WooCommerce按class51商品每6件为单位分区域计算自定义运费
WooCommerce 自定义配送运费计算实现方案
原有代码失效核心原因
- 钩子使用错误:
woocommerce_cart_shipping_total是过滤器接口,原代码用add_action挂载,逻辑根本不会触发 - 变量拼写错误:代码末尾返回未定义的
$totals变量,而非计算完成的$total - 逻辑层级错误:仅修改前端显示的运费价格字符串,没有实际修改运费计算内核值,多区域、多商品场景下计算完全失准
- 冗余逻辑:循环内重复调用购物车运费获取方法,对计算无任何帮助
现有配置确认
- 配送类:2个,class41(免运费类)、class51(计费类)
- 配送区域:2个,基础费率配置如下:
- 区域1:class41单件运费0,class51单件运费10美元
- 区域2:class41单件运费0,class51单件运费12美元
- 目标规则:
- 仅class51商品参与运费计算,class41商品全部免运费
- class51商品每6件计为1个计费单位,按区域对应单价收费,不足6件按1个单位算
正确实现代码
将以下代码添加到当前主题的functions.php文件,或自定义代码片段插件中:
add_filter( 'woocommerce_package_rates', 'custom_calc_shipping_cost', 10, 2 ); function custom_calc_shipping_cost( $rates, $package ) { // 指定需要计算运费的配送类ID $target_class_id = 51; // 统计当前配送包裹内目标配送类的商品总数量 $target_qty = 0; foreach ( $package['contents'] as $item ) { $item_class = $item['data']->get_shipping_class_id(); if ( $item_class == $target_class_id ) { $target_qty += $item['quantity']; } } // 遍历当前区域所有可用配送费率,重算运费 foreach ( $rates as $rate_key => $rate ) { // 仅处理统一运费类型,其他配送方式可按需调整判断逻辑 if ( $rate->method_id !== 'flat_rate' ) continue; // 无目标计费商品时,运费直接置0 if ( $target_qty <= 0 ) { $rate->cost = 0; $rate->taxes = []; continue; } // 计算计费单位:每6件为1个单位,向上取整 $charge_units = intdiv( $target_qty + 5, 6 ); // 自动读取当前区域下目标配送类的单件配置价,无需硬编码区域ID $per_unit_price = isset( $rate->cost_options['class_cost_' . $target_class_id] ) ? floatval( $rate->cost_options['class_cost_' . $target_class_id] ) : 0; // 重算运费及对应税费 $final_cost = $charge_units * $per_unit_price; $rate->cost = $final_cost; $rate->taxes = WC_Tax::calc_shipping_tax( $final_cost, WC_Tax::get_shipping_tax_rates() ); } return $rates; }
代码添加完成后,进入WooCommerce-设置-配送页面,点击一次「保存更改」即可刷新配送缓存生效,无需额外操作。
效果验证
按提供的测试场景核对:
- 购买5件class41商品:无class51商品,两个区域运费均为0,符合免运费规则
- 购买2件class41 + 6件class51商品:计费单位为1,区域1运费10美元,区域2运费12美元,符合预期
- 购买2件class41 + 13件class51商品:计费单位为3(13/6向上取整),区域1运费30美元,区域2运费36美元,符合预期
内容的提问来源于stack exchange,提问作者ozoz
相关产品推荐
相关产品推荐

