WooCommerce结账时按支付方式设置商品价格问题排查
问题描述
在WooCommerce结账页面,选择支付方式invoice时,需要将商品ID为338991、353754的价格设为0。现有代码能修改商品价格并计算小计,但税费与总计计算错误,WooCommerce未识别到价格变动。
原代码如下:
function update_product_prices_and_totals($cart_object) { if (is_admin() && !defined('DOING_AJAX')) { return; } if (is_checkout() && isset($_POST['payment_method']) && $_POST['payment_method'] === 'invoice') { // Set subtotal, tax, and total to 0 $subtotal = 0; $total = 0; $included_products = array(338991, 353754); // Array of product IDs to include // Loop through the products in the cart foreach ($cart_object->get_cart() as $cart_item_key => $cart_item) { $product_id = $cart_item['product_id']; // Check the product IDs if (in_array($product_id, $included_products)) { // Set the price to 0 $cart_item['data']->set_price(0); // Calculate taxes for this product and subtract from the subtotal $taxes = array_sum($cart_item['line_tax_data']['subtotal']); $subtotal -= $taxes; continue; // Skip the iteration for included products } // Update the subtotal $subtotal += $cart_item['line_subtotal']; } // Update the total $total = $subtotal + $cart_object->get_cart_contents_tax(); // Set the updated subtotal and total $cart_object->subtotal = $subtotal; $cart_object->total = $total; } } add_action('woocommerce_cart_calculate_fees', 'update_product_prices_and_totals', 10, 1);
代码问题分析
- 钩子选择错误:
woocommerce_cart_calculate_fees用于添加/调整购物车费用,不是修改商品价格和重新计算购物车核心数据的合适钩子,直接修改$cart_object的subtotal和total不会触发WooCommerce的税费重算逻辑。 - 支付方式获取不可靠:结账页面切换支付方式是AJAX请求,
$_POST['payment_method']无法稳定获取当前选中的支付方式,应该通过WooCommerce会话存储来读取。 - 未更新购物车项核心数据:修改商品价格后,没有同步更新购物车项的
line_subtotal、line_total以及对应的税费数据,这些是WooCommerce计算总计和税费的基础,直接跳过会导致数据不一致。
修正后的代码
// 存储选中的支付方式到会话 function save_selected_payment_method_to_session() { if (is_checkout() && isset($_POST['payment_method'])) { WC()->session->set('selected_payment_method', sanitize_text_field($_POST['payment_method'])); } } add_action('wp_ajax_update_order_review', 'save_selected_payment_method_to_session'); add_action('wp_ajax_nopriv_update_order_review', 'save_selected_payment_method_to_session'); // 修改指定商品价格并重新计算购物车 function adjust_product_prices_based_on_payment_method($cart) { if (is_admin() && !defined('DOING_AJAX')) return; if (empty($cart->get_cart())) return; // 从会话获取当前选中的支付方式 $selected_payment_method = WC()->session->get('selected_payment_method'); if ($selected_payment_method !== 'invoice') return; $target_product_ids = array(338991, 353754); foreach ($cart->get_cart() as $cart_item_key => $cart_item) { $product_id = $cart_item['product_id']; if (!in_array($product_id, $target_product_ids)) continue; // 设置商品价格为0 $cart_item['data']->set_price(0); // 强制更新购物车项的小计、总计及税费 $cart_item['line_subtotal'] = 0; $cart_item['line_total'] = 0; $cart_item['line_subtotal_tax'] = 0; $cart_item['line_tax'] = 0; $cart_item['line_tax_data'] = array('subtotal' => array(), 'total' => array()); } // 触发购物车重新计算(包括税费) $cart->calculate_totals(); } add_action('woocommerce_before_calculate_totals', 'adjust_product_prices_based_on_payment_method', 20);
修正说明
- 会话存储支付方式:通过
wp_ajax_update_order_review钩子捕获支付方式切换的AJAX请求,将选中的支付方式存入WooCommerce会话,确保在购物车计算时能稳定获取。 - 使用正确钩子:
woocommerce_before_calculate_totals是WooCommerce计算购物车总计前的核心钩子,在这里修改商品价格会自动触发后续的税费和总计重算。 - 同步更新购物车项数据:不仅设置商品价格为0,还手动重置购物车项的小计、总计及税费数据,确保WooCommerce计算时使用正确的数值。
- 强制重算总计:最后调用
$cart->calculate_totals(),确保所有数据重新计算,包括税费和最终总计。
内容的提问来源于stack exchange,提问作者Aykut
相关产品推荐
相关产品推荐

