0

I want to add form in cash on delivery payment method only on checkout page Magento 2. I want to add it using layout checkout_index_index.xml.

Can anyone please tell me how to add form using layout file on checkout page Magento 2?

2
0

You may create a custom module and override few js file for this customisation as describe below.

I assume you custom module name is Company_CodForm.

Note:

In this COD Form module I created two form field.That are "codfield1" and "codfield2". codfield1 is text input and codfield2 is dropdown. I also write js code (app/code/Company/CodForm/view/frontend/web/js/view/payment/method-renderer/cashondelivery-method.js) accordingly. Please change this js file as per your custom COD form fields.

step 1) Create requirejs-config.js under YOUR-MAGENTO-ROOT/app/code/Company/CodForm/view/

File: YOUR-MAGENTO-ROOT/app/code/Company/CodForm/view/requirejs-config.js

var config = {
    map: {
        '*': {
           'Magento_OfflinePayments/js/view/payment/offline-payments': 'Company_CodForm/js/view/payment/offline-payments'         
        }
    }
}

Step 2) Create offline-payments.js under YOUR-MAGENTO-ROOT/app/code/Company/CodForm/view/frontend/web/js/view/payment

File: YOUR-MAGENTO-ROOT/app/code/Company/CodForm/view/frontend/web/js/view/payment/offline-payments.js

/

**
 * Copyright © 2013-2017 Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */
/*browser:true*/
/*global define*/
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: 'Magento_OfflinePayments/js/view/payment/method-renderer/banktransfer-method'
            },
            {
                type: 'cashondelivery',
                component: 'Company_CodForm/js/view/payment/method-renderer/cashondelivery-method'
            },
            {
                type: 'purchaseorder',
                component: 'Magento_OfflinePayments/js/view/payment/method-renderer/purchaseorder-method'
            }
        );
        /** Add view logic here if needed */
        return Component.extend({});
    }
);

step 3: Create cashondelivery-method.js under YOUR-MAGENTO-ROOT/app/code/Company/CodForm/view/frontend/web/js/view/payment/method-renderer

File : YOUR-MAGENTO-ROOT/app/code/Company/CodForm/view/frontend/web/js/view/payment/method-renderer/cashondelivery-method.js

/**
 * Copyright © 2013-2017 Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */
define(
    [
        'ko',
        'Magento_Checkout/js/view/payment/default',
        'jquery'
    ],
    function (ko, Component,$) {
        'use strict';

         var optionsList = ko.observableArray();  
         var codOption = function(name, id) {
              this.name = name;
              this.id = id;
         };

        return Component.extend({
            defaults: {
                template: 'MagePritam_CodForm/payment/codForm'
            },
             initialize: function(){
                 this._super(); 
                 this.populateOptionsList();             
                 return this;
             },            
            optionsList: optionsList,            
            getData: function() {
                return {
                    'method': this.item.method,
                    'additional_data': {
                        'codfield1': $('#cashondelivery_codfield1').val(),
                        'codfield2': $('#cashondelivery_codfield2').val()
                    }
                };
            },
            /**
             * Get value of instruction field.
             * @returns {String}
             */
            getInstructions: function () {
                return window.checkoutConfig.payment.instructions[this.item.method];
            },
            populateOptionsList: function(){
                 var self =  this;                
                 this.optionsList([
                     new codOption('Cash','cashcodpayment'),                     
                     new codOption('Credit/Debit Card','cardcodpayment')                     
                 ]);

             }  

        });
    }
);

step 4) Create template file codForm.html under YOUR-MAGENTO-ROOT/app/code/Company/CodForm/view/frontend/web/template

File : YOUR-MAGENTO-ROOT/app/code/Company/CodForm/view/frontend/web/template/codForm.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">
        <p data-bind="html: getInstructions()"></p>   
    <fieldset data-bind="attr: {class: 'fieldset payment items ' + getCode(), id: 'payment_form_' + getCode()}"> 
    <div class="field _required">
        <label data-bind="attr: {for: getCode() + '_codfield1'}" class="label">
            <span><!-- ko i18n: 'COD Custom Field 1'--><!-- /ko --></span>
        </label>
        <div class="control">
            <input data-validate="{'required-entry':true}" type="text" name="payment[codfield1]" class="input-text" value=""
                   data-bind="attr: {
                                    id: getCode() + '_codfield1',
                                    title: $t('COD Field'),
                                    'data-container': getCode() + '-codfield1',
                                    'data-validate': JSON.stringify({'required':true})},
                                    valueUpdate: 'keyup' "/>
        </div>

        <div class="control">
             <select  data-validate="{'required-entry':true}" 
                    data-bind="attr: {
                       id: getCode() + '_codfield2',
                      },
                      options: optionsList(),
                      optionsText: 'name',
                      optionsValue:'id',
                     optionsCaption: 'Choose...'">
             </select>   
        </div>
    </div>
    </fieldset>

        <!-- 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>      
        <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')},
                        enable: (getCode() == isChecked()),
                        css: {disabled: !isPlaceOrderActionAllowed()}
                        "
                        disabled>
                    <span data-bind="i18n: 'Place Order'"></span>
                </button>
            </div>
        </div>
    </div>
</div>

step 5) Create observer file SaveCodInfo.php under YOUR-MAGENTO-ROOT/app/code/Company/CodForm/Observer to save the COD custom field data in order payment table .

File : YOUR-MAGENTO-ROOT/app/code/Company/CodForm/Observer/SaveCodInfo.php

<?php

namespace Company\CodForm\Observer;

use Magento\OfflinePayments\Model\Cashondelivery;

use Magento\Framework\Event\Observer;
use Magento\Payment\Observer\AbstractDataAssignObserver;
use Magento\Quote\Api\Data\PaymentInterface;

/**
 * Class SavePoNumberToOrderObserver
 */
class SaveCodInfo extends AbstractDataAssignObserver
{
    const CODE_FIELD_1 = 'codfield1';
    const CODE_FIELD_2 = 'codfield2';

    /**
     * @var array
     */
    protected $additionalInformationList = [
        self::CODE_FIELD_1,
        self::CODE_FIELD_2
    ];


    protected $logger;


    public function __construct(

      \Psr\Log\LoggerInterface $logger

      ) {

        $this->logger = $logger;

    }
    /**
     * @param Observer $observer
     * @return void
     */
    public function execute(Observer $observer)
    {
        $data = $this->readDataArgument($observer);
        $additionalData = $data->getData(PaymentInterface::KEY_ADDITIONAL_DATA);
        if (!is_array($additionalData)) {
            return;
        }


        $this->logger->info("COD Form Log additionalData",$additionalData);


        $paymentInfo = $this->readPaymentModelArgument($observer);

        foreach ($this->additionalInformationList as $additionalInformationKey) {
            if (isset($additionalData[$additionalInformationKey])) {
                $paymentInfo->setData(
                    $additionalInformationKey,
                    $additionalData[$additionalInformationKey]
                );
            }
        }
    }
}

Step 6) Create events.xml under YOUR-MAGENTO-ROOT/app/code/Company/CodForm/etc

File : YOUR-MAGENTO-ROOT/app/code/Company/CodForm/etc/events.xml

<?xml version="1.0" encoding="UTF-8"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">
    <event name="payment_method_assign_data">
        <observer name="save_codform_infos" instance="Company\CodForm\Observer\SaveCodInfo"/>
    </event>
</config>

:: Demo ::

enter image description here

5
  • Can i add custom dropdown for selected payment methods without overriding template file. By playing with js layout ? – Yash Shah Feb 14 '20 at 6:32
  • What is your particular requirement ? please explain. – Pritam Info 24 Feb 17 '20 at 11:10
  • How can we use Mobile OTP verification on the selection of cash on the delivery method? @PritamInfo24 – Utsav Gupta Jan 29 at 9:53
  • Hello @Utsav. You can use a custom field name "cod_otp". Generate the OTP and save that is database [saving custom filed for COD already ] with Quote ID. Now send the OTP to customer via SMS and open a New Input Box to enter the OTP. Now Put a extra button name "validate OTP" and do check the entered OTP with the save once . Also use the Quote ID while validating the OTP – Pritam Info 24 Jan 29 at 10:35
  • I followed this answer and try to create the mobile verification code. That code working correctly. but now the payment method is updating every second I don't know why? any idea? – Utsav Gupta Feb 4 at 11:00

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.