You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WooCommerce按支付方式触发自定义邮件通知问题求助

WooCommerce按支付方式触发自定义邮件问题解决方案

需求

在WooCommerce中配置两种专属邮件通知:

  • 预支付邮件:对应WooCommerce内置的BACS银行转账支付方式
  • 发票支付邮件:用Cheque支票支付网关替代原生无的发票支付场景

实现基础

基于自定义插件搭建,目录结构如下:

custom-wc-email/
├── custom-wc-email.php
├── emails/
│   ├── class-wc-custom-invoice-email.php
│   └── class-wc-custom-prepayment-email.php
└── templates/
    ├── emails/
    │   ├── wc-custom-invoice-email.php
    │   └── wc-custom-prepayment-email.php
    └── plain/
        ├── wc-custom-invoice-email.php
        └── wc-custom-prepayment-email.php

遇到的问题

  • 用默认取消状态钩子能正常发送自定义模板邮件,但无法按支付方式触发;
  • 替换为woocommerce_thankyou_bacs等网关专属钩子后,仅发送WooCommerce默认通知,自定义邮件无响应;
  • 使用woocommerce_order_status_pending_to_processing等状态变更钩子时,收到的邮件是自定义模板与默认通知的混合内容;
  • 发票支付对应的class-wc-custom-invoice-email.php绑定状态钩子后,下单时触发内部服务器错误。

问题根源

  1. woocommerce_thankyou_{gateway}钩子失效:该钩子仅在订单感谢页加载时触发,此时WooCommerce默认邮件已完成调度,自定义邮件类若未正确绑定到邮件初始化流程,直接调用会因对象未实例化而失败。
  2. 状态钩子导致内容混合:状态变更钩子会自动触发WooCommerce默认的状态邮件,若未禁用对应默认通知,会出现自定义邮件与默认邮件同时发送(或模板逻辑冲突导致内容叠加)的情况。
  3. 发票支付类内部错误:大概率是类文件存在语法错误、未正确继承WC_Email基类、构造函数初始化参数缺失,或钩子回调中未做支付方式判断就执行邮件发送,导致调用未定义方法/变量。

正确实现方案

1. 确保自定义邮件类正确注册

在插件主文件custom-wc-email.php中,通过woocommerce_email_classes过滤器注册自定义邮件类,确保WooCommerce邮件系统能识别它们:

add_filter( 'woocommerce_email_classes', 'register_custom_wc_emails' );
function register_custom_wc_emails( $email_classes ) {
    // 引入邮件类文件
    require_once plugin_dir_path( __FILE__ ) . 'emails/class-wc-custom-prepayment-email.php';
    require_once plugin_dir_path( __FILE__ ) . 'emails/class-wc-custom-invoice-email.php';
    
    // 实例化并注册
    $email_classes['WC_Custom_Prepayment_Email'] = new WC_Custom_Prepayment_Email();
    $email_classes['WC_Custom_Invoice_Email'] = new WC_Custom_Invoice_Email();
    
    return $email_classes;
}

2. 用统一状态钩子实现支付方式触发

放弃网关专属钩子,改用woocommerce_order_status_changed钩子,在回调中判断支付方式和订单状态,触发对应自定义邮件并禁用默认通知:

add_action( 'woocommerce_order_status_changed', 'trigger_payment_specific_emails', 10, 4 );
function trigger_payment_specific_emails( $order_id, $old_status, $new_status, $order ) {
    $payment_method = $order->get_payment_method();
    
    // 预支付(BACS):订单创建后默认状态为pending,此时触发
    if ( $payment_method === 'bacs' && $new_status === 'pending' ) {
        // 禁用默认新订单邮件
        add_filter( 'woocommerce_email_enabled_new_order', '__return_false', 20 );
        // 获取并触发自定义预支付邮件
        $email = WC()->mailer()->get_emails()['WC_Custom_Prepayment_Email'];
        $email->trigger( $order_id );
    }
    
    // 发票支付(Cheque):订单创建后默认状态为on-hold,此时触发
    if ( $payment_method === 'cheque' && $new_status === 'on-hold' ) {
        // 禁用默认新订单邮件
        add_filter( 'woocommerce_email_enabled_new_order', '__return_false', 20 );
        // 获取并触发自定义发票邮件
        $email = WC()->mailer()->get_emails()['WC_Custom_Invoice_Email'];
        $email->trigger( $order_id );
    }
}

3. 修复自定义邮件类的核心方法

确保每个邮件类的trigger方法正确初始化订单对象和邮件变量,示例(以预支付邮件类为例):

class WC_Custom_Prepayment_Email extends WC_Email {
    public function __construct() {
        // 邮件基础配置
        $this->id             = 'custom_prepayment_email';
        $this->title          = '预支付通知';
        $this->description    = '客户选择BACS预支付时发送的专属通知';
        $this->customer_email = true;
        
        // 模板路径设置
        $this->template_base = plugin_dir_path( __FILE__ ) . '../templates/';
        $this->template_html  = 'emails/wc-custom-prepayment-email.php';
        $this->template_plain = 'plain/wc-custom-prepayment-email.php';
        
        parent::__construct();
    }
    
    public function trigger( $order_id ) {
        $this->setup_locale();
        
        if ( $order_id && is_numeric( $order_id ) ) {
            $this->object = wc_get_order( $order_id );
            $this->recipient = $this->object->get_billing_email();
            
            // 模板变量替换
            $this->find['order-date'] = '{order_date}';
            $this->find['order-number'] = '{order_number}';
            
            $this->replace['order-date'] = wc_format_datetime( $this->object->get_date_created() );
            $this->replace['order-number'] = $this->object->get_order_number();
        }
        
        if ( $this->is_enabled() && $this->get_recipient() ) {
            $this->send( $this->get_recipient(), $this->get_subject(), $this->get_content(), $this->get_headers(), $this->get_attachments() );
        }
        
        $this->restore_locale();
    }
}

4. 修复发票支付类的内部错误

检查class-wc-custom-invoice-email.php:

  • 确认类名与文件名匹配(驼峰命名,如WC_Custom_Invoice_Email);
  • 确认正确继承WC_Email,构造函数中完整初始化id、title、description及模板路径;
  • 检查trigger方法中是否存在未定义变量或语法错误,比如未判断订单对象是否存在就调用其方法。

5. 验证测试

  • 分别用BACS和Cheque支付方式下单;
  • 检查收件箱,确认仅收到对应自定义邮件,无默认邮件或混合内容;
  • 查看服务器错误日志,确认无内部错误记录。

内容的提问来源于stack exchange,提问作者Max

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 15:47:52