WooCommerce下单自动生成优惠券报错及Checkout冻结问题求助
问题排查与解决:WooCommerce订单生成优惠券报错、结账冻结及邮件未发送问题
问题现象
- 代码中
$coupon_code = $order->get_meta( 'generated_coupon_code' );行触发报错 - 订单与优惠券可在后台正常生成,但结账页面冻结,无订单确认邮件发送
问题原因
- 订单对象有效性未校验:当
wc_get_order($order_id)返回无效对象(如订单ID错误、订单未完全创建)时,直接调用$order->get_meta()会触发致命错误,中断后续流程(包括页面渲染和邮件发送)。 - 邮件过滤器参数误用:原代码使用
woocommerce_email_order_details过滤器时,错误将第一个参数当作邮件内容字符串处理,实际该参数是订单对象,导致邮件生成逻辑异常。 - 钩子执行流程无容错:
woocommerce_thankyou钩子中未对优惠券创建操作做错误捕获,若优惠券创建失败,会中断整个订单确认流程,引发页面冻结。
解决方法
修正后的完整代码
add_action( 'woocommerce_thankyou', 'generate_coupon_on_order_complete', 10, 1 ); function generate_coupon_on_order_complete( $order_id ) { // 校验订单对象有效性,避免空对象调用报错 $order = wc_get_order( $order_id ); if ( ! $order || ! is_a( $order, 'WC_Order' ) ) { return; } // 检查是否已生成优惠券,避免重复创建 $coupon_code = $order->get_meta( 'generated_coupon_code' ); if ( $coupon_code ) { return; } // 生成更具辨识度的唯一优惠券码 $coupon_code = 'THANKYOU-' . strtoupper( substr( md5( uniqid( wp_rand(), true ) ), 0, 5 ) ); $discount_amount = 10; $expiry_date = strtotime( '+30 days' ); // 创建优惠券并捕获错误 $coupon = array( 'post_title' => $coupon_code, 'post_content' => '', 'post_status' => 'publish', 'post_author' => 1, 'post_type' => 'shop_coupon' ); $new_coupon_id = wp_insert_post( $coupon ); if ( ! is_wp_error( $new_coupon_id ) ) { // 设置优惠券元数据 update_post_meta( $new_coupon_id, 'discount_type', 'percent' ); update_post_meta( $new_coupon_id, 'coupon_amount', $discount_amount ); update_post_meta( $new_coupon_id, 'individual_use', 'yes' ); update_post_meta( $new_coupon_id, 'product_ids', '' ); update_post_meta( $new_coupon_id, 'exclude_product_ids', '' ); update_post_meta( $new_coupon_id, 'usage_limit', '1' ); update_post_meta( $new_coupon_id, 'expiry_date', $expiry_date ); // 将优惠券码绑定到订单 $order->update_meta_data( 'generated_coupon_code', $coupon_code ); $order->save(); } } // 使用官方推荐钩子追加优惠券信息到邮件 add_action( 'woocommerce_email_after_order_table', 'add_coupon_code_to_order_email', 10, 4 ); function add_coupon_code_to_order_email( $order, $sent_to_admin, $plain_text, $email ) { // 仅给客户邮件添加优惠券内容 if ( $sent_to_admin ) { return; } $coupon_code = $order->get_meta( 'generated_coupon_code' ); if ( $coupon_code ) { // 区分纯文本与HTML邮件格式 if ( $plain_text ) { $coupon_message = "\n\n感谢您的订单,我们为您生成了下次购物的折扣优惠券。\n您的折扣码是:$coupon_code\n使用方法:将商品加入购物车,结算时输入该码即可享受优惠。\n"; } else { $coupon_message = "<div style='margin-top:20px; padding:15px; background:#f8f8f8; border-radius:4px;'> <p>感谢您的订单,我们为您生成了下次购物的折扣优惠券。</p> <p>您的折扣码是:<strong style='font-size:1.2em; color:#2d7d9a;'>$coupon_code</strong></p> <p>使用方法:将商品加入购物车,结算时输入该码即可享受优惠。</p> </div>"; } echo $coupon_message; } }
关键修正点说明
- 增加订单对象有效性校验,避免空对象调用方法触发致命错误
- 优化优惠券码生成格式,提升辨识度并降低重复概率
- 增加优惠券创建操作的错误捕获,避免流程中断
- 替换邮件钩子为官方推荐的
woocommerce_email_after_order_table,确保参数处理正确 - 区分纯文本与HTML邮件格式,保证不同类型邮件都能正常显示优惠券信息
- 添加管理员邮件过滤,避免给管理员发送冗余的优惠券内容
内容的提问来源于stack exchange,提问作者Nihilus GM
相关产品推荐
相关产品推荐

