HowTo: Create an Alternative Success Page for a Payment Method in Magento2
This week I had the task to build an alternative success page for customers who pay with a specific payment method.
If the customers select Bank Transfer method they should be redirected to https://magento2.test/checkout/banktransfer/success
.
If any other payment method is selected the customer should be redirected to the default success page https://magento2.test/checkout/onepage/success/
.
Looks simple right? Let's see how can we achieve this.
This post assumes that there is already a custom module created in app/code/Vendor/BanckTransfer
. If you need to know how to
create a custom module, please look at How to create a custom module for Magento 2.
What we need to do
- First, we need a controller to handle the request for
https://magento2.test/checkout/BanckTransfer/success
url. - Next we will need a way to redirect customers when selecting the BanTransfer Payment method to the new success page.
The Controller
To create a controller, first declare the route.
<?xml version="1.0"?>
<!--//app/code/Vendor/BanTransfer/etc/frontend/routes.xml -->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/routes.xsd">
<router id="standard">
<route id="checkout">
<module name="Vendor_BanTransfer"/>
</route>
</router>
</config>
Notice: Because we are adding an extra page to the checkout we use checkout
for the route and we don't need to specify a frontName.
Next, we need to make sure our module extends Magento_Checkout
. If we don't, our custom success page is not going to work.
Also and because we are going to modify the behavior of Bank Transfer payment method, a method that comes with Magento, we need to load our custom module AFTER it.
<?xml version="1.0"?>
<!--//app/code/Vendor/BanTransfer/etc/module.xml -->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
<module name="Vendor_BanTransfer" setup_version="1.0.0">
<sequence>
<module name="Magento_Checkout"/>
<module name="Magento_OfflinePayments"/>
</sequence>
</module>
</config>
With these two changes in place, we can now proceed to create the Controller.
<?php
/** app/code/Vendor/BanTransfer/Controller/BanTransfer/Success.php */
namespace Vendor\BanTransfer\Controller\BanTransfer;
use Magento\Checkout\Model\Session\SuccessValidator;
use Magento\Checkout\Model\Type\Onepage;
use Magento\Framework\App\Action\Action;
use Magento\Framework\App\Action\Context;
use Magento\Framework\App\ResponseInterface;
use Magento\Framework\Controller\Result\Redirect;
use Magento\Framework\Controller\ResultInterface;
use Magento\Framework\View\Result\Page;
use Magento\Framework\View\Result\PageFactory;
class Success extends Action
{
/**
* @var SuccessValidator
*/
private $successValidator;
/**
* @var Onepage
*/
private $onepage;
/**
* @var PageFactory
*/
private $resultPageFactory;
/**
* Success constructor.
* @param SuccessValidator $successValidator
* @param Onepage $onepage
* @param PageFactory $resultPageFactory
* @param Context $context
*/
public function __construct(
SuccessValidator $successValidator,
Onepage $onepage,
PageFactory $resultPageFactory,
Context $context
) {
$this->successValidator = $successValidator;
$this->onepage = $onepage;
$this->resultPageFactory = $resultPageFactory;
parent::__construct($context);
}
/**
* @return ResponseInterface|Redirect|ResultInterface|Page
*/
public function execute()
{
$checkout = $this->onepage->getCheckout();
if (!$this->successValidator->isValid()) {
return $this->resultRedirectFactory->create()->setPath('checkout/cart');
}
$checkout->clearQuote();
$resultPage = $this->resultPageFactory->create();
$this->_eventManager->dispatch(
'checkout_onepage_controller_success_action',
['order_ids' => [$checkout->getLastOrderId()]]
);
return $resultPage;
}
}
You can see this is pretty much a copy of the core Controller in vendor/magento/module-checkout/Controller/Onepage/Success.php
.
Now we need to create a layout to specify the template file.
<?xml version="1.0"?>
<!-- // app/code/Vendor/BanTransfer/view/frontend/layout/checkout_banTransfer_success.xml -->
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="1column" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
<head>
<title>BanTransfer Success Page</title>
</head>
<body>
<referenceBlock name="page.main.title">
<block class="Magento\Checkout\Block\Onepage\Success" name="checkout.success.print.button" template="Magento_Checkout::button.phtml"/>
<action method="setPageTitle">
<argument translate="true" name="title" xsi:type="string">Thank you for your purchase!</argument>
</action>
</referenceBlock>
<referenceContainer name="content">
<block class="Magento\Checkout\Block\Onepage\Success" name="checkout.success" template="Vendor_BanTransfer::checkout/success.phtml" cacheable="false">
<container name="order.success.additional.info" label="Order Success Additional Info"/>
</block>
<block class="Magento\Checkout\Block\Registration" name="checkout.registration" template="Magento_Checkout::registration.phtml" cacheable="false"/>
</referenceContainer>
</body>
</page>
Again this is a copy of the file in vendor/magento/module-checkout/view/frontend/layout/checkout_onepage_success.xml
. The only difference is the success.phtml
where we specified our custom template.
Finally, we will create the template file that is going to be rendered when a customer visit the new url.
<?php /** app/code/Vendor/BanTransfer/view/frontend/templates/checkout/success.phtml */ ?>
<?php /** @var $block \Magento\Checkout\Block\Onepage\Success */ ?>
<div class="checkout-success">
<?php if ($block->getOrderId()):?>
<?php if ($block->getCanViewOrder()) :?>
<p><?= __('Your order number is: %1.', sprintf('<a href="%s" class="order-number"><strong>%s</strong></a>', $block->escapeHtml($block->getViewOrderUrl()), $block->escapeHtml($block->getOrderId()))) ?></p>
<?php else :?>
<p><?= __('Your order # is: <span>%1</span>.', $block->escapeHtml($block->getOrderId())) ?></p>
<?php endif;?>
<p><?= /* @escapeNotVerified */ __('We\'ll email you an order confirmation with details and tracking info.') ?></p>
<?php endif;?>
<?= $block->getAdditionalInfoHtml() ?>
<div class="actions-toolbar">
<div class="primary">
<a class="action primary continue" href="<?= /* @escapeNotVerified */ $block->getContinueUrl() ?>"><span><?= /* @escapeNotVerified */ __('Continue Shopping') ?></span></a>
</div>
</div>
</div>
So far we have a controller that handles the request when a customer visit the url https://magento2.test/checkout/banTransfer/success
but now we need a mechanism to redirect customers to the new url when placing an order is place using Bank Transfer Payment method.
The Redirect
<?xml version="1.0"?>
<!-- // app/code/Vendor/BanTransfer/view/frontend/layout/checkout_index_index.xml-->
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
<body>
<referenceBlock name="checkout.root">
<arguments>
<argument name="jsLayout" xsi:type="array">
<item name="components" xsi:type="array">
<item name="checkout" xsi:type="array">
<item name="children" xsi:type="array">
<item name="steps" xsi:type="array">
<item name="children" xsi:type="array">
<item name="billing-step" xsi:type="array">
<item name="children" xsi:type="array">
<item name="payment" xsi:type="array">
<item name="children" xsi:type="array">
<item name="renders" xsi:type="array">
<item name="children" xsi:type="array">
<item name="offline-payments" xsi:type="array">
<item name="component" xsi:type="string">Vendor_BanTransfer/js/view/payment/offline-payments</item>
<item name="methods" xsi:type="array">
<item name="banktransfer" xsi:type="array">
<item name="isBillingAddressRequired" xsi:type="boolean">true</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</argument>
</arguments>
</referenceBlock>
</body>
</page>
Next we create the component file
// app/code/Vendor/BanTransfer/view/frontend/web/js/view/payment/offline-payments.js
define([
'uiComponent',
'Magento_Checkout/js/model/payment/renderer-list'
], function (Component, rendererList) {
'use strict';
rendererList.push(
{
type: 'checkmo',
component: 'Magento_OfflinePayments/js/view/payment/method-renderer/checkmo-method'
},
{
type: 'banktransfer',
component: 'Vendor_BanTransfer/js/view/payment/method-renderer/banktransfer-method'
},
{
type: 'cashondelivery',
component: 'Magento_OfflinePayments/js/view/payment/method-renderer/cashondelivery-method'
},
{
type: 'purchaseorder',
component: 'Magento_OfflinePayments/js/view/payment/method-renderer/purchaseorder-method'
}
);
return Component.extend({});
});
Finally, we add the new banktransfer-method
file.
// app/code/Vendor/Finance/view/frontend/web/js/view/payment/offline-payments.js
define([
'uiComponent',
'Magento_Checkout/js/model/payment/renderer-list'
], function (Component, rendererList) {
'use strict';
rendererList.push(
{
type: 'checkmo',
component: 'Magento_OfflinePayments/js/view/payment/method-renderer/checkmo-method'
},
{
type: 'banktransfer',
component: 'Vendor_Finance/js/view/payment/method-renderer/banktransfer-method'
},
{
type: 'cashondelivery',
component: 'Magento_OfflinePayments/js/view/payment/method-renderer/cashondelivery-method'
},
{
type: 'purchaseorder',
component: 'Magento_OfflinePayments/js/view/payment/method-renderer/purchaseorder-method'
}
);
return Component.extend({});
});
Before test the result, make sure to flush the cache.