如何修改WooCommerce代码实现单个商品运费单独计算
修改WooCommerce运费计算函数以单独计算单个商品运费
Great question! Your approach of backing up the current cart, temporarily clearing it to calculate shipping for just the target product, then restoring the original cart is spot-on. Here's the modified get_shipping_text function that implements this logic, with key steps commented for clarity:
/* function for calculate shipping */ public function get_shipping_text($shipping_method, $country) { global $woocommerce, $post; $returnResponse = array(); // 1. 备份原购物车状态及用户地址信息 $original_cart = WC()->cart->get_cart(); $original_shipping_address = WC()->customer->get_shipping(); $original_billing_address = WC()->customer->get_billing(); try { // 2. 临时清空购物车,确保仅计算目标商品的运费 WC()->cart->empty_cart(); // 3. 设置指定国家,保证运费计算基于正确的区域规则 WC()->customer->set_shipping_country($country); WC()->customer->set_billing_country($country); WC()->customer->save(); // 4. 将目标商品添加到临时购物车 $product_id = sanitize_text_field($_POST["product_id"]); $qty = (isset($_POST['current_qty']) && $_POST['current_qty'] > 0) ? $_POST['current_qty'] : 1; $variation_id = isset($_POST['variation_id']) ? sanitize_text_field($_POST['variation_id']) : 0; if ($variation_id > 0) { WC()->cart->add_to_cart($product_id, $qty, $variation_id); } else { WC()->cart->add_to_cart($product_id, $qty); } // 5. 计算临时购物车的运费 WC_Shortcode_Cart::calculate_shipping(); $packages = WC()->cart->get_shipping_packages(); $packages = WC()->shipping->calculate_shipping($packages); $packages = WC()->shipping->get_packages(); // 6. 处理运费计算结果 wc_clear_notices(); if (isset($packages[0]["rates"][$shipping_method])) { $selectedShipping = $packages[0]["rates"][$shipping_method]; $returnResponse = array( "label" => $selectedShipping->label, "cost" => wc_price(($selectedShipping->cost)*1.24) ); } else { $AllMethod = WC()->shipping->load_shipping_methods(); if (isset($AllMethod[$shipping_method])) { $selectedMethod = $AllMethod[$shipping_method]; $flag = 0; if ($selectedMethod->availability == "including") { foreach ($selectedMethod->countries as $methodcountry) { if ($country == $methodcountry) { $flag = 1; break; } } if ($flag == 0) { $message = $selectedMethod->method_title . " is not available in selected country."; $returnResponse = array("code" => "error", "message" => $message); } } } else { $returnResponse = array("code" => "error", "message" => "Shipping method not found."); } } } catch (Exception $e) { // 捕获异常,避免计算出错时破坏原购物车状态 $returnResponse = array("code" => "error", "message" => "Failed to calculate shipping: " . $e->getMessage()); } finally { // 7. 恢复原购物车及用户地址信息 WC()->cart->set_cart($original_cart); WC()->customer->set_shipping($original_shipping_address); WC()->customer->set_billing($original_billing_address); WC()->customer->save(); // 重新计算原购物车运费,确保前端显示正确 WC_Shortcode_Cart::calculate_shipping(); } return $returnResponse; }
关键修改说明:
- 购物车与地址备份恢复:提前保存原购物车内容和用户地址,最终通过
finally块确保无论计算成功或失败,都能恢复用户的原始购物状态,不影响正常购物流程。 - 临时购物车隔离:清空原购物车后仅添加目标商品,彻底避免原购物车中其他商品对运费计算的干扰。
- 异常处理:通过
try...catch捕获计算过程中的错误,返回友好提示的同时保证原购物车状态不受破坏。 - 区域规则锁定:明确设置用户的配送/账单国家,确保运费计算使用指定区域的物流规则。
- 恢复后重新计算:恢复原购物车后重新计算运费,保证用户前端看到的运费信息与实际购物车状态一致。
内容的提问来源于stack exchange,提问作者user4697086
相关产品推荐
相关产品推荐

