WooCommerce单品页通过AJAX实时加载阶梯折扣价格方案咨询
实现WooCommerce可变产品数量变化时AJAX自动更新阶梯折扣价格
问题背景
搭建WooCommerce网店时,为可变产品设置了基于购买数量的阶梯折扣(例:0-10件单价20欧元,11-20件单价19欧元),已通过woocommerce_product_variation_get_price过滤器实现折扣,页面刷新后生效,但希望在单品页修改购买数量时,前端价格能通过AJAX自动更新,无需刷新页面。
原价格修改代码:
add_filter('woocommerce_product_variation_get_price', 'ga_change_product_price', 10, 2); function ga_change_product_price($price, $product) { $current_user_id = get_current_user_id(); $current_user_customer_group = get_user_meta($current_user_id, 'customer_group')[0]; $current_variation_id = $product->get_id(); $parent_id = $product->get_parent_id(); $cart = WC()->cart->get_cart(); // Iterate over the custom price rows if (have_rows('custom_prices', $parent_id)) : while (have_rows('custom_prices', $parent_id)) : the_row(); $variation_id = get_sub_field('variation_id'); $customer_id = get_sub_field('customer_id'); $customer_group = get_sub_field('customer_group'); $min_qty = get_sub_field('min_qty'); $max_qty = get_sub_field('max_qty'); // If customer discount && graduated discount if ($variation_id == $current_variation_id && $customer_id == $current_user_id && !empty($min_qty) && !empty($max_qty)) { $cart_qty = 0; // Check the number of items in the cart of this specific variation id foreach ($cart as $cart_item) { $cart_item_variation_id = $cart_item['variation_id']; if ($cart_item_variation_id == $variation_id) { $cart_qty = $cart_item['quantity']; } } if ($cart_qty >= $min_qty && $cart_qty <= $max_qty) { $price = get_sub_field('price'); } } // If customer discount && no graduated discount else if ($variation_id == $current_variation_id && $customer_id == $current_user_id) { $price = get_sub_field('price'); } // If group discount && graduated discount else if ($variation_id == $current_variation_id && $customer_group == $current_user_customer_group && !empty($min_qty) && !empty($max_qty)) { $cart_qty = 0; // Check the number of items in the cart of this specific variation id foreach ($cart as $cart_item) { $cart_item_variation_id = $cart_item['variation_id']; if ($cart_item_variation_id == $variation_id) { $cart_qty = $cart_item['quantity']; } } if ($cart_qty >= $min_qty && $cart_qty <= $max_qty) { $price = get_sub_field('price'); } } // If group discount && no graduated discount else if ($variation_id == $current_variation_id && $customer_group == $current_user_customer_group) { $price = get_sub_field('price'); } endwhile; endif; return $price; }
解决方案
1. 调整价格计算逻辑,支持传入自定义数量
原代码依赖购物车中的数量,但单品页修改数量时还未加入购物车,因此修改函数逻辑,允许传入外部数量参数,同时兼容原有过滤器调用:
// 保留原过滤器,兼容购物车等原有场景 add_filter('woocommerce_product_variation_get_price', 'ga_change_product_price', 10, 2); // 新增独立计算函数,供AJAX调用 function ga_calculate_variation_price($variation_id, $qty = 1) { $product = wc_get_product($variation_id); if (!$product || !$product->is_type('variation')) { return false; } $current_user_id = get_current_user_id(); $current_user_customer_group = get_user_meta($current_user_id, 'customer_group')[0]; $parent_id = $product->get_parent_id(); $price = $product->get_regular_price(); // 默认取产品原价 // 复用原折扣规则,替换购物车数量为传入的自定义数量 if (have_rows('custom_prices', $parent_id)) : while (have_rows('custom_prices', $parent_id)) : the_row(); $variation_id_field = get_sub_field('variation_id'); $customer_id = get_sub_field('customer_id'); $customer_group = get_sub_field('customer_group'); $min_qty = get_sub_field('min_qty'); $max_qty = get_sub_field('max_qty'); // 客户专属阶梯折扣 if ($variation_id_field == $variation_id && $customer_id == $current_user_id && !empty($min_qty) && !empty($max_qty)) { if ($qty >= $min_qty && $qty <= $max_qty) { $price = get_sub_field('price'); } } // 客户专属无阶梯折扣 else if ($variation_id_field == $variation_id && $customer_id == $current_user_id) { $price = get_sub_field('price'); } // 客户组阶梯折扣 else if ($variation_id_field == $variation_id && $customer_group == $current_user_customer_group && !empty($min_qty) && !empty($max_qty)) { if ($qty >= $min_qty && $qty <= $max_qty) { $price = get_sub_field('price'); } } // 客户组无阶梯折扣 else if ($variation_id_field == $variation_id && $customer_group == $current_user_customer_group) { $price = get_sub_field('price'); } endwhile; endif; return wc_price($price); // 返回带货币格式的价格 } // 原过滤器函数调用新增的计算逻辑,兼容购物车场景 function ga_change_product_price($price, $product) { $cart_qty = 0; $variation_id = $product->get_id(); $cart = WC()->cart->get_cart(); // 获取购物车中该变体的数量 foreach ($cart as $cart_item) { if ($cart_item['variation_id'] == $variation_id) { $cart_qty = $cart_item['quantity']; break; } } // 调用计算函数,购物车无该商品时默认传1 $calculated_price = ga_calculate_variation_price($variation_id, $cart_qty ?: 1); return $calculated_price ? strip_tags($calculated_price) : $price; }
2. 注册AJAX端点
添加WooCommerce AJAX接口,供前端请求计算价格:
add_action('wp_ajax_get_variation_discounted_price', 'ga_ajax_get_variation_price'); add_action('wp_ajax_nopriv_get_variation_discounted_price', 'ga_ajax_get_variation_price'); function ga_ajax_get_variation_price() { // 验证请求参数 if (!isset($_POST['variation_id']) || !isset($_POST['qty'])) { wp_send_json_error('参数缺失'); } $variation_id = intval($_POST['variation_id']); $qty = intval($_POST['qty']); $price = ga_calculate_variation_price($variation_id, $qty); if ($price) { wp_send_json_success(array('price' => $price)); } else { wp_send_json_error('无法计算价格'); } }
3. 前端JS监听数量变化,触发AJAX更新
在单品页添加JavaScript,监听数量输入框变化,请求AJAX更新价格:
jQuery(document).ready(function($) { // 变体选中后初始化价格监听 $('.variations_form').on('show_variation', function(event, variation) { updatePriceOnQtyChange(variation.variation_id); }); // 绑定数量变化事件 function updatePriceOnQtyChange(variationId) { $('.quantity input.qty').off('change keyup').on('change keyup', function() { var qty = $(this).val(); if (qty < 1) qty = 1; $.ajax({ url: wc_add_to_cart_params.ajax_url, type: 'POST', data: { action: 'get_variation_discounted_price', variation_id: variationId, qty: qty }, beforeSend: function() { $('.woocommerce-variation-price').addClass('loading'); }, success: function(response) { if (response.success) { $('.woocommerce-variation-price').html(response.data.price).removeClass('loading'); } }, error: function() { $('.woocommerce-variation-price').removeClass('loading'); } }); }); } });
注意事项
- 将代码添加到主题的
functions.php文件或自定义插件中 - 测试前清空缓存,避免旧代码干扰
- 若使用自定义主题,需确认价格元素选择器(
.woocommerce-variation-price)与主题匹配,不匹配则修改JS中的选择器
内容的提问来源于stack exchange,提问作者Pieter
相关产品推荐
相关产品推荐

