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

WooCommerce结账页自定义优惠券自动应用异常问题求助

问题描述

需求:当结账页的billing_business_client和billing_detailer两个复选框同时勾选时,自动应用优惠券代码detailer;取消任意一个复选框时,移除该优惠券。

当前问题:

  • 加载结账页时,若复选框已勾选,优惠券虽已应用,但订单总计计算错误
  • 只有切换支付方式后,优惠券才会正常生效

期望效果:

  • 页面初始加载时,若复选框已勾选,优惠券正确应用且总计计算无误
  • 修改复选框状态时,无需切换支付方式,优惠券立即生效且总计正确

原代码问题分析

  1. 使用woocommerce_cart_calculate_fees钩子并在其中调用WC()->cart->calculate_totals(),会触发循环计算,导致总计混乱
  2. 通过WC()->checkout()->get_value('post_data')解析字段值的方式不可靠,初始加载时无法正确获取复选框状态
  3. 多余的"最高优惠券"逻辑偏离需求,需求是应用指定优惠券detailer,无需遍历已应用优惠券找最高金额

修正后的代码

// 处理页面初始加载时的优惠券应用
add_action('woocommerce_cart_loaded_from_session', 'apply_coupon_on_checkout_load');
function apply_coupon_on_checkout_load() {
    if (is_checkout() && !is_wc_endpoint_url()) {
        $business_client = WC()->checkout->get_value('billing_business_client');
        $detailer = WC()->checkout->get_value('billing_detailer');
        $coupon_code = 'detailer';

        // 两个复选框都勾选时应用优惠券
        if ($business_client && $detailer) {
            if (!in_array($coupon_code, WC()->cart->get_applied_coupons())) {
                WC()->cart->apply_coupon($coupon_code);
            }
        } else {
            // 取消任意复选框时移除优惠券
            if (in_array($coupon_code, WC()->cart->get_applied_coupons())) {
                WC()->cart->remove_coupon($coupon_code);
            }
        }
    }
}

// 处理复选框变更时的优惠券应用(AJAX更新结账)
add_action('woocommerce_checkout_update_order_review', 'apply_coupon_on_checkout_field_change');
function apply_coupon_on_checkout_field_change($posted_data) {
    parse_str($posted_data, $post_data);
    $coupon_code = 'detailer';

    if (isset($post_data['billing_business_client']) && isset($post_data['billing_detailer'])) {
        $business_client = $post_data['billing_business_client'];
        $detailer = $post_data['billing_detailer'];

        if ($business_client && $detailer) {
            if (!in_array($coupon_code, WC()->cart->get_applied_coupons())) {
                WC()->cart->apply_coupon($coupon_code);
            }
        } else {
            if (in_array($coupon_code, WC()->cart->get_applied_coupons())) {
                WC()->cart->remove_coupon($coupon_code);
            }
        }

        // 重新计算总计(这里不会触发循环,因为是在AJAX更新钩子中)
        WC()->cart->calculate_totals();
    }
}

// 监听复选框变更,触发结账更新
add_action('wp_footer', 'woocommerce_checkout_field_change_script');
function woocommerce_checkout_field_change_script() {
    if (is_checkout() && !is_wc_endpoint_url()) {
    ?>
    <script type="text/javascript">
        jQuery(function($){
            // 监听两个复选框的变更事件
            $('form.woocommerce-checkout').on('change', 'input[name="billing_business_client"], input[name="billing_detailer"]', function(){
                // 触发结账更新,触发上面的woocommerce_checkout_update_order_review钩子
                $('body').trigger('update_checkout');
            });
        });
    </script>
    <?php
    }
}

代码说明

  1. woocommerce_cart_loaded_from_session钩子:在购物车从会话加载时触发,用于处理页面初始加载时的优惠券逻辑,直接通过WC()->checkout->get_value()获取复选框的持久化值
  2. woocommerce_checkout_update_order_review钩子:在结账页字段通过AJAX更新时触发,解析POST数据获取最新的复选框状态,处理优惠券的添加/移除,并重新计算总计
  3. 前端脚本:监听两个复选框的变更事件,触发结账页的AJAX更新,确保状态变更后立即同步优惠券和总计
  4. 移除了原代码中多余的"最高优惠券"逻辑,直接针对需求中的指定优惠券detailer进行处理,避免逻辑混淆

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 23:41:30