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()
.
Буду признателен за любую помощь.
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;
}
}