
本文介绍如何在 woocommerce 中实现基于购物车小计(subtotal)的三级运费策略:订单小于 350 元仅支持自提;350–999.99 元收取 35 元配送费;1000 元及以上自动免邮。
本文介绍如何在 woocommerce 中实现基于购物车小计(subtotal)的三级运费策略:订单小于 350 元仅支持自提;350–999.99 元收取 35 元配送费;1000 元及以上自动免邮。
要实现灵活、精准的运费逻辑,WooCommerce 原生的“运费规则”(如基于重量、地区或总额)往往不够用。本方案采用代码级定制方式,通过钩子 woocommerce_package_rates 动态重写运费选项,无需插件依赖,轻量高效且完全可控。
✅ 实现原理
核心思路是:仅配置一个“Flat Rate(统一运费)”运输方式(后台设置运费为 0),然后利用 woocommerce_package_rates 过滤器,在结账前实时读取当前购物车小计(WC()->cart->subtotal),按业务规则动态修改该运费项的成本(cost)与显示名称(label)。系统会自动隐藏不满足条件的运输方式——由于只注册了一个运费方法,我们只需控制其可见性与数值即可达成多档策略。
? 完整代码(推荐添加至子主题的 functions.php)
add_filter( 'woocommerce_package_rates', 'dynamic_shipping_based_on_subtotal', 10, 2 );
function dynamic_shipping_based_on_subtotal( $rates, $package ) {
// 确保在前台且购物车可用
if ( ! is_admin() && WC()->cart && WC()->cart->get_cart_contents_count() > 0 ) {
$subtotal = WC()->cart->subtotal;
foreach ( $rates as $key => $rate ) {
if ( $subtotal < 350 ) {
// 小于 350:仅显示“自提”,运费为 0
$rates[$key]->cost = 0;
$rates[$key]->label = 'Pick Up Only';
// 可选:移除其他运输方式(若存在多个,此处可 unset)
} elseif ( $subtotal >= 350 && $subtotal < 1000 ) {
// 350–999.99:收取 35 元配送费
$rates[$key]->cost = 35;
$rates[$key]->label = 'Shipping - Delivery Fee';
} else {
// ≥ 1000:免费配送
$rates[$key]->cost = 0;
$rates[$key]->label = 'Free Shipping (Order over R1000)';
}
}
}
return $rates;
}⚠️ 关键注意事项
-
务必使用子主题:直接修改父主题
functions.php在更新后将丢失所有改动; - 禁用缓存干扰:部分对象缓存(如 Redis)或页面缓存插件可能缓存运费结果,请在测试阶段临时停用;
-
货币单位一致性:示例中金额单位为“R”(南非兰特),请根据实际币种调整文案与数值(如
¥或$),但逻辑数值无需更改; -
小计 vs 总价:本方案使用
WC()->cart->subtotal(不含运费与税费的纯商品金额),符合常见业务场景;若需基于“订单总额”(含已加运费),应改用WC()->cart->total并注意循环调用风险; -
多地址/分包场景:该方案默认作用于单包裹(
$package)。如启用多地址配送或复杂分包逻辑,需额外判断$package['contents_cost']等字段。
✅ 效果验证建议
- 清空购物车,分别加入商品使小计为 300 / 600 / 1200;
- 进入结算页 → 查看“Shipping Method”区域,确认仅显示对应档位的选项及正确费用;
- 检查订单确认页与后台订单详情,确保运费记录与前端一致。
此方案简洁可靠,兼顾扩展性与可维护性。如后续需增加地区限制、会员等级折扣运费等,可在同一过滤器中叠加条件判断,无需重构基础逻辑。

















