Magento 2.2 – Adding Custom Field to Billing Address

custom-fieldcustomer-addressmagento2.2magento2.2.2onepage-checkout

Magento ver. 2.2.2

I added an extra attribute for Customer Address.

It works as aspected in customer address edit (frontend and backend).

In checkout page:

For Shipping Address everything is working fine but is not saved in sales_order_address table (works for quote_address).

For Billing Address:

  • if shipping address is used it works as shipping address.
  • if is different from shipping address but use an existing customer address it works as shipping address.
  • if is new created custom attribute is not saved (not in order,quote or customer)

For Billing Address I've got those files:

app\code\Company\Module\view\frontend\web\js\action\set-billing-address-mixin.js

/*jshint browser:true jquery:true*/
/*global alert*/
define([
    'jquery',
    'mage/utils/wrapper',
    'Magento_Checkout/js/model/quote'
], function ($, wrapper,quote) {
    'use strict';

    return function (setBillingAddressAction) {

        return wrapper.wrap(setBillingAddressAction, function (originalAction) {  
            var billingAddress = quote.billingAddress();
            if (billingAddress && billingAddress.customAttributes){
                if (billingAddress['extension_attributes'] === undefined) {
                    billingAddress['extension_attributes'] = {};
                }
                var taxcode = billingAddress.customAttributes['tax_code'];
                if($.isPlainObject(taxcode)){
                    taxcode = taxcode['value'];
                }
                billingAddress['extension_attributes']['tax_code'] = taxcode;
                // pass execution to original action ('Magento_Checkout/js/action/set-shipping-information')
            }
            return originalAction();
        });
    };
});

app\code\Company\Module\Plugin\Checkout\PaymentInformation.php

<?php
namespace Company\Module\Plugin\Checkout;

class PaymentInformation
{
    protected $logger;

    public function __construct(\Psr\Log\LoggerInterface $logger)
    {
        $this->logger = $logger;
    }

    public function beforeSavePaymentInformation(
        \Magento\Checkout\Model\PaymentInformationManagement $subject,
        $cartId,
        \Magento\Quote\Api\Data\PaymentInterface $paymentMethod,
        \Magento\Quote\Api\Data\AddressInterface $billingAddress = null
    ) {

        if($billingAddress){
            $billingAddressExtensionAttributes = $billingAddress->getExtensionAttributes();
            if ($billingAddressExtensionAttributes) {
                $customField = $billingAddressExtensionAttributes->getTaxCode();
                $billingAddress->setTaxCode($customField);
            }
            $this->logger->debug('ExtensionAttributes::'.(serialize($billingAddressExtensionAttributes)));
            $this->logger->debug('billingAddress::'.(print_r($billingAddress->debug(),true)));
        } else {
            $this->logger->debug('billingAddress is empty');
        }
    }
}

in debug.log:

when shippng address is used

[2018-03-27 16:20:51] main.DEBUG: ExtensionAttributes::O:39:"Magento\Quote\Api\Data\AddressExtension":1:{s:8:" * _data";a:1:{s:8:"tax_code";s:14:"Codice Fiscale";}} [] []
[2018-03-27 16:20:51] main.DEBUG: billingAddress::Array
(
    [country_id] => IT
    [region] => Stato/Provincia
    [street] => Indirizzo
    [company] => Società
    [telephone] => Numero di telefono
    [postcode] => CAP 
    [city] => Città 
    [firstname] => Nome
    [lastname] => Cognome
    [vat_id] => Partita Iva
    [tax_code] => Codice Fiscale
)
 [] []

when is different from shipping address but use an existing customer address

[2018-03-27 16:23:58] main.DEBUG: ExtensionAttributes::N; [] []
[2018-03-27 16:23:58] main.DEBUG: billingAddress::Array
(
    [customer_address_id] => 33
    [country_id] => IT
    [region_code] => Stato/Provincia
    [region] => Stato/Provincia
    [customer_id] => 1
    [street] => Indirizzo
    [company] => Società
    [telephone] => Numero di telefono
    [postcode] => CAP 
    [city] => Città 
    [firstname] => Nome
    [lastname] => Cognome
    [vat_id] => Partita Iva
)
 [] []

When is New Created

[2018-03-27 16:27:42] main.DEBUG: ExtensionAttributes::N; [] []
[2018-03-27 16:27:42] main.DEBUG: billingAddress::Array
(
    [country_id] => IT
    [region] => Stato/Provincia
    [street] => Indirizzo
    [company] => Società
    [telephone] => Numero di telefono
    [postcode] => CAP 
    [city] => Città 
    [firstname] => Nome
    [lastname] => Cognome
    [vat_id] => Partita Iva
    [save_in_address_book] => 1
)
 [] []

Best Answer

In order to get the values from extension attributes to the order i am using this event:

sales_model_service_quote_submit_before

and the code i am using is:

/** @var OrderInterface $order */
    $order = $observer->getEvent()->getOrder();
    $quote = $observer->getEvent()->getQuote();

    $order->getShippingAddress()->setMobilePhone($quote->getShippingAddress()->getMobilePhone());
    $order->getBillingAddress()->setMobilePhone($quote->getBillingAddress()->getMobilePhone());

    $order->getShippingAddress()->setVatRegion($quote->getShippingAddress()->getVatRegion());
    $order->getBillingAddress()->setVatRegion($quote->getBillingAddress()->getVatRegion());

in the observer.

Try this and let me know if it helps