Magento 2: Create a new Payment Method

Magento 2 provides flexible way for adding custom payment methods in the existing payment methods. Like any other function we sometime needs our own custom payment methods for receiving the payments.
In this example we will consider payment by installment methods as our custom payment method.
For creating your own custom module in Magento 2 we will start by registering or module using registration.php and module.xml.Once we have created our module registration files we will start creating the custom payment method.
Custom payment methods appear in the configuration section so for that we need to create a system.xml and paste the following code in system.xml.

We have declared our payment method as a part of existing payment methods in configuration via giving section id as “payment” you can add your custom name to group id we will use paybyinstallements as our group id.

etc/adminhtml/system.xml
<?xml version="1.0" ?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Config:etc/system_file.xsd">
	<system>
		<section id="payment" sortOrder="1000" showInWebsite="1" showInStore="1" showInDefault="1" translate="label">
			<group id="paybyinstallments" sortOrder="10" showInWebsite="1" showInStore="1" showInDefault="1" translate="label">
				<label>PayByInstallments</label>
				<field id="active" type="select" sortOrder="10" showInWebsite="1" showInStore="1" showInDefault="1" translate="label">
					<label>Enabled</label>
					<source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
				</field>
				<field id="title" type="text" sortOrder="20" showInWebsite="1" showInStore="1" showInDefault="1" translate="label">
					<label>Title</label>
				</field>
				<field id="order_status" type="select" sortOrder="30" showInWebsite="1" showInStore="1" showInDefault="1" translate="label">
					<label>New Order Status</label>
					<source_model>Magento\Sales\Model\Config\Source\Order\Status\NewStatus</source_model>
				</field>
				<field id="allowspecific" type="allowspecific" sortOrder="40" showInWebsite="1" showInStore="1" showInDefault="1" translate="label">
					<label>Payment from Applicable Countries</label>
					<source_model>Magento\Payment\Model\Config\Source\Allspecificcountries</source_model>
				</field>
				<field id="specificcountry" type="multiselect" sortOrder="50" showInWebsite="1" showInStore="1" showInDefault="1" translate="label">
					<label>Payment from Applicable Countries</label>
					<source_model>Magento\Directory\Model\Config\Source\Country</source_model>
					<can_be_empty>1</can_be_empty>
				</field>
				<field id="sort_order" type="text" sortOrder="60" showInWebsite="1" showInStore="1" showInDefault="1" translate="label">
					<label>Sort Order</label>
				</field>
				<field id="instructions" type="textarea" sortOrder="70" showInWebsite="1" showInStore="1" showInDefault="1" translate="label">
					<label>Instructions</label>
				</field>
			</group>
		</section>
	</system>
</config>

The next step is to create config.xml file in which we will add the default values and we will classify the class that is responsible for rendering the custom payment method.

etc/config.xml
<?xml version="1.0" ?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Store:etc/config.xsd">
	<default>
		<payment>
			<paybyinstallments>
				<active>1</active>
				<model>Gm\Module\Model\Payment\PayByInstallments</model>
				<order_status>pending</order_status>
				<title>PayByInstallments</title>
				<allowspecific>0</allowspecific>
				<group>offline</group>
			</paybyinstallments>
		</payment>
	</default>
</config>
etc/payment.xml
<?xml version="1.0" ?>
<payment xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Payment:etc/payment.xsd">
	<groups>
		<group id="offline">
			<label>Offline Payment Methods</label>
		</group>
	</groups>
	<methods>
		<method name="paybyinstallments">
			<allow_multiple_address>1</allow_multiple_address>
		</method>
	</methods>
</payment>

PayByInstallments.php extends the AbstartMethod which we can use to create our own customizations. for example if you only want to enable this method for frontends or backend you can use the isAvailable method .

Model/Payment/PayByInstallments.php
<?php
/**
 * Copyright ©  All rights reserved.
 * See COPYING.txt for license details.
 */
declare(strict_types=1);

namespace Gm\Module\Model\Payment;

class PayByInstallments extends \Magento\Payment\Model\Method\AbstractMethod
{

    protected $_code = "paybyinstallments";
    protected $_isOffline = true;

    public function isAvailable(
        \Magento\Quote\Api\Data\CartInterface $quote = null
    ) {
        return parent::isAvailable($quote);
    }
}

Once these steps are performed you will be able to see your custom payment method in configuration under Sales -> Payment Methods from there you can sett the sort number or rename the payment method name or change the setting make sure to save the configuration and flush the cache.

Once you’ve created payment method the next step is to to make sure its visibility on frontend payment methods for that we will create checkout_index_index and paste the given code in it.

view/frontend/layout/checkout_index_index.xml
<?xml version="1.0" ?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="1column" 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="paybyinstallments" xsi:type="array">
																	<item name="component" xsi:type="string">Gm_Module/js/view/payment/paybyinstallments</item>
																	<item name="methods" xsi:type="array">
																		<item name="paybyinstallments" 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>

in the component tag we have defined the js file which is responsible for rendering the payment method which is paybyinstallments.js . This file identify the js file which will render the html part to the screen in checkout page.

view/frontend/web/js/view/payment/paybyinstallments.js
define(
    [
        'uiComponent',
        'Magento_Checkout/js/model/payment/renderer-list'
    ],
    function (
        Component,
        rendererList
    ) {
        'use strict';
        rendererList.push(
            {
                type: 'paybyinstallments',
                component: 'Gm_Module/js/view/payment/method-renderer/paybyinstallments-method'
            }
        );
        return Component.extend({});
    }
);

In the below file we are returning our template html file to render on payment methods and show it there.

view/frontend/web/js/view/payment/method-renderer/paybyinstallments-method.js
define(
    [
        'Magento_Checkout/js/view/payment/default'
    ],
    function (Component) {
        'use strict';
        return Component.extend({
            defaults: {
                template: 'Gm_Module/payment/paybyinstallments'
            },
            getMailingAddress: function () {
                return window.checkoutConfig.payment.checkmo.mailingAddress;
            },
            getInstructions: function () {
                return window.checkoutConfig.payment.instructions[this.item.method];
            },
        });
    }
);
view/frontend/web/template/payment/paybyinstallments.html
<!--
/**
 * Copyright © 2013-2017 Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */
-->
<div class="payment-method" data-bind="css: {'_active': (getCode() == isChecked())}">
    <div class="payment-method-title field choice">
        <input type="radio"
               name="payment[method]"
               class="radio"
               data-bind="attr: {'id': getCode()}, value: getCode(), checked: isChecked, click: selectPaymentMethod, visible: isRadioButtonVisible()"/>
        <label data-bind="attr: {'for': getCode()}" class="label"><span data-bind="text: getTitle()"></span></label>
    </div>
    <div class="payment-method-content">
        <!-- ko foreach: getRegion('messages') -->
        <!-- ko template: getTemplate() --><!-- /ko -->
        <!--/ko-->
        <div class="payment-method-billing-address">
            <!-- ko foreach: $parent.getRegion(getBillingAddressFormName()) -->
            <!-- ko template: getTemplate() --><!-- /ko -->
            <!--/ko-->
        </div>
        <p data-bind="html: getInstructions()"></p>
        <div class="checkout-agreements-block">
            <!-- ko foreach: $parent.getRegion('before-place-order') -->
                <!-- ko template: getTemplate() --><!-- /ko -->
            <!--/ko-->
        </div>
        <div class="actions-toolbar">
            <div class="primary">
                <button class="action primary checkout"
                        type="submit"
                        data-bind="
                        click: placeOrder,
                        attr: {title: $t('Place Order')},
                        css: {disabled: !isPlaceOrderActionAllowed()},
                        enable: (getCode() == isChecked())
                        "
                        disabled>
                    <span data-bind="i18n: 'Place Order'"></span>
                </button>
            </div>
        </div>
    </div>
</div>
        

Once you have added all of that code run setup upgrade and static content deploy command and you will be able to see your custom method on checkout page.

Leave a Comment

Your email address will not be published. Required fields are marked *