You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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']);
    }
}

关键修改点说明

  1. 会话存储折扣值:通过init钩子捕获用户提交的折扣参数,存入会话,确保后续所有请求都能获取到该值
  2. 多场景兼容:价格更新时优先从会话读取折扣,同时兼容初始提交的POST参数场景
  3. 避免重复折扣:使用get_regular_price()获取产品原始价格,防止多次触发钩子导致价格无限降低
  4. 会话清理:添加购物车清空时的会话清理逻辑,避免折扣值残留影响后续购物

验证步骤

  1. 选择折扣百分比并添加商品到购物车,检查迷你购物车是否持续显示折扣价
  2. 修改购物车中商品数量,确认价格仍保持折扣后的数值
  3. 进入购物车页面和结算页面,验证价格正确显示折扣价

内容的提问来源于stack exchange,提问作者Miran Urbas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 02:00:44