Magento2销售发票电子邮件未发送

Magento2 运行环境条件

  1. Magento 2.3.1
  2. OS: Ubuntu 16.04
  3. Mysql version 5.7.21
  4. PHP version 7.0.22

Steps to reproduce

  1. Set up “Stores -> Settings -> Configuration -> Sales -> Sales Emails -> Invoice -> Enabled -> Yes”
  2. Configure PayPal “Stores -> Settings -> Configuration -> Sales -> Payment Methods -> PayPal -> Payment Action -> Sale”
  3. Make order and pay with PayPal.

Expected result

  1. Order Created
  2. Email with order information send.
  3. Invoice Created
  4. Email with invoice information send

Actual result

  1. Order Created <- ok
  2. Email with order information send. <- ok
  3. Invoice Created <- ok
  4. Email with invoice information is not send <- wrong

Magento CE 2.3.1 使用Paypal付款之后,未发送发票电子邮件,经过仔细分析是因为Magento 开发团队只做了订单邮件发送,未做发票发送,该功能已经在magento CE 2.3.4 的 Vendor /magento/module-quote/Observer/SubmitObserver 中修复。

在Magento 2.3.1 Vendor /magento/module-quote/Observer/SubmitObserver 中只有订单邮件发送代码如下:

 public function execute(\Magento\Framework\Event\Observer $observer)
    {
        /** @var  \Magento\Quote\Model\Quote $quote */
        $quote = $observer->getEvent()->getQuote();
        /** @var  \Magento\Sales\Model\Order $order */
        $order = $observer->getEvent()->getOrder();

        /**
         * a flag to set that there will be redirect to third party after confirmation
         */
        $redirectUrl = $quote->getPayment()->getOrderPlaceRedirectUrl();
        if (!$redirectUrl && $order->getCanSendNewEmailFlag()) {
            try {
                $this->orderSender->send($order);
            } catch (\Exception $e) {
                $this->logger->critical($e);
            }
        }
    }
}

在Magento 2.3.4 Vendor /magento/module-quote/Observer/SubmitObserver 中发送订单和发票邮件代码如下:

 public function execute(Observer $observer)
    {
        /** @var  Quote $quote */
        $quote = $observer->getEvent()->getQuote();
        /** @var  Order $order */
        $order = $observer->getEvent()->getOrder();

        /**
         * a flag to set that there will be redirect to third party after confirmation
         */
        $redirectUrl = $quote->getPayment()->getOrderPlaceRedirectUrl();
        if (!$redirectUrl && $order->getCanSendNewEmailFlag()) {
            try {
                $this->orderSender->send($order);
                $invoice = current($order->getInvoiceCollection()->getItems());
                if ($invoice) {
                    $this->invoiceSender->send($invoice);
                }
            } catch (\Exception $e) {
                $this->logger->critical($e);
            }
        }
    }

本文参考:

那么在Magento2.3.1中怎么解决发送发票邮件呢

在这里我们重新定义模块,使用magento2的事件分发机制,来解决该问题。

重新创建模块ChuWu_AutoInvoiceEmail

第一步:创建文件夹ChuWu/AutoInvoiceEmail /etc,并在etc文件夹里面添加module.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
    <module name="ChuWu_AutoInvoiceEmail" setup_version="1.0.0">
    </module>
</config>

第二步:在文件夹ChuWu/AutoInvoiceEmail /下面,创建 registration.php 文件并添加如下代码。

<?php

\Magento\Framework\Component\ComponentRegistrar::register(
    \Magento\Framework\Component\ComponentRegistrar::MODULE,
    'ChuWu_AutoInvoiceEmail',
    __DIR__
);

第三步:在文件夹ChuWu/AutoInvoiceEmail /etc下面创建events.xml文件,并添加如下代码。

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">
    <event name="sales_model_service_quote_submit_success">
        <observer name="chuwu_autoinvoiceemail_send" instance="ChuWu\AutoInvoiceEmail\Observer\InvoiceEmailObserver" />
    </event>
</config>

第四步:在文件夹ChuWu/AutoInvoiceEmail /文件夹下面创建Observer文件夹并在该文件夹里面创建InvoiceEmailObserver.php文件

/app/code/ChuWu/AutoInvoiceEmail/Observer/InvoiceEmailObserver.php

第五步:在InvoiceEmailObserver.php添加如下代码:

<?php

/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */

namespace ChuWu\AutoInvoiceEmail\Observer;

use Magento\Framework\Event\Observer;
use Magento\Framework\Event\ObserverInterface;
use Magento\Quote\Model\Quote;
use Magento\Sales\Model\Order;
use Magento\Sales\Model\Order\Email\Sender\InvoiceSender;
use Magento\Sales\Model\Order\Email\Sender\OrderSender;
use Psr\Log\LoggerInterface;

use ChuWu\Test\Helper\Data as CCData;


/**
 * Class responsive for sending order and invoice emails when it's created through storefront.
 */
class InvoiceEmailObserver implements ObserverInterface
{
    /**
     * @var LoggerInterface
     */
    private $logger;

    /**
     * @var OrderSender
     */
    private $orderSender;

    /**
     * @var InvoiceSender
     */
    private $invoiceSender;

    /**
     * @var CCData
     */
    private $ccHelper;

    /**
     * @param LoggerInterface $logger
     * @param OrderSender $orderSender
     * @param InvoiceSender $invoiceSender
     * @param CCData $ccHelper
     */
    public function __construct(
        LoggerInterface $logger,
        OrderSender $orderSender,
        InvoiceSender $invoiceSender,
        CCData $ccHelper
    )
    {
        $this->logger = $logger;
        $this->orderSender = $orderSender;
        $this->invoiceSender = $invoiceSender;
        $this->ccHelper = $ccHelper;
    }

    /**
     * Send order and invoice email.
     *
     * @param Observer $observer
     *
     * @return void
     */
    public function execute(Observer $observer)
    {
        /** @var  Quote $quote */
        $quote = $observer->getEvent()->getQuote();
        /** @var  Order $order */
        $order = $observer->getEvent()->getOrder();

        /**
         * a flag to set that there will be redirect to third party after confirmation
         */
        $redirectUrl = $quote->getPayment()->getOrderPlaceRedirectUrl();
        if (!$redirectUrl && $order->getCanSendNewEmailFlag()) {
            try {
                //记录重复发送订单邮件的日志
               $this->ccHelper->LogData('the second send order email:',[]);
               //$this->orderSender->send($order);
                $invoice = current($order->getInvoiceCollection()->getItems());
                if ($invoice) {
                    $this->invoiceSender->send($invoice);
                    //记录发票邮件发送日志
                    $this->ccHelper->LogData('发送发票邮寄:',[]);
                }else{
                    //记录没有生成发票,不发送发票邮件
                    $this->ccHelper->LogData('没有创建发票信息:',[]);
                }
            } catch (\Exception $e) {
                $this->logger->critical($e);
            }
        }
    }
}

在该代码里面需要注释掉 // $this->orderSender->send($order); 发送订单邮件功能,或者不写,如果不这样操作。订单邮件将会多发送一封邮件,因为之前的事件机制调用过订单发送邮件的功能,再调用就重复发送了。

第六步:代码保存上传并执行下面的命令行操作:

php bin/magento setup:upgrade
php bin/magento setup:di:compile

第七步:使用paypal支付下单测试,在这里paypal配置Payment Action 的参数为Sale.如果是Authorization 则不会生成发票更不会发送邮件,这个时候需要网站管员在订单后台手动创建发票,并发送发票邮件。

第八步:支付测试,收到下面邮件,并记录日志文件如下:

[2021-01-28 08:03:41] customLogger.INFO: the second send order email: [] []
[2021-01-28 08:03:45] customLogger.INFO: send  invoice email: [] []

但是查看邮件的收件列表,发现一个问题,发票邮件先发送,订单邮件后发送。

分析原因是magento2先执行了我写的事件,后执行magento2自身的事件。我在想有没有什么办法,设置事件的执行顺序呢 。