【问题标题】:Auto add or update a custom fee via admin edit orders in WooCommerce通过 WooCommerce 中的管理员编辑订单自动添加或更新自定义费用
【发布时间】:2021-04-15 08:19:06
【问题描述】:

我们有一种特殊情况,我们会在收到订单后向客户开具付款发票,而不是让他们在结账时付款。运费是手动计算并添加到订单中的,然后我们会在总额中添加 3% 的信用卡费用。

为了自动化这个过程,我创建了一个脚本,在通过后端设置运费后计算 3% 的费用,并自动将此费用项目添加到订单中。这在我们添加运费并单击保存/重新计算第一次时间时有效。

add_action( 'woocommerce_order_after_calculate_totals', "custom_order_after_calculate_totals", 10, 2);
function custom_order_after_calculate_totals($and_taxes, $order) {

    if ( did_action( 'woocommerce_order_after_calculate_totals' ) >= 2 )
    return;

    if ( is_admin() && ! defined( 'DOING_AJAX' ) )
        return;

    $percentage = 0.03;
    $total = $order->get_total();
    $surcharge = $total * $percentage;
    $feeArray = array(
        'name' => '3% CC Fee',
        'amount' =>  wc_format_decimal($surcharge),
        'taxable' => false,
        'tax_class' => ''
    );

    //Get fees
    $fees = $order->get_fees();
    if(empty($fees)){
        //Add fee
        $fee_object = (object) wp_parse_args( $feeArray );
        $order->add_fee($fee_object);
    } else {
        //Update fee
        foreach($fees as $item_id => $item_fee){
            if($item_fee->get_name() == "3% CC Fee"){
                $order->update_fee($item_id,$feeArray);
            }
        }
    }
}

如果我们不小心添加了错误的运费并尝试更新它,上面的代码会再次触发并更新费用,但是 $total 不会从更新的运费中获取新订单总额,因此费用不会改变。奇怪的是,如果我尝试删除费用项,则会计算新费用并以正确的费用金额加回。

有人知道我该如何解决这个问题吗?

【问题讨论】:

    标签: php wordpress woocommerce orders fee


    【解决方案1】:

    由于您使用订单总额来计算您的费用,并且您使用的挂钩位于 calculate_totals() 方法内,一旦订单更新,您将始终需要按“重新计算”按钮来获取正确的费用总额和正确的订单总额和正确的金额

    自从 WooCommerce 3 以来,您的代码已经过时并且有点过时并出现一些错误……例如,add_fee()update_fee() 方法已被弃用并被其他一些方法取代。

    改用以下内容:

    add_action( 'woocommerce_order_after_calculate_totals', "custom_order_after_calculate_totals", 10, 2 );
    function custom_order_after_calculate_totals( $and_taxes, $order ) {
        if ( did_action( 'woocommerce_order_after_calculate_totals' ) >= 2 )
            return;
    
        $percentage = 0.03; // Fee percentage
    
        $fee_data   = array(
            'name'       => __('3% CC Fee'),
            'amount'     => wc_format_decimal( $order->get_total() * $percentage ),
            'tax_status' => 'none',
            'tax_class'  => ''
        );
    
        $fee_items  = $order->get_fees(); // Get fees
    
        // Add fee
        if( empty($fee_items) ){
            $item = new WC_Order_Item_Fee(); // Get an empty instance object
    
            $item->set_name( $fee_data['name'] );
            $item->set_amount( $fee_data['amount'] );
            $item->set_tax_class($fee_data['tax_class']);
            $item->set_tax_status($fee_data['tax_status']);
            $item->set_total($fee_data['amount']);
    
            $order->add_item( $item );
            $item->save(); // (optional) to be sure
        }
        // Update fee
        else {
            foreach ( $fee_items as $item_id => $item ) {
                if( $item->get_name() === $fee_data['name'] ) {
                    $item->set_amount($fee_data['amount']);
                    $item->set_tax_class($fee_data['tax_class']);
                    $item->set_tax_status($fee_data['tax_status']);
                    $item->set_total($fee_data['amount']);
                    $item->save();
                }
            }
        }
    }
    

    代码进入活动子主题(或活动主题)的functions.php 文件中。经过测试并且可以工作。

    一旦订单得到更新并且按下重新计算按钮后 (以获得正确的订单总数)自动添加和更新费用都会很好地工作。

    相关:Add a fee to an order programmatically in Woocommerce 3


    更新

    现在,如果由于任何原因无法正常工作,您应该删除相关项目以进行更新并添加一个新项目,如下所示:

    add_action( 'woocommerce_order_after_calculate_totals', "custom_order_after_calculate_totals", 10, 2 );
    function custom_order_after_calculate_totals( $and_taxes, $order ) {
        if ( did_action( 'woocommerce_order_after_calculate_totals' ) >= 2 )
            return;
    
        $percentage = 0.03; // Fee percentage
    
        $fee_data   = array(
            'name'       => __('3% CC Fee'),
            'amount'     => wc_format_decimal( $order->get_total() * $percentage ),
            'tax_status' => 'none',
            'tax_class'  => ''
        );
    
        $fee_items  = $order->get_fees(); // Get fees
    
        // Add fee
        if( empty($fee_items) ){
            $item = new WC_Order_Item_Fee(); // Get an empty instance object
    
            $item->set_name( $fee_data['name'] );
            $item->set_amount( $fee_data['amount'] );
            $item->set_tax_class($fee_data['tax_class']);
            $item->set_tax_status($fee_data['tax_status']);
            $item->set_total($fee_data['amount']);
    
            $order->add_item( $item );
            $item->save(); // (optional) to be sure
        }
        // Update fee
        else {
            foreach ( $fee_items as $item_id => $item ) {
                if( $item->get_name() === $fee_data['name'] ) {
                    $item->remove_item( $item_id ); // Remove the item
    
                    $item = new WC_Order_Item_Fee(); // Get an empty instance object
    
                    $item->set_name( $fee_data['name'] );
                    $item->set_amount( $fee_data['amount'] );
                    $item->set_tax_class($fee_data['tax_class']);
                    $item->set_tax_status($fee_data['tax_status']);
                    $item->set_total($fee_data['amount']);
    
                    $order->add_item( $item );
                    $item->save(); // (optional) to be sure
                }
            }
        }
    }
    

    【讨论】:

    • 我看到那些旧方法已被弃用,但无法弄清楚如何以更新的方式执行此操作,因此感谢您对此以及有关钩子的解释。我更新了代码,但问题仍然存在。我更新了运费并点击保存。然后单击更新。然后单击重新计算。手续费还是一样的。更新费用的唯一方法是删除费用并让它自动重新生成。
    • @ZeroNine 抱歉,我提供的代码没有这种行为,使用的是 Storefront 主题的最后一个 WooCommerce 版本。因此,在您的情况下还有其他一些问题。它可以是插件、您的主题或您制作的其他一些自定义代码。
    • @ZeroNine 我已经为你添加了一个更新,删除要更新的项目,然后添加更新的项目……试试看。如果这个答案回答了你的问题,你可以请accept回答,如果你喜欢/想要你也可以请upvote回答,谢谢。
    猜你喜欢
    • 1970-01-01
    • 2018-11-24
    • 2018-07-17
    • 2021-01-18
    • 2019-01-14
    • 1970-01-01
    • 2020-08-24
    • 2021-04-15
    • 1970-01-01
    相关资源
    最近更新 更多