WooCommerce中代码添加指定商品后设置价格为0的问题
解决WooCommerce Ajax添加商品后无法设置自定义价格的问题
问题核心原因
- Ajax请求并行冲突:两个Ajax请求同时发起,设置价格的请求可能在商品尚未添加到购物车时执行,导致找不到目标商品。
- 钩子逻辑混用错误:
custom_set_cart_item_price同时绑定了Ajax钩子和woocommerce_before_calculate_totals,但Ajax调用时不会传入$cart对象,函数无法正常处理购物车数据。 - 价格修改方式不符合规范:直接修改
$cart->cart_contents不是WooCommerce推荐的价格修改方式,且未触发购物车重新计算流程。
修复方案
1. 调整JavaScript代码:合并请求避免并行问题
将自定义价格参数直接传入添加商品的Ajax请求,确保商品添加与价格设置逻辑同步:
<script> const selectedProductId = getProdVal(randomDegree); const isProductInCart = isProductAlreadyInCart(selectedProductId); if (!productAdded && !isProductInCart) { jQuery.ajax({ url: <?php echo json_encode(admin_url('admin-ajax.php')) ?>, type: 'POST', data: { action: 'add_product_to_cart_with_custom_price', product_id: selectedProductId, custom_price: 0.00 // 传递要设置的自定义价格 }, success: function(response) { console.log(response); productAdded = true; spinBtn.disabled = false; }, error: function(error) { console.error(error); spinBtn.disabled = false; } }); } </script>
2. 修改PHP代码:使用WooCommerce官方钩子处理价格
移除错误的Ajax绑定,改用WooCommerce专用钩子存储并应用自定义价格:
// 处理带自定义价格的商品添加请求 function add_product_to_cart_with_custom_price() { if (isset($_POST['product_id']) && isset($_POST['custom_price'])) { $product_id = intval($_POST['product_id']); $custom_price = floatval($_POST['custom_price']); if (!in_array($product_id, get_product_ids_from_cart())) { // 添加商品时携带自定义价格数据 WC()->cart->add_to_cart($product_id, 1, 0, [], ['custom_price' => $custom_price]); } echo json_encode(['success' => true, 'message' => '商品已添加到购物车并设置自定义价格']); } else { echo json_encode(['success' => false, 'message' => '商品ID或自定义价格缺失']); } exit; } add_action('wp_ajax_add_product_to_cart_with_custom_price', 'add_product_to_cart_with_custom_price'); add_action('wp_ajax_nopriv_add_product_to_cart_with_custom_price', 'add_product_to_cart_with_custom_price'); // 存储自定义价格到购物车项数据 function save_custom_cart_item_data($cart_item_data, $product_id, $variation_id) { if (isset($_POST['custom_price'])) { $cart_item_data['custom_price'] = floatval($_POST['custom_price']); // 添加唯一标识,确保WooCommerce识别为独立购物车项(避免同商品价格冲突) $cart_item_data['unique_key'] = md5(microtime() . rand()); } return $cart_item_data; } add_filter('woocommerce_add_cart_item_data', 'save_custom_cart_item_data', 10, 3); // 在购物车计算总价前应用自定义价格 function apply_custom_cart_item_price($cart) { // 后台非Ajax场景跳过 if (is_admin() && !defined('DOING_AJAX')) return; foreach ($cart->get_cart() as $cart_item_key => $cart_item) { if (isset($cart_item['custom_price'])) { $cart_item['data']->set_price($cart_item['custom_price']); } } } add_action('woocommerce_before_calculate_totals', 'apply_custom_cart_item_price');
3. 备选方案:保留双Ajax请求的顺序控制
如果必须分开两个请求,需确保设置价格的请求在商品添加成功后执行:
// 修改后的JS代码 <script> const selectedProductId = getProdVal(randomDegree); const isProductInCart = isProductAlreadyInCart(selectedProductId); if (!productAdded && !isProductInCart) { jQuery.ajax({ url: <?php echo json_encode(admin_url('admin-ajax.php')) ?>, type: 'POST', data: { action: 'add_product_to_cart', product_id: selectedProductId, }, success: function(response) { console.log(response); productAdded = true; spinBtn.disabled = false; // 商品添加成功后再发起设置价格的请求 jQuery.ajax({ url: <?php echo json_encode(admin_url('admin-ajax.php')) ?>, type: 'POST', data: { action: 'set_cart_item_price', product_id: selectedProductId, custom_price: 0.00 }, success: function(res) { console.log(res); }, error: function(err) { console.error(err); } }); }, error: function(error) { console.error(error); spinBtn.disabled = false; } }); } </script>
对应的PHP设置价格函数:
function set_cart_item_price() { if (isset($_POST['product_id']) && isset($_POST['custom_price'])) { $product_id = intval($_POST['product_id']); $custom_price = floatval($_POST['custom_price']); foreach (WC()->cart->get_cart() as $cart_item_key => $cart_item) { if ($cart_item['product_id'] === $product_id) { $cart_item['data']->set_price($custom_price); // 更新购物车会话 WC()->cart->set_session(); break; } } echo json_encode(['success' => true, 'message' => '价格已更新']); } else { echo json_encode(['success' => false, 'message' => '参数缺失']); } exit; } add_action('wp_ajax_set_cart_item_price', 'set_cart_item_price'); add_action('wp_ajax_nopriv_set_cart_item_price', 'set_cart_item_price');
内容的提问来源于stack exchange,提问作者Tom Hank
相关产品推荐
相关产品推荐

