Magento – How to add additional field to checkout payment (Magento 2)

magento2payment-methods

I have a payment module for Magento 2 and I would need to add a new field to checkout fiels. To my understanding I can add the field to checkout_index_index.xml layout file, but I just can't get it right.

My layout file is currently

<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="1column" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/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">
                                                        <!-- merge payment method renders here -->
                                                        <item name="children" xsi:type="array">
                                                            <item name="lindorff-payments" xsi:type="array">
                                                                <item name="component" xsi:type="string">Company_Mypayment/js/view/payment/mypaymentpayment</item>
                                                                <item name="methods" xsi:type="array">

                                                                     <item name="mypaymentpayment" 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>

I wish to keep all existing default payment address fields and add a new text field, but how?

Best Answer

You need to create js component for that

#Company/Mypayment/view/frontend/web/js/view/payment/mypaymentpayment.js

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

Create Company/Mypayment/view/frontend/web/js/view/payment/method-renderer/mypaymentpayment.js

define(
    [
        'Magento_Payment/js/view/payment/cc-form',
        'jquery',
        'Magento_Payment/js/model/credit-card-validation/validator'
    ],
    function (Component, $) {
        'use strict';

        return Component.extend({
            defaults: {
                template: 'Company_Mypayment/payment/form',
                transactionResult: ''
            },

            /**
             * @returns {String}
             */
            getCode: function () {
                return 'mypaymentpayment';
            },

            /**
             * @returns {Boolean}
             */
            isActive: function () {
                return true;
            },
            validate: function() {
                var $form = $('#' + this.getCode() + '-form');
                return $form.validation() && $form.validation('isValid');
            }
        });
    }
);

Now create a template for it [Company/Mypayment/view/frontend/web/template/payment/form.html]

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

        <form class="form" data-bind="attr: {'id': getCode() + '-form'}">
            <!-- ko template: 'Magento_Payment/payment/cc-form' --><!-- /ko -->
        </form>

        <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="text: $t('Place Order')"></span>
                </button>
            </div>
        </div>
    </div>
</div>