Add Customer Attributes Programmatically in Magento 2

In this article we’ll see what’re customer attributes and how we add them programmatically in Magento 2. So we’ll proceed with following points :

1. What’re customer attributes
2. Why we need to add them programmatically
3. Steps to create customer attribute.

1. What’re customer attributes

In Magento, fields which are used in registration, login and filling customer address are basically customer attributes. They’re further divided into customer attributes and customer address attributes. Now if attributes used in customer registration / login are customer attributes and attribute used in address information for customers are customer address attributes. Some examples of customer attributes are below :

a. Customer Attributes
– First Name, Last Name, DOB etc
b. Customer Address Attributes
– Zip, City, Street, Country, Region/State etc

2. Why we need to add them programmatically

Magento by default didn’t provide functionality to add customer attributes in CE and sometime our project requirement have to add some extra fields(customer attributes) in registration form or address form. To do so we need to add them programmatically or through third party modules.

3. Steps to create customer attribute.

Let see how we can create customer attributes programmatically in Magento 2 step by step :-

Step 1: Create setup file InstallData.php

Firstly, we will create the InstallData.php file:
File: Excellence/Customerattr/Setup/InstallData.php

<?php
namespace Excellence\Customerattr\Setup;

use Magento\Eav\Setup\EavSetup;
use Magento\Eav\Setup\EavSetupFactory;
use Magento\Framework\Setup\InstallDataInterface;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\ModuleDataSetupInterface;

class InstallData implements InstallDataInterface
{
	private $eavSetupFactory;

	public function __construct(EavSetupFactory $eavSetupFactory)
	{
		$this->eavSetupFactory = $eavSetupFactory;
	}

}

In this class, we define the EAV setup model which will be use to interact with Magento 2 attribute.

Step 2: Define the install() method

After that, we have to define the install() method and create eav setup model:

	
public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $context)
	{
		$eavSetup = $this->eavSetupFactory->create(['setup' => $setup]);
		$eavSetup->addAttribute(
			\Magento\Customer\Model\Customer::ENTITY,
			'gst_number',
			[
				'type'         => 'varchar',
				'label'        => 'GST Number',
				'input'        => 'text',
				'required'     => false,
				'visible'      => true,
				'user_defined' => true,
				'position'     => 100,
				'system'       => 0,
			]
		);
}

Step 3: Create custom attribute

Finally, we need to set the forms in which the attributes will be used. In this step, we need define the eavConfig object which allow us to call the attribute back and set the data for it and the full code to create customer attribute is:

Now our final InstallData.php looks like below :-

<?php

namespace Excellence\Customerattr\Setup;

use Magento\Eav\Setup\EavSetup;
use Magento\Eav\Setup\EavSetupFactory;
use Magento\Framework\Setup\InstallDataInterface;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\ModuleDataSetupInterface;
use Magento\Eav\Model\Config;
use Magento\Customer\Model\Customer;

class InstallData implements InstallDataInterface
{
	private $eavSetupFactory;

	public function __construct(EavSetupFactory $eavSetupFactory, Config $eavConfig)
	{
		$this->eavSetupFactory = $eavSetupFactory;
		$this->eavConfig       = $eavConfig;
	}

	public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $context)
	{
		$eavSetup = $this->eavSetupFactory->create(['setup' => $setup]);
		$eavSetup->addAttribute(
			\Magento\Customer\Model\Customer::ENTITY,
			'gst_number',
			[
				'type'         => 'varchar',
				'label'        => 'GST Number',
				'input'        => 'text',
				'required'     => false,
				'visible'      => true,
				'user_defined' => true,
				'position'     => 999,
				'system'       => 0,
			]
		);
		$attribute = $this->eavConfig->getAttribute(Customer::ENTITY, 'gst_number');

		//  used_in_forms are of these types you can use forms key according to your need ['adminhtml_checkout','adminhtml_customer','adminhtml_customer_address','customer_account_edit','customer_address_edit','customer_register_address', 'customer_account_create']
		
               $attribute->setData(
			'used_in_forms',
			['adminhtml_customer', 'customer_account_create']

		);
		$attribute->save();
	}
}

Step 4: Show Customer Attribute in Register form
For showing this customer attribute on the registration page, we need to do following things :

We will add our phtml files to ‘form.additional.info’ reference name using Excellence/Customerattr/view/frontend/layout/customer_account_create.xml

<page 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="1column" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <body>
        <referenceContainer name="form.additional.info">
            <block class="Magento\Framework\View\Element\Template" name="mobile_number" template="Excellence_MobileLogin::mobile.phtml"/>
        </referenceContainer>
    </body>
</page>

Explaination : we’re not overriding the entire vendor/magento/module-customer/view/frontend/templates/form/register.phtml file. Instead we used container name form.additional.info as reference and adding a new block to it. ‘form.additional.info’ is being called in register.phtml using this code getChildHtml(‘form_additional_info’); ?>

So by above xml we can simply add new attribute fields with editing register.phtml of core or without overriding it and getChildHtml(‘form_additional_info’); ?> automatically read content of ‘form.additional.info’ child block.

That’s all for adding customer attribute programmatically.

Creating Custom Online Payment Method in Magento 2

In this blog, we will learn to create online payment method. We will implement Stripe payment as a reference. You may change it as per your requirement. It will depend upon the library that the gateway provider gives.

Stripe Payment Gateway has several features, but we will be implementing the most basic ones. We will use the official PHP library of stripe i.e. https://github.com/stripe/stripe-php

It should be noticed that the library of Stripe is managed via Composer so it can be installed via that, alternatively, it can be downloaded and the files should be put in vendor/stripe. If we manage the whole process via composer, then it can be automatically included in the code through autoloader. But if we don’t, then we will have to include it in our code.

We will be creating several files and most of the files will be same as the previous blog. So, we will be dicussing about the important files only. Now, let’s get started:

The structure of the extension will look like this:

1. System.xml

This file is used to create the store configuration part for the extension so that the configuration for setting up the payment method can be done from admin panel easily. We will define several fields like API Key, Supported Credit Card Types etc.

<?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">
            <group id="excellence_stripe" translate="label" type="text" sortOrder="50" showInDefault="1" showInWebsite="1" showInStore="1">
                <label>Stripe</label>
                <comment>
                    <![CDATA[<a href="https://stripe.com/" target="_blank">Click here to sign up for Stripe account</a>]]>
                </comment>
                <field id="active" translate="label" type="select" sortOrder="1" showInDefault="1" showInWebsite="1" showInStore="0">
                    <label>Enabled</label>
                    <source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
                </field>
                <field id="title" translate="label" type="text" sortOrder="2" showInDefault="1" showInWebsite="1" showInStore="1">
                    <label>Title</label>
                </field>
                <field id="api_key" translate="label" type="obscure" sortOrder="3" showInDefault="1" showInWebsite="1" showInStore="0">
                    <label>Api Key</label>
                    <backend_model>Magento\Config\Model\Config\Backend\Encrypted</backend_model>
                </field>
                <field id="debug" translate="label" type="select" sortOrder="4" showInDefault="1" showInWebsite="1" showInStore="0">
                    <label>Debug</label>
                    <source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
                </field>
                <field id="cctypes" translate="label" type="multiselect" sortOrder="5" showInDefault="1" showInWebsite="1" showInStore="0">
                    <label>Credit Card Types</label>
                    <source_model>Excellence\Stripe\Model\Source\Cctype</source_model>
                </field>
                <field id="sort_order" translate="label" type="text" sortOrder="100" showInDefault="1" showInWebsite="1" showInStore="0">
                    <label>Sort Order</label>
                </field>
                <field id="allowspecific" translate="label" type="allowspecific" sortOrder="50" showInDefault="1" showInWebsite="1" showInStore="0">
                    <label>Payment from Applicable Countries</label>
                    <source_model>Magento\Payment\Model\Config\Source\Allspecificcountries</source_model>
                </field>
                <field id="specificcountry" translate="label" type="multiselect" sortOrder="51" showInDefault="1" showInWebsite="1" showInStore="0">
                    <label>Payment from Specific Countries</label>
                    <source_model>Magento\Directory\Model\Config\Source\Country</source_model>
                </field>
                <field id="min_order_total" translate="label" type="text" sortOrder="98" showInDefault="1" showInWebsite="1" showInStore="0">
                    <label>Minimum Order Total</label>
                </field>
                <field id="max_order_total" translate="label" type="text" sortOrder="99" showInDefault="1" showInWebsite="1" showInStore="0">
                    <label>Maximum Order Total</label>
                    <comment>Leave empty to disable limit</comment>
                </field>
            </group>
        </section>


    </system>
</config>

2. Model

We will create a Model for handling the processing of payment and will define this model is the config.xml as explained in the previous blog:

<?php namespace Excellence\Stripe\Model; class Payment extends \Magento\Payment\Model\Method\Cc {              const CODE = 'excellence_stripe';         protected $_code = self::CODE;         protected $_isGateway = true;         protected $_canCapture = true;              protected $_canCapturePartial = true;              protected $_canRefund = true;         protected $_canRefundInvoicePartial = true;         protected $_stripeApi = false;              protected $_countryFactory;         protected $_minAmount = null;         protected $_maxAmount = null;         protected $_supportedCurrencyCodes = array('USD');         protected $_debugReplacePrivateDataKeys = ['number', 'exp_month', 'exp_year', 'cvc'];                  public function __construct(                 \Magento\Framework\Model\Context $context,                 \Magento\Framework\Registry $registry,                 \Magento\Framework\Api\ExtensionAttributesFactory $extensionFactory,                 \Magento\Framework\Api\AttributeValueFactory $customAttributeFactory,                 \Magento\Payment\Helper\Data $paymentData,                 \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,                 \Magento\Payment\Model\Method\Logger $logger,                 \Magento\Framework\Module\ModuleListInterface $moduleList,                 \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate,                 \Magento\Directory\Model\CountryFactory $countryFactory,                 \Stripe\Stripe $stripe,                 array $data = array()         ) {                   parent::__construct($context,$registry,$extensionFactory,$customAttributeFactory,$paymentData,$scopeConfig,$logger,$moduleList,$localeDate,null,null,$data);                   $this->_countryFactory = $countryFactory;

         $this->_stripeApi = $stripe;        $this->_stripeApi->setApiKey(
            $this->getConfigData('api_key')
         );

         $this->_minAmount = $this->getConfigData('min_order_total');
         $this->_maxAmount = $this->getConfigData('max_order_total');
    }

    /**
     * Payment capturing
     *
     * @param \Magento\Payment\Model\InfoInterface $payment
     * @param float $amount
     * @return $this
     * @throws \Magento\Framework\Validator\Exception
     */
    public function capture(\Magento\Payment\Model\InfoInterface $payment, $amount)
    {
        //throw new \Magento\Framework\Validator\Exception(__('Inside Stripe, throwing donuts :]'));

        /** @var \Magento\Sales\Model\Order $order */
        $order = $payment->getOrder();

        /** @var \Magento\Sales\Model\Order\Address $billing */
        $billing = $order->getBillingAddress();

        try {
            $requestData = [
                'amount'        => $amount * 100,
                'currency'      => strtolower($order->getBaseCurrencyCode()),
                'description'   => sprintf('#%s, %s', $order->getIncrementId(), $order->getCustomerEmail()),
                'card'          => [
                    'number'            => $payment->getCcNumber(),
                    'exp_month'         => sprintf('%02d',$payment->getCcExpMonth()),
                    'exp_year'          => $payment->getCcExpYear(),
                    'cvc'               => $payment->getCcCid(),
                    'name'              => $billing->getName(),
                    'address_line1'     => $billing->getStreetLine(1),
                    'address_line2'     => $billing->getStreetLine(2),
                    'address_city'      => $billing->getCity(),
                    'address_zip'       => $billing->getPostcode(),
                    'address_state'     => $billing->getRegion(),
                    'address_country'   => $billing->getCountryId(),
                    // To get full localized country name, use this instead:
                    // 'address_country'   => $this->_countryFactory->create()->loadByCode($billing->getCountryId())->getName(),
                ]
            ];

            $charge = \Stripe\Charge::create($requestData);
            $payment
                ->setTransactionId($charge->id)
                ->setIsTransactionClosed(0);

        } catch (\Exception $e) {
            $this->debugData(['request' => $requestData, 'exception' => $e->getMessage()]);
            $this->_logger->error(__('Payment capturing error.'));
            throw new \Magento\Framework\Validator\Exception(__('Payment capturing error.'));
        }

        return $this;
    }

    /**
     * Payment refund
     *
     * @param \Magento\Payment\Model\InfoInterface $payment
     * @param float $amount
     * @return $this
     * @throws \Magento\Framework\Validator\Exception
     */
    public function refund(\Magento\Payment\Model\InfoInterface $payment, $amount)
    {
        $transactionId = $payment->getParentTransactionId();

        try {
            \Stripe\Charge::retrieve($transactionId)->refund(['amount' => $amount * 100]);
        } catch (\Exception $e) {
            $this->debugData(['transaction_id' => $transactionId, 'exception' => $e->getMessage()]);
            $this->_logger->error(__('Payment refunding error.'));
            throw new \Magento\Framework\Validator\Exception(__('Payment refunding error.'));
        }

        $payment
            ->setTransactionId($transactionId . '-' . \Magento\Sales\Model\Order\Payment\Transaction::TYPE_REFUND)
            ->setParentTransactionId($transactionId)
            ->setIsTransactionClosed(1)
            ->setShouldCloseParentTransaction(1);

        return $this;
    }

    /**
     * Determine method availability based on quote amount and config data
     *
     * @param \Magento\Quote\Api\Data\CartInterface|null $quote
     * @return bool
     */
    public function isAvailable(\Magento\Quote\Api\Data\CartInterface $quote = null)
    {
        if ($quote && (
            $quote->getBaseGrandTotal() < $this->_minAmount
            || ($this->_maxAmount && $quote->getBaseGrandTotal() > $this->_maxAmount))
        ) {
            return false;
        }

        if (!$this->getConfigData('api_key')) {
            return false;
        }

        return parent::isAvailable($quote);
    }

    /**
     * Availability for currency
     *
     * @param string $currencyCode
     * @return bool
     */
    public function canUseForCurrency($currencyCode)
    {
        if (!in_array($currencyCode, $this->_supportedCurrencyCodes)) {
            return false;
        }
        return true;
    }
}

In this file, there are two main methods:

  1. capture(): This method is handling the process of charging the credit card and saving the transaction. We are just fetching the billing address details from payment object, and the passing it to stripe API along with card details and order amount. The API will process this data and will return a charge object. We are just saving its id as transaction id for the order.
  2. refund(): This method will be used to process the refund. The previously saved transaction id will be sent to the API and then refund will be processed.

You can see the exact files and directory structure over here.

Creating Custom Payment Method in Magento 2

Out of the box, Magento comes with several payment methods such as Paypal, Braintree, COD, Bank transfer etc. But we might need to create our own custom payment method to meet any specific need to business. generally, there are two types of payment methods:

  1. Offline Payment Method
  2. Online Payment Method

In this blog, we will learn about creating an offline payment method.

We will need to create a custom module with following files:

1. create Excellence/Payment/registration.php (this will be used to register your module)

<?php

\Magento\Framework\Component\ComponentRegistrar::register(
    \Magento\Framework\Component\ComponentRegistrar::MODULE,
    'Excellence_Payment',
    __DIR__
);

2. Create Excellence/Payment/etc/module.xml (this will be used to define the module)

<?xml version="1.0"?>
<!--
/**
* @copyright Copyright (c) 2015 X.commerce, Inc. (http://www.magentocommerce.com)
*/
-->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
 <module name="Excellence_Payment" setup_version="1.0.0">
 </module>
</config>

3. Create Excellence/Payment/etc/config.xml for define your payment method.

<?xml version="1.0"?>
<!--
/**
 * Copyright © 2015 Magento. All rights reserved.
 * See COPYING.txt for license details.
 */
-->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../Store/etc/config.xsd">
    <default>
        <payment>
                <paymentmethod>
                <active>1</active>
                <title>PaymentMethod</title>
                <order_status>pending_payment</order_status>
                <instructions>Instruction.</instructions>
                <payment_action>true</payment_action>
                <model>Excellence\Payment\Model\PaymentMethod</model>
                <group>offline</group>
            </paymentmethod>
            <!-- payment-config -->
        </payment>
    </default>
</config>

4. Now we will define the system configuration using Excellence/Payment/etc/adminhtml/system.xml, so that admin can handle the configuration of the payment method

<?xml version="1.0"?>
<!--
/**
 * Copyright © 2015 Magento. All rights reserved.
 * See COPYING.txt for license details.
 */
-->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../Config/etc/system_file.xsd">
    <system>
        <section id="payment">
            <group id="paymentmethod" translate="label" type="text" sortOrder="100" showInDefault="1" showInWebsite="1" showInStore="1">
                <label>Payment</label>
                <field id="active" translate="label" type="select" sortOrder="1" showInDefault="1" showInWebsite="1" showInStore="0">
                    <label>Enabled</label>
                    <source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
                </field>
                <field id="title" translate="label" type="text" sortOrder="10" showInDefault="1" showInWebsite="1" showInStore="1">
                    <label>Title</label>
                </field>
                <field id="order_status" translate="label" type="select" sortOrder="20" showInDefault="1" showInWebsite="1" showInStore="0">
                    <label>New Order Status</label>
                    <source_model>Excellence\Payment\Model\Config\Source\Order\Status\Pendingpayment</source_model>
                </field>
              
                <field id="allowspecific" translate="label" type="allowspecific" sortOrder="40" showInDefault="1" showInWebsite="1" showInStore="0">
                    <label>Payment from Applicable Countries</label>
                    <source_model>Magento\Payment\Model\Config\Source\Allspecificcountries</source_model>
                </field>
                <field id="specificcountry" translate="label" type="multiselect" sortOrder="41" showInDefault="1" showInWebsite="1" showInStore="0">
                    <label>Payment from Specific Countries</label>
                    <source_model>Magento\Directory\Model\Config\Source\Country</source_model>
                    <can_be_empty>1</can_be_empty>
                </field>
                <field id="instructions" translate="label" sortOrder="50" showInDefault="1" showInWebsite="1" showInStore="1">
                    <label>Instructions</label>
                </field>
                <field id="sort_order" translate="label" type="text" sortOrder="100" showInDefault="1" showInWebsite="1" showInStore="0">
                    <label>Sort Order</label>
                    <frontend_class>validate-number</frontend_class>
                </field>
            </group>
            <!-- payment-group -->
        </section>
    </system>
</config>

5. Now create the model file that we had defined in config.xml at Excellence/Payment/Model/PaymentMethod.php

<?php
/**
 * Copyright © 2015 Magento. All rights reserved.
 * See COPYING.txt for license details.
 */
namespace Excellence\Payment\Model;

/**
 * Pay In Store payment method model
 */
class PaymentMethod extends \Magento\Payment\Model\Method\AbstractMethod
{

    /**
     * Payment code
     *
     * @var string
     */
    protected $_code = 'paymentmethod';

    /**
     * Availability option
     *
     * @var bool
     */
    protected $_isOffline = true;
}

Now we are done with the basic files and configurations, now we will show the payment method on the frontend.

6. Create Excellence/Payment/view/frontend/web/js/view/payment/paymentmethod.js (it will be used to register the template and render it)

/**
 * Copyright © 2015 Magento. 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: 'paymentmethod',
                component: 'Excellence_Payment/js/view/payment/method-renderer/paymentmethod-method'
            }
        );
        /** Add view logic here if needed */
        return Component.extend({});
    }
);

7. Create Excellence/Payment/view/frontend/web/js/view/payment/method-renderer/paymentmethod-method.js

/**
 * Copyright © 2015 Magento. All rights reserved.
 * See COPYING.txt for license details.
 */
/*browser:true*/
/*global define*/
define(
    [
        'Magento_Checkout/js/view/payment/default'
    ],
    function(Component) {
        'use strict';

        return Component.extend({
            defaults: {
                template: 'Excellence_Payment/payment/paymentmethod'
            },

            /** Returns send check to info */
            getMailingAddress: function() {
                return window.checkoutConfig.payment.checkmo.mailingAddress;
            },


        });
    }
);

8. Now create the template file at Excellence/Payment/view/frontend/web/template/payment/paymentmethod.html

<!--
/**
 * Copyright © 2015 Magento. 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>
        <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>

9. Now create Excellence/Payment/view/frontend/layout/checkout_index_index.xml for adding the payment method to checkout page.

<?xml version="1.0"?>
<!--
/**
 * Copyright © 2015 Magento. All rights reserved.
 * See COPYING.txt for license details.
 */
-->
<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">
                                                            <item name="children" xsi:type="array">
                                                            <!-- merge payment method renders here -->
                                                                <item name="payment-paymentmethod" xsi:type="array">
                                                                    <item name="component" xsi:type="string">Excellence_Payment/js/view/payment/paymentmethod</item>
                                                                    <item name="methods" xsi:type="array">
                                                                  
                                                                         <item name="paymentmethod" xsi:type="array">
                                                                            <item name="isBillingAddressRequired" xsi:type="boolean">true</item>
                                                                        </item>
                                                                    </item>
                                                                </item>
                                                            <!-- item-renderer -->
                                                            </item>
                                                        </item>
                                                    </item>
                                                </item>
                                            </item>
                                        </item>
                                    </item>
                                </item>
                            </item>
                        </item>
                    </item>
                </argument>
            </arguments>
        </referenceBlock>
    </body>
</page>

That’s all folks.

In next blog, we will learn to create online payment method.