php 通过WooCommerce中的管理员编辑订单自动添加或更新自定义费用

jfgube3f  于 2023-01-16  发布在  PHP
关注(0)|答案(2)|浏览(145)

我们有一种特殊情况,即我们在收到订单后向客户开具付款发票,而不是让他们在结账时付款。运费是手动计算的,并添加到订单中,然后我们在总计中添加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不会从更新后的运费中获得新的订单总额,因此费用不会改变。奇怪的是,如果我试图删除费用项,则会计算新的费用并将其添加回正确的费用金额。
有人知道我怎么解决这个问题吗?

fgw7neuy

fgw7neuy1#

由于您使用的是订单授权总额来计算费用,并且您使用的钩子位于calculate_totals()方法中,因此一旦订单更新,您将始终需要按"recalculate"(重新计算)按钮以获得正确的费用总额和正确的订单授权总额以及正确的金额
由于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文件中的活动子主题(或活动主题).测试和作品.
一旦订单得到更新和后,按下重新计算按钮*(以获得正确的订单总数)* 自动添加和更新费用都将很好地工作。
相关:在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
            }
        }
    }
}
ktca8awb

ktca8awb2#

    • 更新**:

需要从$order对象中使用remove_item。WC_Order_Item_Fee类中没有remove_item函数。从订单中删除项目后,请调用订单上的save()函数。

$order_fees = reset( $order->get_items('fee') );
        $fee_data   = array(
            'name'       => __( 'Delivery Fee', 'dsfw' ),
            'amount'     => wc_format_decimal( $day_fee + $timeslot_fee ),
        );

        if( !empty( $order_fees ) && $order_fees instanceof WC_Order_Item_Fee ) {
            // update fee

            if( $order_fees->get_name() === $fee_data['name'] ) {
                $order->remove_item( (int)$order_fees->get_id() );
                $order->save();

                $item = new WC_Order_Item_Fee();
                $item->set_name( $fee_data['name'] );
                $item->set_amount( $fee_data['amount'] );
                $item->set_total( $fee_data['amount'] );
                $order->add_item( $item );  
                $item->save();

            }
        } else {
            // add fee
            $item = new WC_Order_Item_Fee();

            $item->set_name( $fee_data['name'] );
            $item->set_amount( $fee_data['amount'] );
            $item->set_total( $fee_data['amount'] );

            $order->add_item( $item );
            $item->save();
        }

    }

相关问题