WooCommerce购物车批量折扣价显示后被覆盖问题求助
WooCommerce批量折扣价格被默认价格覆盖问题修复
问题背景
开发了一款支持用户选择商品数量的批量折扣插件,已实现折扣计算逻辑,但存在以下问题:当添加2件及以上商品时,迷你购物车的折扣价仅短暂显示后就被默认商品价格覆盖,购物车页面和结算页也始终显示默认价格。
现有代码
// Update cart price add_action('woocommerce_before_calculate_totals', 'woo_bq_update_cart_price', 10, 1); function woo_bq_update_cart_price($cart) { if ( is_admin() && ! defined( 'DOING_AJAX' ) ) return; if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 ) return; // Check if the 'woo_bq_selected_percentage' field is set if (isset($_POST['woo_bq_selected_percentage'])) { // Retrieve the selected percentage $selected_percentage = floatval($_POST['woo_bq_selected_percentage']); // Apply the discount to each item in the cart foreach ($cart->get_cart() as $cart_item) { $product_id = $cart_item['product_id']; $product_price = get_post_meta($product_id, '_price', true); $new_price = $product_price - ($product_price * ($selected_percentage / 100)); $cart_item['data']->set_price($new_price); } } /* Logging function woo_bq_log_data($message) { $upload_dir = wp_upload_dir(); $log_file = $upload_dir['basedir'] . '/woo-bq-logs.log'; $log_message = '[' . date('Y-m-d H:i:s') . '] ' . $message . PHP_EOL; file_put_contents($log_file, $log_message, FILE_APPEND | LOCK_EX); } woo_bq_log_data('Form submitted: ' . print_r($_POST, true)); */ }
核心问题分析
当前代码仅在$_POST['woo_bq_selected_percentage']参数存在时才会应用折扣,但WooCommerce的多数场景(比如购物车数量更新、页面刷新、迷你购物车AJAX自动更新)并不会携带这个POST参数。当这些场景触发woocommerce_before_calculate_totals钩子时,因为没有POST值,折扣逻辑不执行,商品价格会被重置为默认值。
修复方案
把用户选中的折扣百分比存储到**用户会话(Session)**中,这样后续所有页面请求和AJAX操作都能读取到这个值,确保折扣逻辑持续生效。
修改后的代码
// 存储选中的折扣百分比到用户会话 add_action('init', 'woo_bq_save_discount_to_session'); function woo_bq_save_discount_to_session() { if (isset($_POST['woo_bq_selected_percentage'])) { // 启动会话(如果未自动启动) if (!session_id()) { session_start(); } $selected_percentage = floatval($_POST['woo_bq_selected_percentage']); // 限制数值范围在0-100之间,避免异常折扣 $_SESSION['woo_bq_selected_percentage'] = max(0, min(100, $selected_percentage)); } } // 更新购物车价格,优先从会话读取折扣值 add_action('woocommerce_before_calculate_totals', 'woo_bq_update_cart_price', 10, 1); function woo_bq_update_cart_price($cart) { if (is_admin() && !defined('DOING_AJAX')) { return; } if (did_action('woocommerce_before_calculate_totals') >= 2) { return; } // 优先从会话读取折扣百分比,兼容初始POST提交场景 $selected_percentage = 0; if (session_id()) { $selected_percentage = isset($_SESSION['woo_bq_selected_percentage']) ? floatval($_SESSION['woo_bq_selected_percentage']) : 0; } elseif (isset($_POST['woo_bq_selected_percentage'])) { $selected_percentage = floatval($_POST['woo_bq_selected_percentage']); } // 仅当折扣大于0时应用 if ($selected_percentage > 0) { foreach ($cart->get_cart() as $cart_item) { $product = $cart_item['data']; // 获取产品原始常规价格,避免多次应用折扣导致价格异常 $original_price = $product->get_regular_price(); $new_price = $original_price - ($original_price * ($selected_percentage / 100)); $product->set_price($new_price); } } } // 可选:清空购物车时清除会话中的折扣值,避免残留 add_action('woocommerce_cart_emptied', 'woo_bq_clear_discount_session'); function woo_bq_clear_discount_session() { if (session_id()) { unset($_SESSION['woo_bq_selected_percentage']); } }
关键修改点说明
- 会话存储折扣值:通过
init钩子捕获用户提交的折扣参数,存入会话,确保后续所有请求都能获取到该值 - 多场景兼容:价格更新时优先从会话读取折扣,同时兼容初始提交的POST参数场景
- 避免重复折扣:使用
get_regular_price()获取产品原始价格,防止多次触发钩子导致价格无限降低 - 会话清理:添加购物车清空时的会话清理逻辑,避免折扣值残留影响后续购物
验证步骤
- 选择折扣百分比并添加商品到购物车,检查迷你购物车是否持续显示折扣价
- 修改购物车中商品数量,确认价格仍保持折扣后的数值
- 进入购物车页面和结算页面,验证价格正确显示折扣价
内容的提问来源于stack exchange,提问作者Miran Urbas
相关产品推荐
相关产品推荐

