WooCommerce结账页自定义优惠券自动应用异常问题求助
问题描述
需求:当结账页的billing_business_client和billing_detailer两个复选框同时勾选时,自动应用优惠券代码detailer;取消任意一个复选框时,移除该优惠券。
当前问题:
- 加载结账页时,若复选框已勾选,优惠券虽已应用,但订单总计计算错误
- 只有切换支付方式后,优惠券才会正常生效
期望效果:
- 页面初始加载时,若复选框已勾选,优惠券正确应用且总计计算无误
- 修改复选框状态时,无需切换支付方式,优惠券立即生效且总计正确
原代码问题分析
- 使用
woocommerce_cart_calculate_fees钩子并在其中调用WC()->cart->calculate_totals(),会触发循环计算,导致总计混乱 - 通过
WC()->checkout()->get_value('post_data')解析字段值的方式不可靠,初始加载时无法正确获取复选框状态 - 多余的"最高优惠券"逻辑偏离需求,需求是应用指定优惠券
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 } }
代码说明
woocommerce_cart_loaded_from_session钩子:在购物车从会话加载时触发,用于处理页面初始加载时的优惠券逻辑,直接通过WC()->checkout->get_value()获取复选框的持久化值woocommerce_checkout_update_order_review钩子:在结账页字段通过AJAX更新时触发,解析POST数据获取最新的复选框状态,处理优惠券的添加/移除,并重新计算总计- 前端脚本:监听两个复选框的变更事件,触发结账页的AJAX更新,确保状态变更后立即同步优惠券和总计
- 移除了原代码中多余的"最高优惠券"逻辑,直接针对需求中的指定优惠券
detailer进行处理,避免逻辑混淆
内容的提问来源于stack exchange,提问作者Julian Laibach
相关产品推荐
相关产品推荐

