WooCommerce:部分退款后配送方式未更新的问题排查
WooCommerce 部分退款后未自动切换配送方式的问题修复
问题根源分析
你的代码存在三个核心问题,导致退款后配送方式无法正确更新:
- 订单总额计算错误:原代码通过遍历订单商品计算总额,但WooCommerce中订单商品的数量不会因退款减少(退款为独立记录),因此计算出的仍是原始订单金额,无法准确判断是否低于100欧元阈值。
- 配送项属性缺失:手动创建统一费率配送项时,未设置
instance_id、税费等必要属性,导致配送项无法正常保存或显示。 - 钩子时机与数据同步问题:
woocommerce_order_refunded触发时,退款数据可能尚未完全同步到订单,导致获取的订单状态不准确。
修正后的代码
add_action('woocommerce_after_refund_created', 'adjust_shipping_after_partial_refund', 10, 2); function adjust_shipping_after_partial_refund($refund_id, $order_id) { // 获取最新的订单对象,确保退款数据已同步 $order = wc_get_order($order_id); if (!$order) return; // 计算退款后的实际商品小计(对应免运费判断基准) $remaining_subtotal = $order->get_subtotal() - $order->get_total_refunded_for_item_type('line_item'); // 判断是否需要切换配送方式 if ($remaining_subtotal < 100) { $free_shipping_removed = false; // 移除所有免运费配送项 foreach ($order->get_shipping_methods() as $shipping_item_id => $shipping_item) { if ($shipping_item->get_method_id() === 'free_shipping') { $order->remove_item($shipping_item_id); $free_shipping_removed = true; } } // 仅在移除免运费后添加统一费率配送 if ($free_shipping_removed) { // 获取后台配置的统一费率配送实例 $flat_rate_instance = WC_Shipping_Zones::get_zone_matching_package($order->get_shipping_package())->get_shipping_methods('flat_rate')[0]; // 创建并配置配送项 $shipping_item = new WC_Order_Item_Shipping(); $shipping_item->set_props([ 'method_title' => $flat_rate_instance->get_title(), 'method_id' => $flat_rate_instance->id, 'instance_id' => $flat_rate_instance->instance_id, 'total' => wc_format_decimal(9), // 若后台设置了运费,可替换为$flat_rate_instance->get_option('cost') 'taxes' => WC_Tax::calc_shipping_tax(9, WC_Tax::get_shipping_tax_rates($order->get_shipping_country())) ]); $order->add_item($shipping_item); // 重新计算订单总额并保存 $order->calculate_totals(); $order->set_status($order->get_status()); // 触发数据同步 $order->save(); } } }
关键修正说明
- 更换钩子时机:使用
woocommerce_after_refund_created确保退款数据完全写入订单后再执行调整,避免数据不同步。 - 正确计算剩余金额:通过
get_subtotal()减去退款的商品金额,得到退款后的实际商品小计,符合免运费的判断逻辑。 - 关联后台配送配置:调用后台设置的统一费率实例,而非硬编码创建配送项,保证与站点配置一致。
- 完善税费计算:自动计算配送税费,匹配WooCommerce的税费规则。
- 强制数据同步:添加
set_status()触发订单数据刷新,确保保存后状态及时更新。
额外注意事项
- 若你的免运费判断基准是订单总额(含税费),可将
$remaining_subtotal替换为$order->get_total() - $order->get_total_refunded()。 - 测试时需完成退款操作后刷新订单页面,必要时清除WooCommerce缓存。
内容的提问来源于stack exchange,提问作者Jason Lommelen
相关产品推荐
相关产品推荐

