WooCommerce实现运费超350美元自动应用优惠券的代码问题
解决方案
问题分析
- 无限弹窗循环:
woocommerce_package_rates钩子会在购物车、结算页多次触发(比如更新商品、刷新页面),直接在钩子内输出JS会导致重复执行,引发无限弹窗;同时直接输出JS会破坏页面HTML结构,引发更多意外问题。 - 缺失全运费判断逻辑:原代码仅逐个检查运费,未实现“所有运费选项均超过350美元”的判断逻辑。
修正后的代码
// 自动应用/移除350美元免运费优惠券 add_action('woocommerce_before_calculate_totals', 'auto_apply_350_shipping_coupon', 20); function auto_apply_350_shipping_coupon($cart) { if (is_admin() && !defined('DOING_AJAX')) return; if (did_action('woocommerce_before_calculate_totals') >= 2) return; $coupon_code = '350-shipping'; $all_rates_over_350 = true; // 获取当前包裹的运费选项 if ($cart->get_shipping_packages()) { foreach ($cart->get_shipping_packages() as $package) { $shipping_rates = WC()->session->get('shipping_for_package_' . $package['package_key']); if ($shipping_rates && !empty($shipping_rates['rates'])) { foreach ($shipping_rates['rates'] as $rate) { // 检查当前运费是否超过350美元,只要有一个不满足就标记为false if ($rate->cost <= 350) { $all_rates_over_350 = false; break 2; // 跳出两层循环,无需继续检查 } } } } } // 应用/移除优惠券逻辑 $coupon_applied = in_array($coupon_code, $cart->get_applied_coupons()); if ($all_rates_over_350 && !$coupon_applied) { $cart->apply_coupon($coupon_code); } elseif (!$all_rates_over_350 && $coupon_applied) { $cart->remove_coupon($coupon_code); } } // 确保运费更新时重新计算优惠券状态 add_filter('woocommerce_package_rates', 'refresh_coupon_on_shipping_change', 100, 2); function refresh_coupon_on_shipping_change($rates, $package) { WC()->cart->calculate_totals(); return $rates; }
代码说明
- 解决无限弹窗:完全移除前端JS弹窗,改用PHP后端逻辑处理优惠券的自动应用/移除,从根源避免重复执行问题。
- 全运费判断:通过
$all_rates_over_350标志变量,遍历所有运费选项,只要存在任意一个运费≤350美元,就判定不满足免运费条件。 - 动态调整优惠券:在
woocommerce_before_calculate_totals钩子中执行,当购物车内容、运费选项变化时,自动检查并调整优惠券状态——满足条件则添加,不满足则移除。 - 插件兼容性:适配FedEx Shipping和WWE LTL Quotes插件的动态运费计算,确保运费更新时同步刷新优惠券状态。
注意事项
- 确保优惠券
350-shipping已在WooCommerce后台创建,且设置为对应免运费规则。 - 将代码添加到主题的
functions.php文件,或使用自定义代码插件(如Code Snippets),避免主题更新丢失代码。 - 测试时清空购物车缓存,或刷新购物车/结算页,确保逻辑正常生效。
内容的提问来源于stack exchange,提问作者user77619
相关产品推荐
相关产品推荐

