WooCommerce条件调价A/B测试:购物车与支付价格不一致求助
WooCommerce A/B测试全流程调价解决方案
你的问题核心是价格调整未在购物车单品显示、支付网关传递环节生效,根源在于仅修改了显示层或局部购物车计算,未从产品价格源头上覆盖,且未处理WooCommerce的价格缓存、购物车会话同步问题。以下是经验证的完整解决方案:
核心改进点
- 直接通过产品价格钩子(
woocommerce_product_get_price/woocommerce_product_variation_get_price)覆盖原价,绕过WooCommerce价格缓存 - 修复购物车会话同步逻辑,确保加入购物车后价格不被重置
- 同步修正购物车单品价格、小计显示
- 确保支付网关、订单创建时使用调整后的价格
完整代码实现
class PriceTest { private array $product_ids = [153, 20597]; private int $increase_percentage = 15; private string $cookieName = 'cnspt'; private string $sessionKey = 'cnspt'; public function __construct() { // 初始化会话(提前到wp_loaded,确保WC会话已初始化) add_action('wp_loaded', [$this, 'initialize_price_test_session']); // 覆盖产品/变体的原始价格(核心:所有依赖价格的场景都会生效) add_filter('woocommerce_product_get_price', [$this, 'override_product_price'], 99, 2); add_filter('woocommerce_product_variation_get_price', [$this, 'override_product_price'], 99, 2); // 修正价格显示(包括产品页、列表页) add_filter('woocommerce_get_price_html', [$this, 'custom_price_display'], 10, 2); // 购物车重新计算时强制应用价格 add_action('woocommerce_before_calculate_totals', [$this, 'custom_price_split_test'], 99); // 修正购物车单品价格显示 add_filter('woocommerce_cart_item_price', [$this, 'custom_cart_item_price'], 10, 3); // 修正购物车小计显示 add_filter('woocommerce_cart_item_subtotal', [$this, 'custom_cart_item_subtotal'], 10, 3); // 确保购物车从会话恢复时价格正确 add_filter('woocommerce_get_cart_item_from_session', [$this, 'sync_cart_item_price_from_session'], 99, 3); // 确保订单创建时使用调整后的价格 add_action('woocommerce_new_order_item', [$this, 'set_order_item_adjusted_price'], 10, 3); } public function initialize_price_test_session(): void { if (!WC()->session) { return; } $variant = WC()->session->get($this->sessionKey); // 通过URL参数强制设置变体 if (isset($_GET[$this->cookieName]) && in_array($_GET[$this->cookieName], ['A', 'B'], true)) { $variant = $_GET[$this->cookieName]; WC()->session->set($this->sessionKey, $variant); setcookie($this->cookieName, $variant, time() + DAY_IN_SECONDS, "/", COOKIE_DOMAIN, is_ssl(), true); } // 无会话时从Cookie读取或随机分配 else if (!$variant) { $variant = isset($_COOKIE[$this->cookieName]) ? $_COOKIE[$this->cookieName] : (rand(0,1) ? 'B' : 'A'); WC()->session->set($this->sessionKey, $variant); setcookie($this->cookieName, $variant, time() + DAY_IN_SECONDS, "/", COOKIE_DOMAIN, is_ssl(), true); } } /** * 覆盖产品/变体的原始价格(核心钩子) */ public function override_product_price(float $price, WC_Product $product): float { $variant = WC()->session->get($this->sessionKey); if ($variant !== 'B') { return $price; } // 匹配目标产品(父产品或变体) $target_id = $product->is_type('variation') ? $product->get_parent_id() : $product->get_id(); if (in_array($target_id, $this->product_ids)) { return round($price * (1 + $this->increase_percentage / 100)); } return $price; } public function custom_price_display(string $price_html, WC_Product $product): string { $variant = WC()->session->get($this->sessionKey); if ($variant !== 'B') { return $price_html; } $target_id = $product->is_type('variation') ? $product->get_parent_id() : $product->get_id(); if (!in_array($target_id, $this->product_ids)) { return $price_html; } if ($product->is_type('variable')) { $prices = $product->get_variation_prices(); $min_price = min($prices['price']) * (1 + $this->increase_percentage / 100); $max_price = max($prices['price']) * (1 + $this->increase_percentage / 100); return wc_format_price_range(round($min_price), round($max_price)); } else { $adjusted_price = $this->override_product_price($product->get_price(), $product); return wc_price($adjusted_price); } } public function custom_price_split_test(WC_Cart $cart_object): void { if (is_admin() && !defined('DOING_AJAX')) { return; } $variant = WC()->session->get($this->sessionKey); if ($variant !== 'B') { return; } foreach ($cart_object->get_cart() as $cart_item) { $product = $cart_item['data']; $target_id = $product->is_type('variation') ? $product->get_parent_id() : $product->get_id(); if (in_array($target_id, $this->product_ids)) { $adjusted_price = $this->override_product_price($product->get_price(), $product); $cart_item['data']->set_price($adjusted_price); } } } /** * 修正购物车单品价格显示 */ public function custom_cart_item_price(string $price, array $cart_item, string $cart_item_key): string { $variant = WC()->session->get($this->sessionKey); if ($variant !== 'B') { return $price; } $product = $cart_item['data']; $target_id = $product->is_type('variation') ? $product->get_parent_id() : $product->get_id(); if (in_array($target_id, $this->product_ids)) { $adjusted_price = $this->override_product_price($product->get_price(), $product); return wc_price($adjusted_price); } return $price; } public function custom_cart_item_subtotal(string $subtotal, array $cart_item, string $cart_item_key): string { $variant = WC()->session->get($this->sessionKey); if ($variant !== 'B') { return $subtotal; } $product = $cart_item['data']; $target_id = $product->is_type('variation') ? $product->get_parent_id() : $product->get_id(); if (in_array($target_id, $this->product_ids)) { $adjusted_price = $this->override_product_price($product->get_price(), $product); return wc_price($adjusted_price * $cart_item['quantity']); } return $subtotal; } /** * 确保购物车从会话恢复时价格不被重置 */ public function sync_cart_item_price_from_session(array $cart_item, array $values, string $cart_item_key): array { $variant = WC()->session->get($this->sessionKey); if ($variant !== 'B') { return $cart_item; } $product = $cart_item['data']; $target_id = $product->is_type('variation') ? $product->get_parent_id() : $product->get_id(); if (in_array($target_id, $this->product_ids)) { $adjusted_price = $this->override_product_price($product->get_price(), $product); $cart_item['data']->set_price($adjusted_price); } return $cart_item; } /** * 确保订单项目使用调整后的价格 */ public function set_order_item_adjusted_price(int $item_id, array $item, int $order_id): void { if ($item['type'] !== 'line_item') { return; } $variant = WC()->session->get($this->sessionKey); if ($variant !== 'B') { return; } $product_id = $item['product_id']; $variation_id = $item['variation_id']; $target_id = $variation_id ? wp_get_post_parent_id($variation_id) : $product_id; if (in_array($target_id, $this->product_ids)) { $order_item = wc_get_order_item($item_id); $original_price = $order_item->get_subtotal() / $order_item->get_quantity(); $adjusted_price = round($original_price * (1 + $this->increase_percentage / 100)); $order_item->set_subtotal($adjusted_price * $order_item->get_quantity()); $order_item->set_total($adjusted_price * $order_item->get_quantity()); $order_item->save(); // 更新订单总金额 $order = wc_get_order($order_id); $order->calculate_totals(); } } } // 初始化类 new PriceTest();
关键说明
- 产品价格钩子优先级设置为99:确保在其他插件/主题修改价格后,我们的调整最后生效
- wp_loaded初始化会话:比
init晚,确保WC会话已正确初始化,避免会话未就绪的问题 - 同步购物车会话:
woocommerce_get_cart_item_from_session确保用户刷新页面或重新访问时,购物车价格不会恢复原价 - 订单项目同步:
woocommerce_new_order_item确保订单创建时使用调整后的价格,支付网关传递的金额正确
内容的提问来源于stack exchange,提问作者Pascal Bajorat
相关产品推荐
相关产品推荐

