How To Custom Payment Method In Checkout Steps in Magento 2

As you might have noticed, the checkout of Magento includes two steps which are Shipping Information and Review and Payment Information, which is quite amazing. Also, on the Review and Payment Information step, the enabled payment methods are displayed.

In today post, I will provide you four simple steps to help you custom payment method in checkout steps.

How to custom payment method in checkout steps

Step 1: Create .js component file

Before going to the first step, there are some points that you need to remember to ensure compatibility, upgradability, and easy maintenance. Firstly, you need to implement your payment method renderer as a UI component. Secondly, instead of editing the default Magento code, please add your customizations in a separate module. Thirdly, for your customizations in the checkout step is applied correctly, your custom module should depend on the Magento_Checkout module. In the module’s composer.json, you can find the module dependencies. And finally, don’t set Ui as the name of the module as %Mageplaza%_Ui, notation required when specifying paths, can cause various issues.

Now, let’s create a .js component file also known as payment method renderer in your custom module directory. Remember that this file must be located under the <your_module_dir>/view/frontend/web/js/view/ directory. For instance, with Magento modules, you can store the payment methods renderers in the directory <Magento_module_dir>/view/frontend/web/js/view/payment/method-renderer/

Normally, the default payment method component which is inplemented in the <Magento_Checkout_module_dir>/view/frontend/web/js/view/payment/default.js file will be extended. Below I will help provide you the default component’s methods list which includes all methods and their description.

Method Description
getCode():string When you use this, the payment method’s code will be returned
getData():object This method will return you an object, which has the payment data on selecting a payment method or extension, to be sent to the server. This object has to include the data according to \Magento\Quote\Api\Data\PaymentInterface. Apart from the method code and purchase order number, all the information about the payment will be passed in the additional_data field.
placeOrder():bool If all the validations passed, an order will be placed
selectPaymentMethod():bool This allows you to add information about the payment method which is picked by the user to the Quote JS object
isChecked():string It will return the selected payment method’s code
isRadioButtonVisible():bool If only one payment method is available, the result that it returns will be true
getTitle():string The title of the payment method will be returned
validate():bool This is used in the placeOrder() method. It allows you to override validate() in your module. Also, this validation will be displayed in the placeOrder() scope
getBillingAddressFormName():string You will be able to get the unique billing address name
disposeSubscriptions() The subscription of the object will be terminated

Following code is the payment method renderer’s general view:

define(
    [
        'Magento_Checkout/js/view/payment/default'
    ],
    function (Component) {
        'use strict';
        return Component.extend({
            defaults: {
                template: '%path to template%'
            },
            // add required logic here
        });
    }
);

In case the credit cards information is required in your payment method, you might need to use the Magento rederer to implement a credit card form: [/view/frontend/web/js/view/payment/cc-form.js](https://github.com/magento/magento2/blob/2.1/app/code/Magento/Payment/view/frontend/web/js/view/payment/cc-form.js). It can also extend the default payment rederer by using its own methods which are listed below:

Method Description
getData():object This method will return you an object, which has the payment data on selecting a payment method or extension, to be sent to the server. This object has to include the data according to \Magento\Quote\Api\Data\PaymentInterface. Apart from the method code and purchase order number, all the information about the payment will be passed in the additional_data field. Credit card data such as type, issue date, number, CVV will be added.
getCcAvailableTypes():array The results will be the list which includes all available credit card types
getIcons():bool Links to the images for credit card types which is available
getCcMonths():object The month of the credit card expiration date will be retrieved
getCcYears():object The year of the credit card expiration date will be retrieved
hasVerification():bool A flag which shows if the CVV number of the credit card is required for the payment
hasSsCardType():bool If the Solo and Switch (Maestro) card type are available, the return will be true
getCvvImageUrl():string The CVV tooltip image URL will be retrieved
getCvvImageHtml():string The CVV tooltip image HTML will be retrieved
getSsStartYears():object Returns the start year of Solo or Switch (Maestro) card

Access data of system config

In some situation, your payment method may need to get the data which cannot be defined in layout configuration, JS components or even templates directly such as data from the Magento system config. This data is stored in the window.checkoutConfig variable which is defined in the root checkout template.

To access the system configuration, a payment method or a group of methods need to implement the \Magento\Checkout\Model\ConfigProviderInterface interface. At the same time, the class which implements it has to be injected to the composite config provider through DI frontend configuration. In the following code, I will illustrate this:

Here is a sample .php class which implements \Magento\Checkout\Model\ConfigProviderInterface:

class MyCustomPaymentConfigProvider implements \Magento\Checkout\Model\ConfigProviderInterface
{
...
    public function getConfig()
    {
        return [
            // 'key' => 'value' pairs of configuration
        ];
    }
...
}

Here is a sample DI configuration file of a custom module <your_module_dir>/etc/frontend/di.xml:

...
<type name="Magento\Checkout\Model\CompositeConfigProvider">
    <arguments>
        <argument name="configProviders" xsi:type="array">
            ...
            <item name="%Custom_provider_name%" xsi:type="object">MyCustomPaymentConfigProvider</item>
            ...
        </argument>
    </arguments>
...
</type>

Other features which are related to payment such as reward points, gift registry can also be added to the Review and Payment Information checkout step. However, they should be implemented as UI components. And these features can be dispayed before or after the payment methods’ list. You can configure this in the checkout page layout file correspondingly.

Step 2: Create .js component registered renderer

In this step, create the .js UI component which registers the payment method renderer in the renderers list in your custom module directory. Remeber to locate it under the directory <your_module_dir>/view/frontend/web/js/view/. For instance, in Magento modules, the payment methods renderers are located in the directory <Magento_module_dir>/view/frontend/web/js/view/payment/.

The content of the file need to be similar to this:

define(
    [
        'uiComponent',
        'Magento_Checkout/js/model/payment/renderer-list'
    ],
    function (
        Component,
        rendererList
    ) {
        'use strict';
        rendererList.push(
            {
                type: '%payment_method_code%',
                component: '%js_renderer_component%'
            },
            // other payment method renderers if required
        );
        /** Add view logic here if needed */
        return Component.extend({});
    }
);

If several payment methods are added to your module, you can register all the renderers of those methods in one file.

Step 3: Create template for payment method component

After following the above steps, now you are going to create a new file in your custom module directory, which is <your_module_dir>/view/frontend/web/template/<your_template>.html. Knockout JS syntax can be used for the template. If you want to fine a sample .html template, you will see it in any module which implements payment methods like the Magento_Authorizenet module.

Here is the template for rendering the Authorize.Net payment method in checkout: [/view/frontend/web/template/payment/authorizenet-directpost.html](https://github.com/magento/magento2/blob/2.1/app/code/Magento/Authorizenet/view/frontend/web/template/payment/authorizenet-directpost.html)

Step 4: Declare payment method in layout

Finally, in your custom directory, you need to create a new <your_module_dir>/view/frontend/layout/checkout_index_index.xml file. And in that file, add the following code:

<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="component" xsi:type="string">uiComponent</item>
                                            <item name="children" xsi:type="array">
                                                <item name="payment" xsi:type="array">
                                                    <item name="children" xsi:type="array">
                                                        <!-- Declare additional before payment components. START -->
                                                        <item name="beforeMethods" xsi:type="array">
                                                            <item name="component" xsi:type="string">uiComponent</item>
                                                            <item name="displayArea" xsi:type="string">beforeMethods</item>
                                                            <item name="children" xsi:type="array">
                                                                <item name="%your_feature_name%" xsi:type="array">
                                                                    <item name="component" xsi:type="string">%path/to/your/feature_js_component%</item>
                                                                </item>
                                                            </item>
                                                        </item>
                                                        <!-- Declare additional before payment components. END -->
                                                        <!-- Declare the payment method (the component that registrates in the list). START -->
                                                        <item name="renders" xsi:type="array">
                                                            <item name="children" xsi:type="array">
                                                                <item name="%group name of the payment methods%" xsi:type="array">
                                                                    <!-- Example of value: Magento_Authorizenet/js/view/payment/authorizenet-->
                                                                    <item name="component" xsi:type="string">%component_that_registers_payment_renderer%</item>
                                                                    <item name="methods" xsi:type="array">

                                                                        <!-- Add this if your payment method requires entering a billing address-->
                                                                        <item name="%payment_method_code%" xsi:type="array">
                                                                            <item name="isBillingAddressRequired" xsi:type="boolean">true</item>
                                                                        </item>
                                                                    </item>
                                                                </item>
                                                            </item>
                                                            <!-- Declare the payment method (the component that registrates in the list). END -->
                                                            <!-- Declare additional after payment components. START -->
                                                            <item name="afterMethods" xsi:type="array">
                                                                <item name="component" xsi:type="string">uiComponent</item>
                                                                <item name="displayArea" xsi:type="string">afterMethods</item>
                                                                <item name="children" xsi:type="array">
                                                                    <item name="%your_feature_name%" xsi:type="array">
                                                                        <item name="component" xsi:type="string">%path/to/your/feature_js_component%</item>
                                                                    </item>
                                                                </item>
                                                            </item>
                                                            <!-- Declare additional after payment components. END -->
                                                        </item>
                                                    </item>
                                                </item>
                                            </item>
                                        </item>
                                    </item>
                                </item>
                            </item>
                        </item>
                    </item>
                </argument>
            </arguments>
        </referenceBlock>
    </body>
</page>

To view the checkout_index_index.xml illustration where declares a new payment method, please view app/code/Magento/Authorizenet/view/frontend/layout/checkout_index_index.xml

Conclusion

I have just provided you four steps to help you custom a new payment method in checkout steps, hope this instruction is helpful for you. If you have any questions or new ideas, feel free to leave a comment below.

Custom Payment Method with One step checkout!

Enjoyed the tutorial? Spread it to your friends!