woocommerce_coupon_get_discount_amount返回值按商品重复应用问题咨询
问题描述
你当前使用woocommerce_coupon_get_discount_amount钩子计算针对特定属性商品的优惠券折扣,但返回的折扣金额会被应用到购物车每个商品行项,导致总折扣重复计算(比如返回100美元,4个商品时总折扣变成400美元)。需求是让折扣仅针对尺寸属性为'Low-Res'的商品生效,且作为单次折扣应用到整个购物车。
问题原因
你误用了钩子的工作逻辑:woocommerce_coupon_get_discount_amount会针对购物车中每个符合优惠券条件的商品行项触发一次,而你当前的代码在每次触发时都计算了所有符合条件商品的总折扣,导致每个行项都叠加了这个总金额,最终总折扣被重复计算。
优化方案
提供两种更合理的实现方式,可根据需求选择:
方式一:正确使用原生优惠券钩子
利用woocommerce_coupon_get_discount_amount的完整参数(共4个:折扣金额、待折扣价格、当前购物车项、优惠券对象),仅对当前符合属性条件的商品行项计算对应折扣,避免重复叠加总金额。
优化后的代码:
/* 仅对'Low-Res'商品应用'free download'优惠券 */ add_filter( 'woocommerce_coupon_get_discount_amount', 'filter_woocommerce_coupon_get_discount_amount', 10, 4 ); function filter_woocommerce_coupon_get_discount_amount( $discount_amount, $price_to_discount, $cart_item, $coupon ) { $target_attribute_value = 'Low-Res'; $target_coupon_code = 'free download'; // 仅针对目标优惠券生效 if ( $coupon->get_code() !== $target_coupon_code ) { return $discount_amount; } // 获取当前商品的尺寸属性 $product = $cart_item['data']; $size_attribute = $product->get_attribute( 'pa_size' ); // 对符合属性的商品应用全额折扣(实现免费) if ( $size_attribute === $target_attribute_value ) { return $price_to_discount; } // 不符合条件则返回原折扣金额 return $discount_amount; }
方式二:添加一次性购物车折扣
如果希望折扣作为单次总额展示在购物车底部,而非每个商品行项单独显示,可通过添加负费用的方式实现,确保折扣仅计算一次。
代码示例:
/* 为'Low-Res'商品添加一次性免费折扣 */ add_action( 'woocommerce_cart_calculate_fees', 'add_low_res_free_discount' ); function add_low_res_free_discount() { if ( is_admin() && ! defined( 'DOING_AJAX' ) ) return; $target_attribute_value = 'Low-Res'; $target_coupon_code = 'free download'; $discount_total = 0; // 检查购物车是否使用了目标优惠券 $cart = WC()->cart; if ( ! $cart->has_discount( $target_coupon_code ) ) { return; } // 计算所有符合属性商品的含税总价 foreach ( $cart->get_cart() as $cart_item ) { $product = $cart_item['data']; if ( $product->get_attribute( 'pa_size' ) === $target_attribute_value ) { $discount_total += $cart_item['line_total'] + $cart_item['line_tax']; } } // 添加负费用作为折扣 if ( $discount_total > 0 ) { $cart->add_fee( 'Low-Res 免费折扣', -$discount_total, true ); } }
方案说明
- 方式一更贴合WooCommerce优惠券的原生逻辑,折扣会显示在对应商品行项上,符合用户对优惠券的常规认知。
- 方式二将折扣作为一次性费用扣除,总折扣仅在购物车底部显示一次,适合需要统一展示折扣总额的场景。
内容的提问来源于stack exchange,提问作者Glen Turvey
相关产品推荐
相关产品推荐

