Magento 2 Подтверждение заказа по электронной почте Отправить Программно с Success.php


Я отключил электронное письмо с подтверждением заказа от серверной части, потому что я хочу отправлять электронное письмо с заказом при перенаправлении пользователя на Success.phtml после успешного размещения заказа.

Я создал для него плагины di.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
   <preference for="Magento\Checkout\Block\Onepage\Success" type="<vendor_name>\Checkout\Block\Onepage\Success"/>
    <type name="Magento\Sales\Model\Order\Email\Sender">
        <plugin name="sale_order_custom_email_send" type="<vendor_name>\Checkout\Model\Plugin\Sender" sortOrder="1" />
    </type>
    <type name="Magento\Sales\Model\Order\Email\Sender\OrderSender">
        <plugin name="sale_order_sender_custom_email" type="<vendor_name>\Checkout\Model\Plugin\OrderSender" sortOrder="1" />
    </type>
</config>

Создан Вокруг Плагина: OrderSender.php

<?php

namespace <vendor_name>\Checkout\Model\Plugin;

use Magento\Sales\Model\Order;

class OrderSender
{
    /**
     * Order success action.
     *
     * @return \Magento\Framework\Controller\ResultInterface
     */
    public function aroundSend(\Magento\Sales\Model\Order\Email\Sender\OrderSender $subject, \Closure $proceed, Order $order, $forceSyncMode = false, $isCustom = false)
    {
       $order->setSendEmail(true);
        if (!$this->globalConfig->getValue('sales_email/general/async_sending') || $forceSyncMode) {
            if ($this->checkAndSend($order, $isCustom)) {
                $order->setEmailSent(true);
                $this->orderResource->saveAttribute($order, ['send_email', 'email_sent']);
                return true;
            }
        }

        $this->orderResource->saveAttribute($order, 'send_email');

        return false;
   }
}

Я передал параметр $isCustom в метод checkAndSend(), чтобы он мог проверить мое пользовательское условие.

Второй плагин : Sender.php

<?php

namespace <vendor_name>\Checkout\Model\Plugin;

class Sender
{
    /**
     * Order success action.
     *
     * @return \Magento\Framework\Controller\ResultInterface
     */
    protected function aroundCheckAndSend(\Magento\Sales\Model\Order\Email\Sender $subject, \Closure $proceed, Order $order, $isCustom = false)
    {
       $this->identityContainer->setStore($order->getStore());
        if (!$this->identityContainer->isEnabled() && $isCustom = false) {
            return false;
        }
        $this->prepareTemplate($order);

        /** @var SenderBuilder $sender */
        $sender = $this->getSender();

        try {
            $sender->send();
            $sender->sendCopyTo();
        } catch (\Exception $e) {
            $this->logger->error($e->getMessage());
        }

        return true;
   }
}

Если $isCustom равно true, то даже если Подтверждение заказа Отключенный от серверной части, он должен отправить клиенту электронное письмо с подтверждением заказа.

Не знаю, где я ошибаюсь, но не получаю никакого электронного письма. Может быть, мы не можем создать плагин для защищенного метода класса Abstract, но любое другое решение для изменения условия в checkAndSend().

Буду признателен за любую помощь.

Author: Suresh Chikani, 2017-07-05

1 answers

Как вы указали в своем вопросе, что отключили электронное письмо с подтверждением заказа от серверной части, я предположил то же самое и написал код таким образом, чтобы электронное письмо не отправлялось дважды, даже если вы включили электронное письмо с подтверждением заказа от серверной части. Таким образом, электронное письмо с подтверждением заказа будет отправлено со страницы успеха только в том случае, если вы отключили его из бэкэнда.

Чтобы отправить электронное письмо на странице успеха заказа, нам нужно связать наблюдателя с событием проверка_onepage_controller_success_action. Здесь мы пишем наш код отправки почты. Чтобы гарантировать, что электронная почта не отправляется дважды, я создал плагин для isenable() метода OrderIdentity.php класс из модуля Magento_sales.

Во-первых, вам необходимо зарегистрировать событие с помощью events.xml . Проверьте приведенный ниже код.

[ имя_пакета]\[имя_модуля]\etc\frontend\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="checkout_onepage_controller_success_action">
        <observer name="checkout_onepage_controller_success_action_sendmail" instance="[Package_Name]\[Module_Name]\Observer\SendMailOnOrderSuccess" />
    </event>
</config>

После регистрации события мы создадим Наблюдателя Класс.

[ имя_пакета]\[имя_модуля]\Observer\SendMailOnOrderSuccess.php

<?php

namespace [Package_Name]\[Module_Name]\Observer;

use Magento\Framework\Event\ObserverInterface;

class SendMailOnOrderSuccess implements ObserverInterface
{
    /**
     * @var \Magento\Sales\Model\OrderFactory
     */
    protected $orderModel;

    /**
     * @var \Magento\Sales\Model\Order\Email\Sender\OrderSender
     */
    protected $orderSender;

    /**
     * @var \Magento\Checkout\Model\Session $checkoutSession
     */
    protected $checkoutSession;

    /**
     * @param \Magento\Sales\Model\OrderFactory $orderModel
     * @param \Magento\Sales\Model\Order\Email\Sender\OrderSender $orderSender
     * @param \Magento\Checkout\Model\Session $checkoutSession
     *
     * @codeCoverageIgnore
     */
    public function __construct(
        \Magento\Sales\Model\OrderFactory $orderModel,
        \Magento\Sales\Model\Order\Email\Sender\OrderSender $orderSender,
        \Magento\Checkout\Model\Session $checkoutSession
    )
    {
        $this->orderModel = $orderModel;
        $this->orderSender = $orderSender;
        $this->checkoutSession = $checkoutSession;
    }

    /**
     * @param \Magento\Framework\Event\Observer $observer
     * @return void
     */
    public function execute(\Magento\Framework\Event\Observer $observer)
    {
        $orderIds = $observer->getEvent()->getOrderIds();
        if(count($orderIds))
        {
            $this->checkoutSession->setForceOrderMailSentOnSuccess(true);
            $order = $this->orderModel->create()->load($orderIds[0]);
            $this->orderSender->send($order, true);
        }
    }
}

После добавления наблюдателя электронное письмо с подтверждением заказа будет отправлено на странице успеха заказа, если мы включили электронное письмо с подтверждением заказа от Магазины > Конфигурация > Продажи > Электронная почта продаж > Заказ. Но теперь подтверждение заказа отправляется дважды, если мы включим это поле. Итак, нам нужно создать плагин, чтобы избежать этого сценария.

Для создания плагина вам необходимо использовать di.xml.

[ имя_пакета]\[имя_модуля]\etc\di.xml

<?xml version="1.0"?>

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <type name="Magento\Sales\Model\Order\Email\Container\OrderIdentity">
        <plugin name="change_is_enable_method" type="\[Package_Name]\[Module_Name]\Plugin\Sales\Order\Email\Container\OrderIdentityPlugin"/>
    </type>
</config>

[ Имя_пакета]\[имя_модуля]\Плагин\Продажи\Заказ\Заказ\Электронная почта\Контейнер\ OrderIdentityPlugin.php

<?php

namespace [Package_Name]\[Module_Name]\Plugin\Sales\Order\Email\Container;

class OrderIdentityPlugin
{
    /**
     * @var \Magento\Checkout\Model\Session $checkoutSession
     */
    protected $checkoutSession;

    /**
     * @param \Magento\Checkout\Model\Session $checkoutSession
     *
     * @codeCoverageIgnore
     */
    public function __construct(
        \Magento\Checkout\Model\Session $checkoutSession
    )
    {
        $this->checkoutSession = $checkoutSession;
    }

    /**
     * @param \Magento\Sales\Model\Order\Email\Container\OrderIdentity $subject
     * @param callable $proceed
     * @return bool
     */
    public function aroundIsEnabled(\Magento\Sales\Model\Order\Email\Container\OrderIdentity $subject, callable $proceed)
    {
        $returnValue = $proceed();

        $forceOrderMailSentOnSuccess = $this->checkoutSession->getForceOrderMailSentOnSuccess();
        if(isset($forceOrderMailSentOnSuccess) && $forceOrderMailSentOnSuccess)
        {
            if($returnValue)
                $returnValue = false;
            else
                $returnValue = true;

            $this->checkoutSession->unsForceOrderMailSentOnSuccess();
        }

        return $returnValue;
    }
}
 6
Author: Hitarth Pattani, 2017-07-05 10:30:59