WooCommerce编程添加的自定义优惠手续费无法留存至结账及订单页
问题原因分析
你的代码存在两个核心问题导致优惠无法留存到结账页和订单页:
- 钩子挂载时机错误:你仅当URL中存在
$_GET['discount']参数时才挂载woocommerce_cart_calculate_fees钩子,但从购物车跳转到结账页时,这个GET参数不会被自动携带,钩子无法触发,优惠也就不会被计算。 - 折扣值未持久化:直接依赖临时的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
相关产品推荐
相关产品推荐

