You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

调用calculate_totals()触发订单总额为0的提前邮件通知如何解决?

解决WooCommerce拆分订单时提前触发邮件与总额计算问题

核心问题分析

拆分订单调用calculate_totals()时,内部会先执行calculate_taxes(true),该方法会自动调用save()——此时订单总额尚未完成计算(显示为0),且会触发订单状态变更的邮件通知;若跳过calculate_taxes()则会导致税费计算错误。

更优解决方案:临时使用草稿状态规避邮件触发

WooCommerce默认不会给草稿(draft)状态的订单发送通知邮件,因此可以通过以下步骤实现无提前邮件的正确计算:

  • 创建新订单时先设置为draft状态,避免计算过程中的save()触发邮件
  • 完成订单项转移、总额与税费计算后,再将订单状态恢复为原订单的目标状态
  • 此时触发的邮件会包含正确的订单总额与税费数据

修改后的代码实现

public static function add_hooks() {
    // 支付确认后拆分订单
    add_action( 'woocommerce_order_status_pending_to_processing', [ __CLASS__, 'split_order' ], 10, 2 );
}

public static function split_order( $order_id, WC_Order $order, $force = null ) {
    $items_to_split = array();
    foreach ( $order->get_items() as $item_id => $item_data ) {
        if ( $item_data->meta_exists( '_SnapshotId' ) ) {
            $items_to_split[ $item_id ] = $item_data;
        }
    }

    if ( count( $items_to_split ) === 0 ) return;

    $target_status = $order->get_status();
    $new_order = wc_create_order();
    $new_order->set_customer_id( $order->get_customer_id() );
    $new_order->set_payment_method( $order->get_payment_method() );
    $new_order->set_created_via( 'split_order' );
    // 临时设置为草稿状态,避免计算时触发邮件
    $new_order->set_status( 'draft' );

    $new_order->set_billing( $order->get_address( 'billing' ) );
    $new_order->set_shipping( $order->get_address( 'shipping' ) );

    // 转移订单项到新订单
    foreach ( $items_to_split as $item_id => $item_data ) {
        /** @var WC_Order_Item_Product $item_data */
        $new_order_item = new WC_Order_Item_Product();
        $data = $item_data->get_data();
        unset( $data['id'] );
        unset( $data['order_id'] );
        $new_order_item->set_props( $data );

        $meta_data = array_map( function ( $n ) {
            return $n->get_data();
        }, $item_data->get_meta_data() );
        foreach ( $meta_data as $meta_data_entry ) {
            $new_order_item->add_meta_data( $meta_data_entry['key'], $meta_data_entry['value'] );
        }

        $new_order->add_item( $new_order_item );
        $order->remove_item( $item_id );
    }

    // 完成计算,此时草稿状态不会触发邮件
    $new_order->calculate_totals();
    $order->calculate_totals();

    // 恢复目标状态,此时触发的邮件包含正确数据
    $new_order->set_status( $target_status );
    $new_order->save();
}

备选方案:临时禁用邮件过滤器

如果草稿状态的方式不适用,还可以通过临时禁用WooCommerce邮件的过滤器实现:

// 计算前禁用所有邮件
add_filter( 'woocommerce_email_enabled', '__return_false' );

// 执行计算
$new_order->calculate_totals();
$order->calculate_totals();

// 恢复邮件功能
remove_filter( 'woocommerce_email_enabled', '__return_false' );

该方案会临时屏蔽所有WooCommerce邮件通知,适合需要严格控制邮件触发时机的场景。

内容的提问来源于stack exchange,提问作者shadryck

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 11:33:24