草庐IT

php - 当客户更改地址 WooCommerce 时发送通知电子邮件

coder 2024-04-18 原文

跟进此线程:Woocommerce Refund Email
我有一个似乎无法解决的问题,我阅读了所有关于使用带有自定义触发器的自定义类扩展 WC_Email 类的主题,但我无法让它工作。

我想要实现的是向 WooCommerce 电子邮件 设置添加电子邮件通知,并在客户更新其账单或运输详细信息时向收件人发送电子邮件。

所以在我的 functions.php 中,我将 woocommerce_customer_save_address 操作添加到 woocommerce_email_actions 并添加我自己的 WC_Email像这样的类扩展:

<?php    
// Add a custom email action to the list of emails WooCommerce should load
add_action( 'woocommerce_init', function() { 
  add_action( 'woocommerce_customer_save_address', array( WC(), 'send_transactional_email' ), 10, 10 ); // WC 2.2-
});
add_filter( 'woocommerce_email_actions', 'add_customer_address_change_woocommerce_email_actions' ); // WC 2.3+
function add_customer_address_change_woocommerce_email_actions( $email_actions ) {
  $email_actions[] = 'woocommerce_customer_save_address';
  return $email_actions;
}
// Add a custom email class to the list of emails WooCommerce should load
add_filter( 'woocommerce_email_classes', 'add_customer_address_change_woocommerce_email_classes' );
function add_customer_address_change_woocommerce_email_classes( $email_classes ) {
    require_once( get_stylesheet_directory() . '/includes/class-wc-customer-address-change-email.php' );
    $email_classes['WC_Customer_Address_Change_Email'] = new WC_Customer_Address_Change_Email();
    return $email_classes;
} 

这是我自定义 WC_Customer_Address_Change_Email 类中的代码:

<?php
if ( ! defined( 'ABSPATH' ) ) {
    exit; // Exit if accessed directly
}

if ( ! class_exists( 'WC_Customer_Address_Change_Email' ) ) :

/**
 * A custom address change WooCommerce Email class
 *
 * @class       WC_Customer_Address_Change_Email
 * @version     2.3.0
 * @package     WooCommerce/Classes/Emails
 * @author      WooThemes
 * @extends     WC_Email
 */
class WC_Customer_Address_Change_Email extends WC_Email {

  public $woocommerce;
  public $current_user;

    /**
     * Set email defaults
     *
     * @since 0.1
     */
    function __construct() {

        // set ID, this simply needs to be a unique name
        $this->id = 'wc_customer_address_changed';

        // this is the title in WooCommerce Email settings
        $this->title = __('Customer Address Change', 'monum');

        // this is the description in WooCommerce email settings
        $this->description = __('Address Change Notification emails are sent when a customer changes his billing or shipping address', 'monum');

        // these are the default heading and subject lines that can be overridden using the settings
        $this->heading = __('Customer Address Change', 'monum');
        $this->subject = __('Customer Address Change', 'monum');

        // these define the locations of the templates that this email should use, we'll just use the new order template since this email is similar
        $this->template_html  = 'emails/admin-address-change.php';
        $this->template_plain = 'emails/plain/admin-address-change.php';

        // Trigger on new paid orders
        //add_action( 'woocommerce_order_status_completed_notification', array( $this, 'trigger' ) );
        add_action( 'woocommerce_customer_save_address', array( $this, 'trigger' ) );

        // Call parent constructor to load any other defaults not explicity defined here
        parent::__construct();

        // this sets the recipient to the settings defined below in init_form_fields()
        $this->recipient = $this->get_option( 'recipient' );

        // if none was entered, just use the WP admin email as a fallback
        if ( ! $this->recipient )
            $this->recipient = get_option( 'admin_email' );
    }


    /**
   * trigger function.
   *
   * @access public
   * @return void
   */
    function trigger( $user_id ) {

        $this->send( $this->get_recipient(), $this->get_subject(), $this->get_content(), $this->get_headers(), $this->get_attachments() );
    }      

    /**
     * get_content_html function.
     *
     * @access public
     * @return string
     */
    function get_content_html() {
        ob_start();
        wc_get_template( $this->template_html, array(
            'email_heading' => $this->get_heading(),
            'blogname'      => $this->get_blogname(),
            'sent_to_admin' => true,
            'plain_text'    => false
        ) );
        return ob_get_clean();
    }


    /**
     * get_content_plain function.
     *
     * @access public
     * @return string
     */
    function get_content_plain() {
        ob_start();
        wc_get_template( $this->template_plain, array(
            'email_heading' => $this->get_heading(),
            'blogname'      => $this->get_blogname(),
            'sent_to_admin' => true,
            'plain_text'    => true
        ) );
        return ob_get_clean();
    }


    /**
     * Initialise Settings Form Fields
   *
   * @access public
   * @return void
     */
    function init_form_fields() {

        $this->form_fields = array(
            'enabled' => array(
        'title'         => __( 'Enable/Disable', 'woocommerce' ),
        'type'          => 'checkbox',
        'label'         => __( 'Enable this email notification', 'woocommerce' ),
        'default'       => 'yes'
      ),
            'recipient'  => array(
                'title'       => __( 'Recipient(s)', 'woocommerce' ),
                'type'        => 'text',
                'description' => sprintf( __( 'Enter recipients (comma separated) for this email. Defaults to <code>%s</code>.', 'woocommerce' ), esc_attr( get_option('admin_email') ) ),
                'placeholder' => '',
                'default'     => ''
            ),
            'subject'    => array(
                'title'       => __( 'Subject', 'woocommerce' ),
                'type'        => 'text',
                'description' => sprintf( __( 'This controls the email subject line. Leave blank to use the default subject: <code>%s</code>.', 'woocommerce' ), $this->subject ),
                'placeholder' => '',
                'default'     => ''
            ),
            'heading'    => array(
                'title'       => __( 'Email Heading', 'woocommerce' ),
                'type'        => 'text',
                'description' => sprintf( __( 'This controls the main heading contained within the email notification. Leave blank to use the default heading: <code>%s</code>.', 'woocommerce' ), $this->heading ),
                'placeholder' => '',
                'default'     => ''
            ),
            'email_type' => array(
                'title'       => __( 'Email type', 'woocommerce' ),
                'type'        => 'select',
                'description' => __( 'Choose which format of email to send.', 'woocommerce' ),
                'default'     => 'html',
                'class'       => 'email_type wc-enhanced-select',
                'options'     => $this->get_email_type_options()
            )
        );
    }


}

endif;

return new WC_Customer_Address_Change_Email();

类(class)本身有效,因为额外的电子邮件通知设置显示在 WooCommerce 设置中。
问题出在触发器调用中:

add_action( 'woocommerce_customer_save_address', array( $this, 'trigger' ) );

它只是不开火。 当我将其更改为:

add_action( 'woocommerce_order_status_completed_notification', array( $this, 'trigger' ) );

在后台完成订单后,我确实从类(class)收到了一封额外的电子邮件,其中包含我自己的电子邮件模板。

@birgire 建议的将 woocommerce_customer_save_address 操作添加到 woocommerce_email_actions 的解决方案似乎不起作用?

add_filter( 'woocommerce_email_actions', function( $email_actions ) {
    $email_actions[] = 'woocommerce_customer_save_address';
    return $email_actions;
});

对此有什么想法或解决方法吗?
可能值得一提的是我正在使用 Peddlar 主题的 child 主题,但那不应该吗?我正在使用 Woocommerce 2.3.11 和 Wordpress 4.2.2

谢谢!


更新 08-07-2015

我找到了一个解决方法。 在我的 functions.php 中,我直接在 woocommerce_customer_save_address 操作中使用扩展的 WC_Email 类来发送邮件:

// Send notification email when customer saves address using custom extended WC_Email class
add_action( 'woocommerce_customer_save_address','notify_admin_customer_address_change', 10, 2);
function notify_admin_customer_address_change( $user_id ) {
  global $woocommerce;
    $mailer   = WC()->mailer();
    $My_Class = new WC_Customer_Address_Change_Email; // retrieve custom extended class 
  $mailer->send( $My_Class->get_recipient(), $My_Class->get_subject(), $My_Class->get_content(), $My_Class->get_headers(), $My_Class->get_attachments() );
}

这样我仍然可以从后端使用自定义类设置并使用 WC_Email 类功能。

唯一还行不通的是,如果我将电子邮件类型设置为纯文本,Content-Type 仍设置为:text/html 而不是text/plain,导致我所有的换行符在我的模板中消失。在默认的 WooCommerce 电子邮件通知中,这确实可以正常工作。

我的猜测是 $mailer->send 调用中的 $My_Class->get_headers() 参数无法正常工作。

有什么办法解决这个问题吗?
我可以在模板中手动设置Content-Type吗?
谢谢

最佳答案

几周前,我为我的一个客户写了一个简单的插件,几乎就是为了这个目的。 每当客户更改/更新他的帐户数据时,这将发送电子邮件通知。

查看我的代码并从那里编辑/删除您不需要的任何内容。

 if( !class_exists('WooCommerceNotifyChanges') ){

class WooCommerceNotifyChanges{

    function __construct(){
        // customer saves main account data
        add_action('woocommerce_save_account_details', array( $this, 'woocommerce_send_notification' ));

        // customer saves billing or shipping data
        add_action('woocommerce_customer_save_address', array( $this, 'woocommerce_send_notification' ));
    }

    function woocommerce_send_notification(){
        $body       = '';
        $to         = 'recipient@gmail.com';    //address that will receive this email
        $subject    = 'One of your customers has updated their information.';

        $curr_user      = wp_get_current_user();
        $user_id        = $curr_user->ID;
        $curr_username  = $curr_user->data->user_login;

        $body .= '<table>';
        $body .= '<tr><td><strong>Account</strong></td></tr>';
        $body .= '<tr><td>Username: </td><td>' . $curr_username                                         . '</td></tr>';
        $body .= '<tr><td colspan="2">&nbsp;</td></tr>';
        $body .= '<tr><td colspan="2"><strong>Billing</strong></td></tr>';
        $body .= '<tr><td>First name: </td><td>' . get_user_meta( $user_id, 'billing_first_name', true ). '</td></tr>';
        $body .= '<tr><td>Last name: </td><td>' . get_user_meta( $user_id, 'billing_last_name', true )  . '</td></tr>';
        $body .= '<tr><td>Company: </td><td>' . get_user_meta( $user_id, 'billing_company', true )      . '</td></tr>';
        $body .= '<tr><td>Address 1: </td><td>' . get_user_meta( $user_id, 'billing_address_1', true )  . '</td></tr>';
        $body .= '<tr><td>Address 2: </td><td>' . get_user_meta( $user_id, 'billing_address_2', true )  . '</td></tr>';
        $body .= '<tr><td>City: </td><td>' . get_user_meta( $user_id, 'billing_city', true )            . '</td></tr>';
        $body .= '<tr><td>Post code: </td><td>' . get_user_meta( $user_id, 'billing_postcode', true )   . '</td></tr>';
        $body .= '<tr><td>Country: </td><td>' . get_user_meta( $user_id, 'billing_country', true )      . '</td></tr>';
        $body .= '<tr><td>State: </td><td>' . get_user_meta( $user_id, 'billing_state', true )          . '</td></tr>';
        $body .= '<tr><td>Phone: </td><td>' . get_user_meta( $user_id, 'billing_phone', true )          . '</td></tr>';
        $body .= '<tr><td>Email: </td><td>' . get_user_meta( $user_id, 'billing_email', true )          . '</td></tr>';
        $body .= '<tr><td colspan="2">&nbsp;</td></tr>';
        $body .= '<tr><td colspan="2"><strong>Shipping</strong></td></tr>';
        $body .= '<tr><td>First name: </td><td>' . get_user_meta( $user_id, 'shipping_first_name', true ). '</td></tr>';
        $body .= '<tr><td>Last name: </td><td>' . get_user_meta( $user_id, 'shipping_last_name', true ) . '</td></tr>';
        $body .= '<tr><td>Company: </td><td>' . get_user_meta( $user_id, 'shipping_company', true )     . '</td></tr>';
        $body .= '<tr><td>Address 1: </td><td>' . get_user_meta( $user_id, 'shipping_address_1', true ) . '</td></tr>';
        $body .= '<tr><td>Address 2: </td><td>' . get_user_meta( $user_id, 'shipping_address_2', true ) . '</td></tr>';
        $body .= '<tr><td>City: </td><td>' . get_user_meta( $user_id, 'shipping_city', true )           . '</td></tr>';
        $body .= '<tr><td>Post code: </td><td>' . get_user_meta( $user_id, 'shipping_postcode', true )  . '</td></tr>';
        $body .= '<tr><td>Country: </td><td>' . get_user_meta( $user_id, 'shipping_country', true )     . '</td></tr>';
        $body .= '<tr><td>State: </td><td>' . get_user_meta( $user_id, 'shipping_state', true )         . '</td></tr>';
        $body .= '</table>';    

        //set content type as HTML
        $headers = array('Content-Type: text/html; charset=UTF-8;');

        //send email
        if( wp_mail( $to, $subject, $body, $headers ) ){
            //echo 'email sent';
        }else{
            //echo 'email NOT sent';                
        }
        //exit();
    }
}
new WooCommerceNotifyChanges(); 
} 

关于php - 当客户更改地址 WooCommerce 时发送通知电子邮件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31270846/

有关php - 当客户更改地址 WooCommerce 时发送通知电子邮件的更多相关文章

  1. ruby-on-rails - Ruby on Rails 迁移,将表更改为 MyISAM - 2

    如何正确创建Rails迁移,以便将表更改为MySQL中的MyISAM?目前是InnoDB。运行原始执行语句会更改表,但它不会更新db/schema.rb,因此当在测试环境中重新创建表时,它会返回到InnoDB并且我的全文搜索失败。我如何着手更改/添加迁移,以便将现有表修改为MyISAM并更新schema.rb,以便我的数据库和相应的测试数据库得到相应更新? 最佳答案 我没有找到执行此操作的好方法。您可以像有人建议的那样更改您的schema.rb,然后运行:rakedb:schema:load,但是,这将覆盖您的数据。我的做法是(假设

  2. ruby-on-rails - Rails 常用字符串(用于通知和错误信息等) - 2

    大约一年前,我决定确保每个包含非唯一文本的Flash通知都将从模块中的方法中获取文本。我这样做的最初原因是为了避免一遍又一遍地输入相同的字符串。如果我想更改措辞,我可以在一个地方轻松完成,而且一遍又一遍地重复同一件事而出现拼写错误的可能性也会降低。我最终得到的是这样的:moduleMessagesdefformat_error_messages(errors)errors.map{|attribute,message|"Error:#{attribute.to_s.titleize}#{message}."}enddeferror_message_could_not_find(obje

  3. ruby-on-rails - 项目升级后 Pow 不会更改 ruby​​ 版本 - 2

    我在我的Rails项目中使用Pow和powifygem。现在我尝试升级我的ruby​​版本(从1.9.3到2.0.0,我使用RVM)当我切换ruby​​版本、安装所有gem依赖项时,我通过运行railss并访问localhost:3000确保该应用程序正常运行以前,我通过使用pow访问http://my_app.dev来浏览我的应用程序。升级后,由于错误Bundler::RubyVersionMismatch:YourRubyversionis1.9.3,butyourGemfilespecified2.0.0,此url不起作用我尝试过的:重新创建pow应用程序重启pow服务器更新战俘

  4. ruby - Capistrano 3 在任务中更改 ssh_options - 2

    我尝试使用不同的ssh_options在同一阶段运行capistranov.3任务。我的production.rb说:set:stage,:productionset:user,'deploy'set:ssh_options,{user:'deploy'}通过此配置,capistrano与用户deploy连接,这对于其余的任务是正确的。但是我需要将它连接到服务器中配置良好的an_other_user以完成一项特定任务。然后我的食谱说:...taskswithoriginaluser...task:my_task_with_an_other_userdoset:user,'an_othe

  5. ruby - 从 Ruby 中的主机名获取 IP 地址 - 2

    我有一个存储主机名的Ruby数组server_names。如果我打印出来,它看起来像这样:["hostname.abc.com","hostname2.abc.com","hostname3.abc.com"]相当标准。我想要做的是获取这些服务器的IP(可能将它们存储在另一个变量中)。看起来IPSocket类可以做到这一点,但我不确定如何使用IPSocket类遍历它。如果它只是尝试像这样打印出IP:server_names.eachdo|name|IPSocket::getaddress(name)pnameend它提示我没有提供服务器名称。这是语法问题还是我没有正确使用类?输出:ge

  6. jquery - 我的 jquery AJAX POST 请求无需发送 Authenticity Token (Rails) - 2

    rails中是否有任何规定允许站点的所有AJAXPOST请求在没有authenticity_token的情况下通过?我有一个调用Controller方法的JqueryPOSTajax调用,但我没有在其中放置任何真实性代码,但调用成功。我的ApplicationController确实有'request_forgery_protection'并且我已经改变了config.action_controller.consider_all_requests_local在我的environments/development.rb中为false我还搜索了我的代码以确保我没有重载ajaxSend来发送

  7. ruby - 更改 ActiveRecord 中对象的类 - 2

    假设我有一个FireNinja我的数据库中的对象,使用单表继承存储。后来才知道他真的是WaterNinja.将他更改为不同的子类的最干净的方法是什么?更好的是,我很想创建一个新的WaterNinja对象并替换旧的FireNinja在数据库中,保留ID。编辑我知道如何创建新的WaterNinja来self现有FireNinja的对象,我也知道我可以删除旧的并保存新的。我想做的是改变现有项目的类别。我是通过创建一个新对象并执行一些ActiveRecord魔法来替换行,还是通过对对象本身做一些疯狂的事情,或者甚至通过删除它并使用相同的ID重新插入来做到这一点,这是问题的一部分。

  8. ruby - 使用 Ruby 通过 Outlook 发送消息的最简单方法是什么? - 2

    我的工作要求我为某些测试自动生成电子邮件。我一直在四处寻找,但未能找到可以快速实现的合理解决方案。它需要在outlook而不是其他邮件服务器中,因为我们有一些奇怪的身份验证规则,我们需要保存草稿而不是仅仅发送邮件的选项。显然win32ole可以做到这一点,但我找不到任何相当简单的例子。 最佳答案 假设存储了Outlook凭据并且您设置为自动登录到Outlook,WIN32OLE可以很好地完成此操作:require'win32ole'outlook=WIN32OLE.new('Outlook.Application')message=

  9. ruby-on-rails - 如何在发布新的 Ruby 或 Rails 版本时收到通知? - 2

    有人知道在发布新版本的Ruby和Rails时收到电子邮件的方法吗?他们有邮件列表,RubyonRails有一个推特,但我不想听到那些随之而来的喧嚣,我只想知道什么时候发布新版本,尤其是那些有安全修复的版本。 最佳答案 从therailsblog获取提要.http://weblog.rubyonrails.org/feed/atom.xml 关于ruby-on-rails-如何在发布新的Ruby或Rails版本时收到通知?,我们在StackOverflow上找到一个类似的问题:

  10. python - 如何读取 MIDI 文件、更改其乐器并将其写回? - 2

    我想解析一个已经存在的.mid文件,改变它的乐器,例如从“acousticgrandpiano”到“violin”,然后将它保存回去或作为另一个.mid文件。根据我在文档中看到的内容,该乐器通过program_change或patch_change指令进行了更改,但我找不到任何在已经存在的MIDI文件中执行此操作的库.他们似乎都只支持从头开始创建的MIDI文件。 最佳答案 MIDIpackage会为您完成此操作,但具体方法取决于midi文件的原始内容。一个MIDI文件由一个或多个音轨组成,每个音轨是十六个channel中任何一个上的

随机推荐