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

WooCommerce编程添加的自定义优惠手续费无法留存至结账及订单页

问题原因分析

你的代码存在两个核心问题导致优惠无法留存到结账页和订单页:

  1. 钩子挂载时机错误:你仅当URL中存在$_GET['discount']参数时才挂载woocommerce_cart_calculate_fees钩子,但从购物车跳转到结账页时,这个GET参数不会被自动携带,钩子无法触发,优惠也就不会被计算。
  2. 折扣值未持久化:直接依赖临时的GET参数存储折扣值,页面跳转后参数丢失,无法在后续页面读取到折扣信息。
修正后的代码
// 始终挂载钩子,不要用GET参数条件限制
add_action('woocommerce_cart_calculate_fees', 'add_loyalty_discounts');

// 处理GET参数,将折扣值存入会话
add_action('template_redirect', 'save_loyalty_discount_to_session');

function save_loyalty_discount_to_session() {
    if (isset($_GET['discount']) && !empty($_GET['discount']) && is_numeric($_GET['discount'])) {
        // 将折扣值存入WooCommerce会话
        WC()->session->set('loyalty_discount', intval($_GET['discount']));
    }
    // 可选:添加移除折扣的逻辑,比如URL带?remove_discount=1时清空会话
    if (isset($_GET['remove_discount'])) {
        WC()->session->__unset('loyalty_discount');
    }
}

function add_loyalty_discounts(WC_Cart $cart) {
    // 从会话中读取折扣值,而不是直接用GET
    $discount_amount = WC()->session->get('loyalty_discount');
    
    // 如果没有折扣值,直接返回
    if (empty($discount_amount)) {
        return;
    }

    $total_regular = 0;
    // 计算购物车商品原价总和(修正原代码未乘购买数量的问题)
    foreach ($cart->get_cart() as $cart_item_key => $item) {
        $total_regular += $item['data']->get_regular_price() * $item['quantity'];
    }

    $current_user = wp_get_current_user();
    $loyalty_points = get_user_meta($current_user->ID, 'loyalty_points', true);
    $loyalty_points = empty($loyalty_points) ? 0 : intval($loyalty_points);
    // 注释掉硬写的测试值,使用真实用户积分
    // $loyalty_points = 100;

    // 验证条件,失败则清空会话并终止
    if ($total_regular < $discount_amount) {
        wc_add_notice('您的购物金额必须超过€' . $discount_amount . '才能使用忠诚度折扣', 'error');
        WC()->session->__unset('loyalty_discount');
        return;
    }

    if ($loyalty_points < $discount_amount) {
        wc_add_notice('您的忠诚度积分不足以兑换该折扣', 'error');
        WC()->session->__unset('loyalty_discount');
        return;
    }

    // 添加折扣手续费
    $cart->add_fee('忠诚度折扣', -$discount_amount, true);
}

// 确保订单完成后清空会话中的折扣值
add_action('woocommerce_order_status_completed', 'clear_loyalty_discount_session');
function clear_loyalty_discount_session($order_id) {
    WC()->session->__unset('loyalty_discount');
}
关键修正点说明
  • 持久化折扣值:通过WC()->session->set()将折扣值存入WooCommerce会话,确保页面跳转后仍能读取到该值。
  • 始终挂载钩子:不管是否有GET参数,都挂载woocommerce_cart_calculate_fees钩子,在函数内部判断会话中是否有折扣值再执行逻辑。
  • 修正计算逻辑:补全商品原价总和的购买数量乘数,避免金额计算错误。
  • 添加会话清理:验证失败或订单完成后清空会话中的折扣值,避免无效折扣残留。
  • 移除冗余代码:去掉不必要的global $woocommerce,直接使用传入的$cart参数或WC()->session。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 00:37:30