You need to enable JavaScript to run this app. WooCommerce订阅场景下移除父订阅优惠券的函数报错排查
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.11.05 14:15:05