In the normal scenario, after you set up order confirmation Email in the Magento 2 customers receive order confirmation Email immediately after the order is placed. As online purchases don’t allow them to get their products instantly, the confirmation gives them the patience to wait for the delivery after they have spent their money! Such a service is helpful for customer satisfaction and hence improving the customer experience of your store!
Default Magento automatically sends a confirmation Email once the order is placed. But the question is what if the payment is done via a third party payment gateway or what if the card is declined and payment fails? Default Magento 2 falls short in such a situation. So I have come up with custom code to allow to send order confirmation Email after payment success in Magento 2.
To send email confirmation on successful order payment, we need to tie Magento 2 observer with an event of checkout_onepage_controller_success_action.
Create a simple method isEnable() using OrderIdentity.php to ensure that order confirmation email is not sent twice.
Register event under events.xml using below code
[Package_Name]\[Module_Name]\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>
Once the event is registered, create Observer class in the following file:
[Package_Name]\[Module_Name]\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); } } }
After adding observer code, an email will be sent to customers on successful order payment. To avoid order duplication Email, we need to create a plugin using the di.xml file.
[Package_Name]\[Module_Name]\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>
Create another file along with ‘di.xml’ that is OrderIdentityPlugin.php to remove duplication of email.
[Package_Name]\[Module_Name]\Plugin\Sales\Order\Email\Container\ 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; } }
There you go!
Now you may start sending the order confirmation Emails to your customers only after the payment is successful. ?
Start Emailing today itself. We’d love to hear how your order Emails are now organized in a better way.
Thank you!