I am using stripe payment method, I want to add billing zip filed in cc form.
How can I add this field??
Magento 2 Payment Methods – Add New Field in Payment Method
magento2magento2.3payment-methodsstripe
Related Solutions
In your custom module :
di.xml
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<type name="Magento\OfflinePayments\Model\Cashondelivery">
<plugin sortOrder="1" name="restrictByCustomer"
type="[vendor]\[module]\Plugin\Payment\Method\CashOnDelivery\Available"/>
</type>
</config>
[vendor][module]\Plugin\Payment\Method\CashOnDelivery\Available.php
<?php
/**
* Copyright © 2016 MageWorx. All rights reserved.
* See LICENSE.txt for license details.
*/
namespace [vendor]\[module]\Plugin\Payment\Method\CashOnDelivery;
use Magento\Customer\Model\Session as CustomerSession;
use Magento\Backend\Model\Auth\Session as BackendSession;
use Magento\OfflinePayments\Model\Cashondelivery;
class Available
{
/**
* @var CustomerSession
*/
protected $customerSession;
/**
* @var BackendSession
*/
protected $backendSession;
/**
* @param CustomerSession $customerSession
* @param BackendSession $backendSession
*/
public function __construct(
CustomerSession $customerSession,
BackendSession $backendSession
) {
$this->customerSession = $customerSession;
$this->backendSession = $backendSession;
}
/**
*
* @param Cashondelivery $subject
* @param $result
* @return bool
* @throws \Magento\Framework\Exception\LocalizedException
*/
public function afterIsAvailable(Cashondelivery $subject, $result)
{
// Do not remove payment method for admin
if ($this->backendSession->isLoggedIn()) {
return $result;
}
..........................
return true/false;
}
In this some time you will get the JS error of :
window.checkoutConfig.payment.instructions
In this you need to change the .js
file of that payment method and remove this line.
To answer your question, there are 3 parts:
- Create Order Attribute
- Insert attribute when placing order
- Read the Order Attribute in payment module
Create Order Attribute
For creating order attribute, you MUST use setup script with the following code:
<?php
namespace Vendor\Module\Setup;
use Magento\Eav\Setup\EavSetupFactory;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\ModuleDataSetupInterface;
use Magento\Framework\Setup\UpgradeDataInterface;
use Magento\Quote\Setup\QuoteSetupFactory;
use Magento\Sales\Setup\SalesSetupFactory;
class UpgradeData implements UpgradeDataInterface
{
/**
* @var QuoteSetupFactory
*/
protected $quoteSetupFactory;
/**
* @var SalesSetupFactory
*/
protected $salesSetupFactory;
/**
* @var EavSetupFactory
*/
protected $eavSetupFactory;
/**
* Constructor
*/
public function __construct(
QuoteSetupFactory $quoteSetupFactory,
SalesSetupFactory $salesSetupFactory,
EavSetupFactory $eavSetupFactory
) {
$this->quoteSetupFactory = $quoteSetupFactory;
$this->salesSetupFactory = $salesSetupFactory;
$this->eavSetupFactory = $eavSetupFactory;
}
/**
* {@inheritdoc}
*/
public function upgrade(
ModuleDataSetupInterface $setup,
ModuleContextInterface $context
) {
$setup->startSetup();
if (version_compare($context->getVersion(), '1.0.1', '<')) {
/** @var \Magento\Quote\Setup\QuoteSetup $quoteInstaller */
$quoteInstaller = $this->quoteSetupFactory->create(['resourceName' => 'quote_setup', 'setup' => $setup]);
/** @var \Magento\Sales\Setup\SalesSetup $salesInstaller */
$salesInstaller = $this->salesSetupFactory->create(['resourceName' => 'sales_setup', 'setup' => $setup]);
//Add attributes to quote
$entityAttributesCodes = [
'bank_name' => \Magento\Framework\DB\Ddl\Table::TYPE_TEXT,
];
foreach ($entityAttributesCodes as $code => $type) {
$quoteInstaller->addAttribute('quote', $code, ['type' => $type, 'length' => 255, 'visible' => true, 'nullable' => true,]);
$salesInstaller->addAttribute('order', $code, ['type' => $type, 'length' => 255, 'visible' => true, 'nullable' => true,]);
}
$setup->endSetup();
}
}
I used upgrade script as example, but you can use inscript to perform the same function too.
Insert attribute when placing order
This process is a little bit tricky but I think it's still OK for you.
Create new file
app/code/Vendor/Module/etc/extension_attributes.xml
with the following code:<?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\AddressInterface"> <attribute code="bank_name" type="string"/> </extension_attributes> </config>
Create file
app/code/Vendor/Module/view/frontend/requirejs-config.js
with the following code:var config = { config: { mixins: { 'Magento_Checkout/js/action/set-shipping-information': { 'Vendor_Module/js/order/set-shipping-information-mixin': true } } } };
Create new file
app/code/Vendor/Module/view/frontend/web/js/order/set-shipping-information-mixin.js
with the following code:define([ 'jquery', 'mage/utils/wrapper', 'Magento_Checkout/js/model/quote' ], function ($, wrapper, quote) { 'use strict'; return function (setShippingInformationAction) { return wrapper.wrap(setShippingInformationAction, function (originalAction) { var shippingAddress = quote.shippingAddress(); if (shippingAddress['extension_attributes'] === undefined) { shippingAddress['extension_attributes'] = {}; } // you can extract value of extension attribute from any place (in this example I use customAttributes approach) shippingAddress['extension_attributes']['bank_name'] = jQuery('input[name="bank_name"]').val(); // pass execution to original action ('Magento_Checkout/js/action/set-shipping-information') return originalAction(); }); }; });
Create file
app/code/Vendor/Module/view/frontend/layout/checkout_index_index.xml
<?xml version="1.0" encoding="UTF-8"?> <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="shipping-step" xsi:type="array"> <item name="children" xsi:type="array"> <item name="shippingAddress" xsi:type="array"> <item name="children" xsi:type="array"> <item name="before-form" xsi:type="array"> <item name="children" xsi:type="array"> <!-- Your form declaration here --> <item name="custom-checkout-form-container" xsi:type="array"> <item name="component" xsi:type="string">Vendor_Module/js/view/order_attr</item> <item name="provider" xsi:type="string">checkoutProvider</item> <item name="config" xsi:type="array"> <item name="template" xsi:type="string">Vendor_Module/order_attr</item> </item> <item name="children" xsi:type="array"> <item name="custom-checkout-form-fieldset" xsi:type="array"> <!-- uiComponent is used as a wrapper for form fields (its template will render all children as a list) --> <item name="component" xsi:type="string">uiComponent</item> <!-- the following display area is used in template (see below) --> <item name="displayArea" xsi:type="string">custom-checkout-form-fields</item> <item name="children" xsi:type="array"> <item name="bank_name" xsi:type="array"> <item name="component" xsi:type="string">Magento_Ui/js/form/element/abstract</item> <item name="config" xsi:type="array"> <!-- customScope is used to group elements within a single form (e.g. they can be validated separately) --> <item name="customScope" xsi:type="string">customCheckoutForm</item> <item name="template" xsi:type="string">ui/form/field</item> <item name="elementTmpl" xsi:type="string">ui/form/element/input</item> </item> <item name="provider" xsi:type="string">checkoutProvider</item> <item name="dataScope" xsi:type="string">customCheckoutForm.bank_name</item> <item name="label" xsi:type="string">Clearance Full Name</item> <item name="sortOrder" xsi:type="string">1</item> <item name="validation" xsi:type="array"> <item name="required-entry" xsi:type="string">true</item> </item> </item> </item> </item> </item> </item> </item> </item> </item> </item> </item> </item> </item> </item> </item> </item> </item> </argument> </arguments> </referenceBlock> </body> </page>
Create file
app/code/Vendor/Module/view/frontend/web/template/order_attr.html
with the following code:<div> <form id="custom-checkout-form" class="form" data-bind="attr: {'data-hasrequired': $t('* Required Fields')}"> <fieldset class="fieldset"> <legend data-bind="i18n: 'Clearance Info'"></legend> <div><!-- ko i18n: 'This is clearance description' --><!-- /ko --></div> <!-- ko foreach: getRegion('custom-checkout-form-fields') --> <!-- ko template: getTemplate() --><!-- /ko --> <!--/ko--> </fieldset> </form> </div>
Create file
app/code/Vendor/Module/view/frontend/web/js/view/order_attr.js
with the following code:define([ 'Magento_Ui/js/form/form' ], function(Component) { 'use strict'; return Component.extend({ initialize: function () { this._super(); // component initialization logic return this; }, /** * Form submit handler * * This method can have any name. */ onSubmit: function() { // trigger form validation this.source.set('params.invalid', false); this.source.trigger('customCheckoutForm.data.validate'); // verify that form data is valid if (!this.source.get('params.invalid')) { // data is retrieved from data provider by value of the customScope property var formData = this.source.get('customCheckoutForm'); // do something with form data console.dir(formData); } } }); });
Create file
app/code/Vendor/Module/etc/di.xml
with the following code:<?xml version="1.0" encoding="UTF-8"?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd"> <type name="Magento\Checkout\Model\ShippingInformationManagement"> <plugin name="save-in-quote" type="Vendor\Module\Plugin\AddOrderAttrToQuote" sortOrder="10"/> </type> </config>
Create new file
app/code/Vendor/Module/Plugin/AddOrderAttrToQuote.php
with the following code:<?php namespace Vendor\Module\Plugin; class AddOrderAttrToQuote { protected $quoteRepository; public function __construct( \Magento\Quote\Model\QuoteRepository $quoteRepository ) { $this->quoteRepository = $quoteRepository; } /** * @param \Magento\Checkout\Model\ShippingInformationManagement $subject * @param $cartId * @param \Magento\Checkout\Api\Data\ShippingInformationInterface $addressInformation */ public function beforeSaveAddressInformation( \Magento\Checkout\Model\ShippingInformationManagement $subject, $cartId, \Magento\Checkout\Api\Data\ShippingInformationInterface $addressInformation ) { $extAttributes = $addressInformation->getShippingAddress()->getExtensionAttributes(); $bank_name = $extAttributes->getBankName(); $quote = $this->quoteRepository->getActive($cartId); $quote->setBankName($bank_name); $extAttributes->setBankName(""); } }
Create new file
app/code/Cleargo/NewAttributes/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="sales_model_service_quote_submit_before"> <observer name="handle_order_attrs" instance="Vendor\Module\Observer\HandleOrderAttrs" /> </event> </config>
Create new file
app/code/Vendor/Module/Observer/HandleOrderAttrs.php
with the following code:<?php namespace Vendor\Module\Observer; use \Magento\Framework\Event\ObserverInterface; use \Magento\Framework\Event\Observer; class HandleOrderAttrs implements ObserverInterface { public function execute(Observer $observer) { $order = $observer->getOrder(); $quote = $observer->getQuote(); //Load the values $bank_name = $quote->getData("bank_name"); $order->setData('bank_name', $bank_name) ->save(); } }
Read the Order Attribute in payment module
For case 3, seems it's from 3rd party module. Anyway, if you want to get the value of bank_name
from order, you can use the following code:
$order->getData('bank_name')
Conslusion
It's quite a lot of work to do for an order attribute, but once you get the key point, everything will go smooth.
Best Answer
First create your schema file inside Ibnab/Additional/Setup/InstallSchema.php :
We will add this behavior on bank transfert methode , ok let's remap offline-payments٫js inside Ibnab/Additional/view/frontend/requirejs-config.js :
now you need copy the original file from magento vendor and pas in your module with some change (Ibnab/Additional/view/frontend/web/js/view/payment/offline-payments.js):
we have changed the banktransfert renderer :
and create other one from original file in vendor (Ibnab/Additional/view/frontend/web/js/view/payment/method-renderer/banktransfer-method.js) :
In the banktransfer-method.js we have changed the path to our new html template (Ibnab/Additional/view/frontend/web/template/payment/banktransfer.html) :
And we have added the value of bank account owner to additional data bu using the id :
And that is the code of our html template (the original code is inside vendor) :
Our custom input text is with name name="payment[bankowner]" :
Now is the time to add observer (Ibnab/Additional/etc/events.xml):
is very clear the system will declanche this event on before order payment save (Ibnab/Additional/Observer/SaveBankInfoToOrderObserver.php) :
We have use one way to get value of our input text from additional data of payment quote with inputParamsResolver :
we have use foreach clause the extract the value and push inside payment qoute and payment order. So now if you create an order the value of your custom field will be saved in column bankowner of quote_payment and sales_order_payment table . But how you can show it in order view (inside admin) , you can add layout (Ibnab/Additional/view/adminhtml/layout/sales_order_view.xml) and push :
Now create you .phtml (Ibnab/Additional/view/adminhtml/templates/info/banktransferinfo.phtml):
we will show the account now just if bank transfert method :