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

WooCommerce结账页按支付方式更新总价异常问题求助

WooCommerce支付方式折扣偶尔失效问题解决

问题场景

在WooCommerce结账页实现了根据支付方式(PayPal/信用卡)自动应用折扣的功能,但约20-25%的订单无法触发折扣,跳转至支付页面时显示原价。

现有代码

1. 触发结账更新的前端代码

add_action( 'wp_footer', 'refresh_payment_methods', 20 );
function refresh_payment_methods() {
    ?>
    <script type="text/javascript">
      (function($){
        $( 'form.checkout' ).on( 'change', 'input[name^="payment_method"]', function() {
          $('body').trigger('update_checkout'); 
        });  
      })(jQuery);
    </script>
<?php } ?>

2. 折扣处理的PHP代码

/* APPLY DISCOUNT BASED ON PAYMENT METHOD */ 
add_action('woocommerce_checkout_update_order_review', 'payment_method_discount', 10, 2); 
add_action( 'woocommerce_cart_calculate_fees', 'payment_method_discount', 20, 1 );
function payment_method_discount( $param1, $param2 = null ) {

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

    // 根据钩子类型获取正确的购物车对象
    if ( current_action() === 'woocommerce_cart_calculate_fees' ) {
        $cart_object = $param1;
    } else {
        // 同步支付方式到session
        parse_str($param1, $post_data);
        if ( isset($post_data['payment_method']) ) {
            WC()->session->set('chosen_payment_method', $post_data['payment_method']);
        }
        $cart_object = WC()->cart;
    }

    $payment_method_arr = array('ppcp-gateway' ,'axepta');
    $chosen_payment_method = WC()->session->get('chosen_payment_method'); 
    $percent = 5; // 示例折扣百分比,按需修改

    // 清空现有折扣费用,避免重复累加
    $cart_object->fees_api()->remove_fees();

    if(in_array($chosen_payment_method, $payment_method_arr)) {              
        $total_discount = 0;
        foreach($cart_object->cart_contents as $cart_item_id => $cart_item) {
            $riepilogo = json_decode(stripslashes($cart_item['_dettagli_noleggio']));
            if ( isset($riepilogo->noleggio->prezzo_noleggio) ) {
                // 先计算再格式化,避免精度丢失
                $discount = ($riepilogo->noleggio->prezzo_noleggio / 100) * $percent;
                $total_discount += $discount;

                // 更新购物车项自定义数据
                $riepilogo->noleggio->prezzo_noleggio_scontato = number_format( $riepilogo->noleggio->prezzo_noleggio - $discount, 2, '.','');
                $riepilogo->noleggio->prezzo_totale_scontato = number_format( 
                    $riepilogo->noleggio->prezzo_noleggio_scontato + 
                    $riepilogo->noleggio->prezzo_accessori + 
                    $riepilogo->noleggio->prezzo_assicurazione, 
                    2, '.',''
                );
                $cart_object->cart_contents[$cart_item_id]['_dettagli_noleggio'] = json_encode($riepilogo);
            }
        }
        // 添加总折扣费用
        if ( $total_discount > 0 ) {
            $cart_object->add_fee( 'Sconto pagamento online', -$total_discount );
        }
    }else{
        foreach($cart_object->cart_contents as $cart_item_id => $cart_item) {
            $riepilogo = json_decode(stripslashes($cart_item['_dettagli_noleggio']));
            $riepilogo->noleggio->prezzo_noleggio_scontato = "";
            $riepilogo->noleggio->prezzo_totale = number_format( 
                $riepilogo->noleggio->prezzo_noleggio + 
                $riepilogo->noleggio->prezzo_accessori + 
                $riepilogo->noleggio->prezzo_assicurazione, 
                2,'.',''
            );
            $riepilogo->noleggio->prezzo_totale_scontato = ''; 
            $cart_object->cart_contents[$cart_item_id]['_dettagli_noleggio'] = json_encode($riepilogo);
        }
    }
    // 强制同步购物车数据到session
    WC()->session->set('cart', $cart_object->cart_contents);
}

问题根源分析

  1. 前端事件绑定失效:原代码自执行函数未传入jQuery,部分场景下事件无法触发结账更新。
  2. 钩子参数不匹配:woocommerce_checkout_update_order_review钩子参数为$posted_data,原代码误将其当作购物车对象使用,逻辑混乱。
  3. 精度丢失:提前使用number_format导致小数计算误差,触发金额错误。
  4. 数据未同步:修改购物车项后未主动保存到session,跳转支付时数据未更新。
  5. 费用清理错误:原代码遍历删除fees的方式存在遗漏,未使用官方API。

补充兜底方案(防止前端未触发更新)

添加订单创建时的验证逻辑,确保折扣最终生效:

add_action('woocommerce_checkout_create_order', 'payment_method_discount_order_create', 10, 2);
function payment_method_discount_order_create($order, $data) {
    $payment_method = $order->get_payment_method();
    $payment_method_arr = array('ppcp-gateway' ,'axepta');
    if ( in_array($payment_method, $payment_method_arr) ) {
        $percent = 5; // 同之前的折扣百分比
        $total_discount = 0;
        foreach($order->get_items() as $item) {
            $riepilogo = json_decode(stripslashes($item->get_meta('_dettagli_noleggio')));
            if ( isset($riepilogo->noleggio->prezzo_noleggio) ) {
                $discount = ($riepilogo->noleggio->prezzo_noleggio / 100) * $percent;
                $total_discount += $discount;
            }
        }
        if ( $total_discount > 0 ) {
            $order->add_fee('Sconto pagamento online', -$total_discount);
        }
    }
}

优化建议

  • 使用WC_Cart::set_cart_contents_hash()更新购物车哈希,确保页面自动重新渲染。
  • 若折扣比例固定,可改用WooCommerce优惠券功能自动应用/移除,更符合平台规范。
  • 前端添加加载状态,防止用户在结账更新完成前跳转支付。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 11:30:55