WooCommerce订阅场景下移除父订阅优惠券的函数报错排查
致命错误根因
- 报错的核心原因是方法所属的对象类型用错了:通过
$subscription->get_items('coupon')遍历得到的每一项是WC_Order_Item_Coupon类的实例,这个类的作用是存储订单上关联优惠券的消费记录(比如抵扣金额、优惠券代码),本身不存在get_discount_type()方法。 get_discount_type()是WC_Coupon类的内置方法,用来获取优惠券本身的配置类型,必须通过实例化真实的优惠券实体才能调用,直接在订单优惠券条目上调用就会触发未定义方法的致命错误。
订阅对象传递逻辑校验
当前的参数传递方式完全正确:
woocommerce_subscription_payment_complete钩子的官方传参规则为:仅传入1个参数,也就是触发支付动作的完整WC_Subscription实例对象- 你写的钩子挂载参数
add_action('woocommerce_subscription_payment_complete','remove_store_credit',10,1)和这个规则完全匹配,不存在传错父级订阅对象、拿不到实体的问题。
修正后的可运行代码
修正逻辑为:从订单优惠券条目中提取优惠券代码,实例化对应的WC_Coupon实体后再做类型判断,同时补充对象校验、实体持久化逻辑:
function remove_store_credit($subscription) { // 前置校验,避免非预期场景传入错误对象触发报错 if ( ! is_object( $subscription ) || ! is_a( $subscription, 'WC_Subscription' ) ) { return; } $coupon_items = $subscription->get_items( 'coupon' ); foreach ( $coupon_items as $coupon_item ) { // 通过优惠券代码实例化真实的优惠券实体 $coupon = new WC_Coupon( $coupon_item->get_code() ); // 仅对匹配类型的店铺抵用券做移除操作 if ( $coupon->get_discount_type() === 'smart_coupon' ) { $subscription->remove_coupon( $coupon_item->get_code() ); } } // 必须调用save()将修改持久化到数据库,否则移除操作不会生效 $subscription->save(); } add_action('woocommerce_subscription_payment_complete','remove_store_credit',10,1);
时序调整提示
如果你的需求是在每笔订阅关联的续订订单创建时就执行移除逻辑,当前使用的woocommerce_subscription_payment_complete触发时机偏晚(要等支付完成才会执行),可以将钩子替换为订单创建阶段的对应钩子,让移除动作在订单生成后、支付流程启动前就完成,避免出现时序冲突。
内容的提问来源于stack exchange,提问作者Rob
相关产品推荐
相关产品推荐

