0

I need to add custom fields in the payment step of the checkout page in Magento 2 and also data should be saved in needed tables.

I want to add a payment comment note before-place-order.

how to do it in Magento 2

1
  • I think the following article can help you to understand general logic how to [How to Add Custom Field in Checkout Page Below Payment Method List in Magento 2 ](meetanshi.com/blog/…) Jun 22, 2022 at 15:50

1 Answer 1

0

First, you created a custom module.

app/code/sale/Paymentcomment/etc/module.xml

<?xml version="1.0"?>
 <config>
   <module name="Sale_Paymentcomment" setup_version="1.1.0">
    <sequence>
        <module name="Magento_Checkout"/>
    </sequence>
   </module>
 </config>

created db_schema.xml in app/code/sale/Paymentcomment/etc/db_schema.xml

<?xml version="1.0"?>
  <schema xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Setup/Declaration/Schema/etc/schema.xsd">   
<table name="quote" resource="default" engine="innodb">
   
    <column xsi:type="text" name="paycommenttextarea" nullable="true" comment="Custom field"/>
</table>
<table name="sales_order" resource="default" engine="innodb">
    <column xsi:type="text" name="paycommenttextarea" nullable="true" comment="Custom field"/>
</table>
<table name="sales_order_grid" resource="default" engine="innodb">
   <column xsi:type="text" name="paycommenttextarea" nullable="true" comment="Custom field"/>
</table>

The above code is used to create a custom field in your database.

Adding custom fields in payment steps, we can achieved in two ways one from layout XML and the other one is plugin. so we can use the plugin.

We create a di.xml file in our module - sale/Paymentcomment/etc/frontend/di.xml

<?xml version="1.0"?>
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<type name="Magento\Checkout\Block\Checkout\LayoutProcessor">
    <plugin name="checkout_custom_shipping_fields" type="Sale\Paymentcomment\Plugin\Checkout\LayoutProcessorPlugin"/>
</type>

Sale/Paymentcomment/Plugin/Checkout/LayoutProcessorPlugin.php

<?PHP
  namespace Sale\Paymentcomment\Plugin\Checkout;
  use Magento\Checkout\Block\Checkout\LayoutProcessor;

 class LayoutProcessorPlugin
 {
   protected $logger;


public function __construct(
    \Psr\Log\LoggerInterface $logger

) {
    $this->logger = $logger;

}

public function afterProcess(LayoutProcessor $subject, array $jsLayout)
{

        $jsLayout['components']['checkout']['children']['steps']['children']['billing-step']['children']
        ['payment']['children']['payments-list']['children']['before-place-order']['children']['paycommenttextarea'] = [
            'component' => 'Magento_Ui/js/form/element/textarea',
            'config' => [
                'customScope' => 'shippingAddress',
                'template' => 'ui/form/field',
                'options' => [],
                'id' => 'paycommenttextarea'
            ],
            'dataScope' => 'paycommenttextarea',
            'label' => 'Paycommenttextarea',
            'notice' => __('Paycommenttextarea'),
            'provider' => 'checkoutProvider',
            'visible' => true,
            'sortOrder' => 110,
            'id' => 'paycommenttextarea'
        ];

    return $jsLayout;
}
}

we created extension_attributes.xml file. app/code/sale/Paymentcomment/etc/extension_attributes.xml

<?xml version="1.0"?>
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Api/etc/extension_attributes.xsd">
<extension_attributes for="Magento\Quote\Api\Data\PaymentInterface">
    <attribute code="paycommenttextarea" type="string"/>
</extension_attributes>

override js create a js file Sale/Paymentcomment/view/frontend/requirejs-config.js

var config = {
  config: {
     mixins: {
    'Magento_Checkout/js/action/place-order': {
        'Sale_Paymentcomment/js/order/place-order-mixin': true
    },
    'Magento_Checkout/js/action/set-payment-information': {
        'Sale_Paymentcomment/js/order/set-payment-information-mixin': true
    }
}
}
};

Sale/Paymentcomment/view/frontend/web/js/order/place-order-mixin.js

define([
'jquery',
'mage/utils/wrapper',
'Sale_Paymentcomment/js/order/ordercomment-assigner'
  ], function ($, wrapper, orderCommentsAssigner) {
'use strict';

return function (placeOrderAction) {

    /** Override default place order action and add comments to request */
    return wrapper.wrap(placeOrderAction, function (originalAction, paymentData, messageContainer) {
        orderCommentsAssigner(paymentData);

        return originalAction(paymentData, messageContainer);
    });
   };
  });

Sale/Paymentcomment/view/frontend/web/js/order/set-payment-information-mixin.js

define([
'jquery',
'mage/utils/wrapper',
'Sale_Paymentcomment/js/order/ordercomment-assigner'
 ], function ($, wrapper, orderCommentsAssigner) {
'use strict';

return function (placeOrderAction) {

    /** Override place-order-mixin for set-payment-information action as they differs only by method signature */
    return wrapper.wrap(placeOrderAction, function (originalAction, messageContainer, paymentData) {
        orderCommentsAssigner(paymentData);

        return originalAction(messageContainer, paymentData);
    });
   };
  });

Sale/Paymentcomment/view/frontend/web/js/order/ordercomment-assigner.js

define([
'jquery'
], function ($) {
'use strict';


/** Override default place order action and add comment to request */
return function (paymentData) {

    if (paymentData['extension_attributes'] === undefined) {
        paymentData['extension_attributes'] = {};
    }
    paymentData['extension_attributes']['paycommenttextarea'] =     jQuery('[name="paycommenttextarea"]').val();
};
  });

The next step is saving this custom field post data to the quote.

Sale/Paymentcomment/etc/di.xml

<?xml version="1.0"?>
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<type name="Magento\Checkout\Model\GuestPaymentInformationManagement">
    <plugin name="save_order_comments_in_quote" type="Sale\Paymentcomment\Plugin\Model\Checkout\GuestPaymentInformationManagement" sortOrder="10"/>
</type>
<type name="Magento\Checkout\Model\PaymentInformationManagement">
    <plugin name="save_order_comments_in_quote" type="Sale\Paymentcomment\Plugin\Model\Checkout\PaymentInformationManagement" sortOrder="20"/>
</type>
</config>

Sale/Paymentcomment/Plugin/Model/Checkou/GuestPaymentInformationManagement.php

<?PHP
  namespace Sale\Paymentcomment\Plugin\Model\Checkout;

  /**
   * Class PaymentInformationManagement
   * @package Sale\Paymentcomment\Plugin\Model\Checkout
   */
class PaymentInformationManagement
{
 /**
  * @var \Magento\Quote\Model\QuoteRepository
  */
 protected $quoteRepository;

/**
 * @var \Magento\Framework\Json\Helper\Data
 */
protected $jsonHelper;

/**
 * @var \Magento\Framework\Filter\FilterManager
 */
protected $filterManager;

/**
 * PaymentInformationManagement constructor.
 * @param \Magento\Framework\Json\Helper\Data $jsonHelper
 * @param \Magento\Framework\Filter\FilterManager $filterManager
 * @param \Magento\Quote\Model\QuoteRepository $quoteRepository
 */
public function __construct(
    \Magento\Framework\Json\Helper\Data $jsonHelper,
    \Magento\Framework\Filter\FilterManager $filterManager,
    \Magento\Quote\Model\QuoteRepository $quoteRepository
) {
    $this->jsonHelper = $jsonHelper;
    $this->filterManager = $filterManager;
    $this->quoteRepository = $quoteRepository;
}

/**
 * @param \Magento\Checkout\Model\PaymentInformationManagement $subject
 * @param $cartId
 * @param \Magento\Quote\Api\Data\PaymentInterface $paymentMethod
 */
public function beforeSavePaymentInformation(
    \Magento\Checkout\Model\PaymentInformationManagement $subject,
    $cartId,
    \Magento\Quote\Api\Data\PaymentInterface $paymentMethod
) {
    $commentsExtensionAttributes = $paymentMethod->getExtensionAttributes();
    if ($commentsExtensionAttributes->getPaycommenttextarea()) {
        $commentstextarea = trim($commentsExtensionAttributes->getPaycommenttextarea());
    } else {   
        $commentstextarea = '';
    }
    $quote = $this->quoteRepository->getActive($cartId);
    $quote->setPaycommenttextarea($commentstextarea);
}
}

Sale/Paymentcomment/Plugin/Model/Checkout/PaymentInformationManagement.php

<?PHP
  namespace Sale\Paymentcomment\Plugin\Model\Checkout;

  /**
   * Class PaymentInformationManagement
   * @package Sale\Paymentcomment\Plugin\Model\Checkout
   */
 class PaymentInformationManagement
 {
  /**
   * @var \Magento\Quote\Model\QuoteRepository
   */
  protected $quoteRepository;

/**
 * @var \Magento\Framework\Json\Helper\Data
 */
protected $jsonHelper;

/**
 * @var \Magento\Framework\Filter\FilterManager
 */
protected $filterManager;

/**
 * PaymentInformationManagement constructor.
 * @param \Magento\Framework\Json\Helper\Data $jsonHelper
 * @param \Magento\Framework\Filter\FilterManager $filterManager
 * @param \Magento\Quote\Model\QuoteRepository $quoteRepository
 */
public function __construct(
    \Magento\Framework\Json\Helper\Data $jsonHelper,
    \Magento\Framework\Filter\FilterManager $filterManager,
    \Magento\Quote\Model\QuoteRepository $quoteRepository
) {
    $this->jsonHelper = $jsonHelper;
    $this->filterManager = $filterManager;
    $this->quoteRepository = $quoteRepository;
}

/**
 * @param \Magento\Checkout\Model\PaymentInformationManagement $subject
 * @param $cartId
 * @param \Magento\Quote\Api\Data\PaymentInterface $paymentMethod
 */
public function beforeSavePaymentInformation(
    \Magento\Checkout\Model\PaymentInformationManagement $subject,
    $cartId,
    \Magento\Quote\Api\Data\PaymentInterface $paymentMethod
) {
    $commentsExtensionAttributes = $paymentMethod->getExtensionAttributes();
    if ($commentsExtensionAttributes->getPaycommenttextarea()) {
        $commentstextarea = trim($commentsExtensionAttributes->getPaycommenttextarea());
    } else {   
        $commentstextarea = '';
    }
    $quote = $this->quoteRepository->getActive($cartId);
    $quote->setPaycommenttextarea($commentstextarea);
}
}

Sale/Paymentcomment/etc/events.xml

<?xml version="1.0"?>
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">
  <event name="sales_model_service_quote_submit_before">
    <observer name="add_order_comments_to_order" instance="Sale\Paymentcomment\Observer\AddOrderCommentsToOrder" />
  </event>
</config>

Sale\Paymentcomment\Observer\AddOrderCommentsToOrder.php

<?PHP
 namespace Sale\Paymentcomment\Observer;

/**
 * Class AddOrderCommentsToOrder
 * @package Sale\Paymentcomment\Observer
 */
  class AddOrderCommentsToOrder implements \Magento\Framework\Event\ObserverInterface
{
  /**
   * @param \Magento\Framework\Event\Observer $observer
   */
public function execute(\Magento\Framework\Event\Observer $observer)
{
    $order = $observer->getEvent()->getOrder();
    $quote = $observer->getEvent()->getQuote();
 
    $order->setData('paycommenttextarea', $quote->getPaycommenttextarea());
    

     return $this;
 }
 }

if you want show data admin grid side. add below code di.xml file.

Sale/Paymentcomment/etc/di.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<type name="Magento\Framework\View\Element\UiComponent\DataProvider\CollectionFactory">
    <arguments>
        <argument name="collections" xsi:type="array">
            <item name="sales_order_grid_data_source" xsi:type="string">Sale\Paymentcomment\Model\ResourceModel\Order\Grid\Collection</item>
        </argument>
    </arguments>
</type>
<type name="Sale\Paymentcomment\Model\ResourceModel\Order\Grid\Collection">
    <arguments>
        <argument name="mainTable" xsi:type="string">sales_order_grid</argument>
        <argument name="resourceModel" xsi:type="string">Magento\Sales\Model\ResourceModel\Order</argument>
    </arguments>
</type>
</config>

Sale/Paymentcomment/Model/ResourceModel/Order/Grid/Collection.php

<?PHP
  namespace Sale\Paymentcomment\Model\ResourceModel\Order\Grid;

  use Magento\Framework\Data\Collection\Db\FetchStrategyInterface as       CoreFetchStrategy;
  use Magento\Framework\Data\Collection\EntityFactoryInterface as CoreEntityFactory;
  use Magento\Framework\Event\ManagerInterface as CoreEventManager;
  use Magento\Sales\Model\ResourceModel\Order\Grid\Collection as CoreSalesGrid;
  use Psr\Log\LoggerInterface as Logger;

  class Collection extends CoreSalesGrid
 {
/**
 * @param CoreEntityFactory $entityFactory
 * @param Logger            $logger       
 * @param CoreFetchStrategy $fetchStrategy
 * @param CoreEventManager  $eventManager 
 * @param string            $mainTable    
 * @param string            $resourceModel
 */
public function __construct(
    CoreEntityFactory $entityFactory,
    Logger $logger,
    CoreFetchStrategy $fetchStrategy,
    CoreEventManager $eventManager,
    $mainTable = 'sales_order_grid',
    $resourceModel = \Magento\Sales\Model\ResourceModel\Order::class
) {
    parent::__construct($entityFactory, $logger, $fetchStrategy, $eventManager, $mainTable, $resourceModel);
}

protected function _renderFiltersBefore()
{
    $joinTablepaycomment = $this->getTable('sales_order');
    $this->getSelect()->joinLeft(
        $joinTablepaycomment,
        'main_table.entity_id = sales_order.entity_id',
        ['paycommenttextarea']

    );

    parent::_renderFiltersBefore();
}
}

Now, add a custom column in the grid create sales_order_grid.xml at app/code/sale/Paymentcomment/view/adminhtml/ui_component/sales_order_grid.xml and paste the below code :

<?xml version="1.0" encoding="UTF-8"?>
 <listing xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd">
<columns name="sales_order_columns">
    <column name="paycommenttextarea">
        <argument name="data" xsi:type="array">
            <item name="config" xsi:type="array">
                <item name="filter" xsi:type="string">text</item>
                <item name="label" xsi:type="string" translate="true">Paycommenttextarea</item>
            </item>
        </argument>
    </column>
</columns>
</listing>


               

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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