WooCommerce令牌折扣在IE中添加商品到购物车后失效问题
问题描述
我在为WooCommerce商店做基于令牌的折扣系统,Chrome、Firefox、Edge这些主流浏览器都能正常跑,但到了Internet Explorer(IE)就出问题:带令牌的URL能让商品页、店铺页正常显示折扣价,可点「Add to Cart」把商品加进购物车后,价格直接变回原价。
预期实现目标
- 用户点开带
?token=AX4HN参数的链接时,自动设置有效期1小时的cookie存折扣令牌 - 不管用户浏览页面还是加购商品,这个令牌折扣得全程生效
现存问题
- IE里首次通过带令牌的链接进商品页,折扣显示正常;但一点「Add to Cart」,购物车就显示原价
- 只有IE会出这问题,其他浏览器都符合预期
当前实现代码
步骤1:URL里有令牌时设置Cookie
function set_token_cookie() { if (isset($_GET['token']) && $_GET['token'] === 'AX4HN') { setcookie('discount_token', 'AX4HN', time() + 3600, '/'); // Cookie有效期1小时 $_COOKIE['discount_token'] = 'AX4HN'; // 让当前请求立即生效 } } add_action('init', 'set_token_cookie');
步骤2:验证令牌是否有效
function has_valid_token() { return (isset($_GET['token']) && $_GET['token'] === 'AX4HN') || (isset($_COOKIE['discount_token']) && $_COOKIE['discount_token'] === 'AX4HN'); }
步骤3:令牌有效时应用折扣
add_filter('woocommerce_product_get_price', 'custom_price_discount', 20, 2); function custom_price_discount($price, $product) { $discount_rate = 0.8; // 打8折 if (has_valid_token() && !$product->is_on_sale()) { return floatval($price) * $discount_rate; } return $price; }
观察结果
- IE里商品页能正确显示折扣价
- 加购后购物车页面显示原价
- 推测IE离开初始页面后没法正确读取Cookie
解决方案
针对IE Cookie读取问题的修复
IE对Cookie的处理有特殊限制,尤其是跨请求(比如加购的POST请求)场景,得把Cookie属性设置得更兼容:
- 完善Cookie属性设置
IE要求显式声明SameSite属性,HTTPS站点还要注意secure属性。修改set_token_cookie函数:
function set_token_cookie() { if (isset($_GET['token']) && $_GET['token'] === 'AX4HN') { $expire = time() + 3600; $path = '/'; $domain = $_SERVER['HTTP_HOST']; $secure = is_ssl(); $httponly = true; $samesite = 'Lax'; // IE不支持SameSite属性,单独处理 if (isset($_SERVER['HTTP_USER_AGENT']) && (strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE') !== false || strpos($_SERVER['HTTP_USER_AGENT'], 'Trident/') !== false)) { setcookie('discount_token', 'AX4HN', $expire, $path, $domain, $secure, $httponly); } else { setcookie('discount_token', 'AX4HN', [ 'expires' => $expire, 'path' => $path, 'domain' => $domain, 'secure' => $secure, 'httponly' => $httponly, 'samesite' => $samesite ]); } $_COOKIE['discount_token'] = 'AX4HN'; } } add_action('init', 'set_token_cookie');
- 覆盖购物车价格计算逻辑
WooCommerce加购可能用AJAX或POST请求,IE里这类请求可能不自动带Cookie。除了商品页的折扣钩子,还要加购物车总价计算的钩子:
// 购物车项目价格重新计算 add_action('woocommerce_before_calculate_totals', 'custom_cart_price_discount', 20); function custom_cart_price_discount($cart) { if (is_admin() && !defined('DOING_AJAX')) return; if (has_valid_token()) { $discount_rate = 0.8; foreach ($cart->get_cart() as $cart_item) { $product = $cart_item['data']; if (!$product->is_on_sale()) { $original_price = $product->get_regular_price(); $cart_item['data']->set_price(floatval($original_price) * $discount_rate); } } } }
更兼容IE的全站令牌折扣实现方案
- 结合Session存储令牌
除了Cookie,同时用Session存令牌,绕开IE的Cookie读取问题:
function set_token_session_and_cookie() { if (isset($_GET['token']) && $_GET['token'] === 'AX4HN') { // 启动Session并存令牌 session_start(); $_SESSION['discount_token'] = 'AX4HN'; // 设置兼容IE的Cookie $expire = time() + 3600; setcookie('discount_token', 'AX4HN', $expire, '/', $_SERVER['HTTP_HOST'], is_ssl(), true); $_COOKIE['discount_token'] = 'AX4HN'; } } add_action('init', 'set_token_session_and_cookie'); // 更新令牌验证函数,加入Session判断 function has_valid_token() { session_start(); return (isset($_GET['token']) && $_GET['token'] === 'AX4HN') || (isset($_COOKIE['discount_token']) && $_COOKIE['discount_token'] === 'AX4HN') || (isset($_SESSION['discount_token']) && $_SESSION['discount_token'] === 'AX4HN'); }
- 覆盖所有价格相关钩子
WooCommerce有多个价格计算钩子,要确保折扣在商品页、购物车、结算页都生效:
woocommerce_product_get_price:商品页显示价格woocommerce_product_get_regular_price:商品常规价格woocommerce_before_calculate_totals:购物车总价计算woocommerce_cart_item_price:购物车单个商品价格显示
内容的提问来源于stack exchange,提问作者thecodedeveloper.com
相关产品推荐
相关产品推荐

