Como: Crear una pagina de success diferente para un método de pago en Magento2

Esta semana, me asignaron la tarea de crear una página de success diferente para un método de pago específico.

La idea era que si un cliente seleccionaba el método de pago Transferencia Bancaria, fuese redirigido a https://magento2.test/checkout/banktransfer/success. Por el contrario si el cliente selecciona cualquier otro método de pago, debería ser redirigido a la página de success por defecto, es decir https://magento2.test/checkout/onepage/success/.

Parece simple verdad?, veamos como se puede lograr esto.

Este post asume que existe ya un módulo de Magento con la ruta app/code/Vendor/BanckTransfer. Si necesitas saber como crear un nuevo module, te recomiendo que le eches un vistazo a Cómo crear un nuevo módulo para Magento 2.

Requerimientos

  1. Primero que nada necesitamos un controlador que responda a las peticiones en la Url https://magento2.test/checkout/BanckTransfer/success.
  2. Luego, necesitaremos que el checkout redirija a la nueva Url, solo cuando Transferencia bancaria sea seleccionado como método de pago.

El Controlador

Antes de crear el controlador, primero especificamos el 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>

Nota: Debido a que estamos agregando una página adicional al pago, usamos checkout para la ruta y no necesitamos especificar un frontName.

A continuación, debemos asegurarnos de que nuestro módulo extienda Magento_Checkout. Si no lo hacemos, nuestra página de éxito personalizada no funcionará. Además y debido a que vamos a modificar el comportamiento del método de pago Transferencia Bancaria, (método que viene con Magento), necesitamos cargar nuestro módulo personalizado DESPUÉS.

<?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>

Con estos dos cambios implementados, ahora podemos proceder a crear el Controlador.

<?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;
    }
}

Puedes ver que esto es prácticamente una copia del controlador en vendor/magento/module-checkout/Controller/Onepage/Success.php.

Ahora necesitamos crear un layout para especificar el archivo de plantilla.

<?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>

Nuevamente, esta es una copia del archivo en vendor/magento/module-checkout/view/frontend/layout/checkout_onepage_success.xml. La única diferencia es el success.phtml donde especificamos nuestra plantilla personalizada.

Finalmente, crearemos el archivo de plantilla que se renderizará cuando un cliente visite la nueva 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>

Hasta este punto, tenemos ya creado un controlador que responderá a la solicitud cuando el cliente visite la url https://magento2.test/checkout/banTransfer/success ahora necesitamos un mecanismo para redirigir a los clientes a la nueva URL cuando se realice un pedido utilizando el método de pago mediante transferencia bancaria.

La Redirección (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>

A continuación, creamos el archivo del componente

// 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({});
});

Por último, agregamos el nuevo archivo banktransfer-method.

// 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({});
});

Antes de probar el resultado en el frontend, recuerda borrar la caché.

Comentarios

Siguiente Entrada Entrada Anterior