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

如何实现适配多场景的WooCommerce支付关联费/折扣功能?

通用WooCommerce支付类型手续费/折扣实现方案

问题分析

原代码存在以下几个导致场景覆盖不全的问题:

  • 重复注册了woocommerce_cart_calculate_fees钩子,可能引发执行冲突
  • 获取选中支付方式时,session键名错误(多了美元符号$)
  • JS仅监听常规结账表单的支付方式切换,未覆盖押金插件等自定义结账场景
  • 钩子优先级默认10,可能被其他插件的同钩子代码覆盖

改进后的通用代码

PHP部分

// 注册费用计算钩子,提高优先级确保优先执行
add_action( 'woocommerce_cart_calculate_fees', 'ts_add_payment_based_discount', 20, 1 );
function ts_add_payment_based_discount( $cart ) {
    // 后台非AJAX请求直接返回
    if ( is_admin() && ! defined( 'DOING_AJAX' ) ) return;

    // 目标支付方式(替换为你的支付方式slug)
    $target_payment_method = 'redsys';
    // 折扣百分比(正数为折扣,负数为手续费)
    $percent = 5.435;

    // 正确获取选中的支付方式
    $chosen_payment_method = WC()->session->get( 'chosen_payment_method' );

    // 仅当选中目标支付方式时执行计算
    if ( $target_payment_method === $chosen_payment_method ) {
        // 使用cart->get_subtotal()确保兼容更多场景(包括押金插件的金额计算)
        $cart_total = $cart->get_subtotal();
        $discount = round( ( $cart_total / 100 ) * $percent, 2 );

        // 添加折扣(负数为折扣,正数为手续费)
        $cart->add_fee( __( "Discount International Charge" ), -$discount, false );
    }
}

// 触发结账更新的钩子,使用更通用的位置
add_action( 'woocommerce_before_checkout_form', 'ts_refresh_checkout_on_payment_change' );
function ts_refresh_checkout_on_payment_change() {
    ?>
    <script type="text/javascript">
        (function($){
            // 监听所有支付方式单选框的变化,不限于常规结账表单
            $( document.body ).on( 'change', 'input[name^="payment_method"]', function() {
                // 触发结账更新事件,兼容WooCommerce核心及多数插件
                $( document.body ).trigger( 'update_checkout' );
            });
        })(jQuery);
    </script>
    <?php
}

关键优化点

  • 钩子优先级:将woocommerce_cart_calculate_fees的优先级设为20,确保在多数插件之后执行,避免被覆盖
  • 支付方式获取:修正session键名错误,使用正确的chosen_payment_method
  • 金额计算:使用$cart->get_subtotal()替代subtotal_ex_tax,兼容更多自定义结账场景(如押金插件的部分金额计算)
  • JS监听范围:将监听对象从form.checkout改为document.body,覆盖所有页面中的支付方式切换事件
  • 移除重复钩子:删除重复的add_action注册,避免函数重复执行

额外适配建议

如果押金插件使用了独立的结账流程或自定义session存储,可尝试以下补充操作:

  • 检查押金插件是否支持woocommerce_cart_calculate_fees钩子,若不支持,可查看插件文档寻找对应的费用计算钩子
  • 若支付方式在押金场景下存储在其他位置,可通过$_POST['payment_method']或插件提供的API获取当前选中的支付方式

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 06:25:27