基于商品分类的WooCommerce购物车商品阶梯折扣定价问题
解决特定分类商品阶梯折扣同步购物车小计及订单的问题
问题根源
原代码使用woocommerce_cart_calculate_fees钩子修改商品价格,这个钩子的执行时机是购物车总计计算完成后,仅修改商品显示价格不会触发小计重新计算,导致购物车总价不更新。同时未处理钩子重复触发的问题,可能造成价格被多次错误扣减。
解决方案
改用woocommerce_before_calculate_totals钩子(该钩子在购物车计算总价前触发),同时添加原始价格缓存逻辑避免重复折扣,确保折扣价同步到购物车小计和最终订单。
修改后的代码
add_action( 'woocommerce_before_calculate_totals', 'custom_bulk_discount', 20, 1 ); function custom_bulk_discount( $cart ) { // 后台非AJAX请求直接返回 if ( is_admin() && ! defined( 'DOING_AJAX' ) ) return; // 防止重复触发导致价格多次修改 if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 ) return; $target_category = 'ferns'; $total_qty = 0; // 第一步:计算目标分类商品的总数量 foreach ( $cart->get_cart() as $cart_item ) { if ( has_term( $target_category, 'product_cat', $cart_item['product_id'] ) ) { $total_qty += $cart_item['quantity']; } } // 第二步:根据阶梯数量设置折扣价 if ( $total_qty >= 100 ) { $discount_amount = $total_qty >= 200 ? 1.5 : 1; foreach ( $cart->get_cart() as $cart_item ) { if ( has_term( $target_category, 'product_cat', $cart_item['product_id'] ) ) { $product = $cart_item['data']; // 保存原始价格到临时属性,避免重复折扣 if ( ! $product->get_meta( '_original_price', true ) ) { $original_price = version_compare( WC_VERSION, '3.0', '<' ) ? $product->price : $product->get_price(); $product->add_meta_data( '_original_price', $original_price, true ); } // 基于原始价格计算折扣价 $original_price = $product->get_meta( '_original_price', true ); $discounted_price = $original_price - $discount_amount; // 设置折扣价(兼容WC3.0+版本) if ( version_compare( WC_VERSION, '3.0', '<' ) ) { $product->price = $discounted_price; } else { $product->set_price( $discounted_price ); } } } } else { // 数量未达阶梯,恢复原始价格 foreach ( $cart->get_cart() as $cart_item ) { if ( has_term( $target_category, 'product_cat', $cart_item['product_id'] ) ) { $product = $cart_item['data']; $original_price = $product->get_meta( '_original_price', true ); if ( $original_price ) { if ( version_compare( WC_VERSION, '3.0', '<' ) ) { $product->price = $original_price; } else { $product->set_price( $original_price ); } $product->delete_meta_data( '_original_price' ); } } } } }
关键说明
- 钩子选择:
woocommerce_before_calculate_totals确保在购物车计算总价前修改价格,小计会自动同步更新。 - 原始价格缓存:通过商品临时元数据保存原始价格,避免钩子重复触发时多次扣减价格。
- 订单同步:修改后的商品价格会直接传递到订单,开票时会使用折扣后的单价,满足开票需求。
- 版本兼容:保留了WC3.0前后的价格获取/设置逻辑,适配不同版本的WooCommerce。
内容的提问来源于stack exchange,提问作者AlexTSF
相关产品推荐
相关产品推荐

