Cursos Magento

Novo campo de endereço no checkout – Passo a passo

,

Atualizado em 01 de março de 2022

Para se fazer um pedido no Magento é preciso informar um endereço de cobrança durante o processo de checkout. Se estiver realizando uma compra que exija que um ou mais produtos sejam entregues, um endereço de entrega também é solicitado.

Você pode adicionar novos campos nos formulários de checkout do Magento. Ao longo deste artigo veremos como adicionar um novo campo no formulário de endereço de entrega e/ou de cobrança.

Para fins deste exemplo, vamos criar um novo campo de endereço chamado “Referência para Entrega”.

Para fazer isso você precisará:

  1. Adicionar o campo no Layout
  2. Adicionar um mixin JavaScript para modificar o que está sendo enviado
  3. Carregar o mixin
  4. Adicionar o campo no Model de endereço
  5. Acessar o valor que está sendo enviado no lado do servidor
  6. Conclusão
  7. Módulo final

Adicionando campo no LayoutProcessor

Tanto os campos de endereço de cobrança quanto os de entrega são gerados dinamicamente. Isto é, através de classes PHP que injetam estes campos no método \Magento\Checkout\Block\Checkout\LayoutProcessor::process.

Sendo assim, a melhor forma para se injetar um novo campo neste método é através do uso de Plugins – um componente comum no Magento 2, e amplamente explicado no Magento 2: O Curso.

O trecho de código abaixo pode ser usado num Plugin do tipo before para o método acima.

<?php
// ...
    /**
     * @param \Magento\Checkout\Block\Checkout\LayoutProcessor $subject
     * @param array                                            $jsLayout
     *
     * @return array[]
     */
    public function beforeProcess(\Magento\Checkout\Block\Checkout\LayoutProcessor $subject, $jsLayout)
    {
        $customAttributeCode = 'referencia_entrega';
        $customField = ['component'                         => 'Magento_Ui/js/form/element/abstract',
                        'config'                  => [//customScope é usado para agrupar elementos em um form simples
                                                      // (assim eles podem ser validados separadamente)
                                                      'customScope' => 'shippingAddress.custom_attributes',
                                                      'customEntry' => null,
                                                      'template'    => 'ui/form/field',
                                                      'elementTmpl' => 'ui/form/element/input',
                                                      'tooltip'     => [
                                                          'description' => 'Usado pelo serviço de entrega',
                                                          ],],
                        'dataScope'                         => 'shippingAddress.custom_attributes'
                            . '.' . $customAttributeCode,
                        'label'                             => 'Referência para Entrega',
                        'provider'                          => 'checkoutProvider',
                        'sortOrder'                         => 70,
                        'validation'                        => ['required-entry' => false],
                        'options'                           => [],
                        'filterBy'                          => null,
                        'customEntry'                       => null,
                        'visible'                           => true,
                        'value'                             => '' // valor padrão
        ];

        $jsLayout['components']['checkout']['children']['steps']['children']['shipping-step']['children']['shippingAddress']['children']['shipping-address-fieldset']['children'][$customAttributeCode]
            = $customField;

        return [$jsLayout];
    }

No exemplo acima, adicionamos o campo de “Referência de endereço” no endereço de entrega. Fizemos isso adicionando o campo na propriedade customAttributes do Magento_Checkout/js/model/new-customer-address.js, que é um objeto que lista os atributos de endereço pré-definido e faz a associação com o atributo correspondente do lado do servidor usando a interface \Magento\Quote\Api\Data\AddressInterface.

A propriedade customAttributes foi desenhada para conter atributos de endereço do tipo EAC e relacionada com o método \Magento\Quote\Model\Quote\Address\CustomAttributeListInterface::getAttributes. O exemplo acima vai lidar automaticamente com a gravação do atributo dentro do local storage no frontend da loja. Não é legal?

Alternativa: Usando Injeção de Dependência

Opcionalmente, ao invés de adicionar um Plugin, você pode fazer uso de Injeção de Dependência. Para fazer desta forma, adicione o LayoutProcessor (que adiciona um campo personalizado de endereço à classe de formulário de endereço) dentro do diretório <seu_modulo>/Block/Checkout. A classe deve implementar \Magento\Checkout\Block\Checkout\LayoutProcessorInterface. Use o código acima na sua implementação de \Magento\Checkout\Block\Checkout\LayoutProcessorInterface::process() na sua classe.

Depois é só adicionar o LayoutProcessor na lista de “processors”, especificando o seguinte:

<type name="Magento\Checkout\Block\Onepage">
        <arguments>
            <argument name="layoutProcessors" xsi:type="array">
                <item name="%nome_unico%" xsi:type="object">%seu\modulo\seu\LayoutProcessor%</item>
            </argument>
        </arguments>
</type>

Onde %nomeunico% e %seu\modulo\seu\LayoutProcessor% devem ser trocados por valores reais, de acordo com aqueles definidos no <seu_modulo>/etc/frontend/di.xml.

Adicione um mixin JavaScript

Mixins são como Plugins para JavaScript no Magento. Neste exercício eles nos permitirão mudar o comportamento do componente responsável pelo envio de dados do formulário.

No seu módulo, defina um mixin como um módulo AMD separado, que retorna um método (callback). Adicione o mixin em qualquer lugar em <seu_modulo>/view/frontend/web. Não há requisitos ou restrições para o nome dele.

O código abaixo é um exemplo de mixin para mudar o comportamento de Magento_Checkout/js/action/set-shipping-information, que é o componente responsável pelo envio dos dados do formulário entre os passos de cobrança e entrega.

/*jshint browser:true jquery:true*/
/*global alert*/
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'] = {};
            }

            var attribute = shippingAddress.customAttributes.find(
                function (element) {
                    return element.attribute_code === 'referencia_entrega';
                }
            );

            shippingAddress['extension_attributes']['referencia_entrega'] = attribute.value;

            // chama o método original ('Magento_Checkout/js/action/set-shipping-information')
            return originalAction();
        });
    };
});

Ao adicionar um campo no endereço de cobrança, você deve modificar o comportamento de Magento_Checkout/js/action/place-order ou Magento_Checkout/js/action/set-payment-information dependendo do momento que você deseja passar o valor do campo personalizado para o servidor. Um exemplo de um mixin que modifica um destes componentes pode ser visto no place-order-mixin.js do módulo Magento_CheckoutAgreements.

Carregue o seu mixin

Para registrar o mixin que acabamos de criar, precisamos inserir o conteúdo abaixo no arquivo <seu_modulo>/view/frontend/requirejs-config.js:

var config = {
    config: {
        mixins: {
            'Magento_Checkout/js/action/set-shipping-information': {
                'Magenteiro_CampoEndereco/js/referencia-endereco-mixin': true
            }
        }
    }
};

No meu caso, o nome que dei para meu mixin no passo anterior foi referencia-endereco-mixin.js. Altere isso e o nome do módulo de acordo com sua necessidade.

Adicionar o campo no Model

Para fazer o Model de endereço enxergar o nosso atributo no backend (lado do servidor), precisamos adicionar o arquivo extension_attributes.xml em <seu_modulo>/etc/.

Veja o exemplo:

<?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="referencia_entrega" type="string" />
    </extension_attributes>
</config>

Lembre-se de apagar o diretório generated/code quando fizer o setup:di:compile. Novos métodos serão adicionados em generated/code/Magento/Quote/Api/Data/AddressExtension.php.

Acessando o valor do lado do servidor

Se você seguiu os passos anteriores, o seu atributo já está disponível no backend, pois o Magento gerou novamente a interface de endereço com o novo elemento.

Você pode obter esses valores quando cria uma nova instância de Magento/Quote/Api/Data/AddressInterface.php. Veja um exemplo simples:

<?php

// ... //

use Magento\Checkout\Api\Data\ShippingInformationInterface;
use Magento\Framework\View\Element\Template;
use Magento\Framework\View\Element\Template\Context;

class MyBlock extends Template {

    /**
     * @var ShippingInformationInterface
     */
    private $_addressInformation;

    /**
     * @param Context $context
     * @param ShippingInformationInterface $addressInformation
     * @param array $data
     */
    public function __construct(
        Context $context,
        ShippingInformationInterface $addressInformation,
        array $data = []
    ) {
        $this->_addressInformation = $addressInformation;
        parent::__construct($context, $data);
    }

    /**
     * Get custom Shipping Charge
     *
     * @return String
     */
    public function getShippingCharge()
    {
        $extAttributes = $this->_addressInformation->getExtensionAttributes();
        return $extAttributes->getReferenciaEndereco(); //pega atributo personalizado.
    }
}

Conclusão e ressalvas

O exemplo acima mostrou como adicionar um novo campo de endereço ao nosso checkout Magento.

Fizemos isso usando extension attributes, um recurso novo implementado no Magento 2. Ele nos possibilita inserir novos e (nem sempre) complexos atributos à interfaces como as de produto, cliente, endereço, etc.

No entanto, um extension_attribute não é persistido na base de dados nem visível no admin por padrão. Você pode usar esta abordagem do jeito que está aqui para algum tipo de integração ou regra de negócio que não precise de persistência no banco.

Se ter este valor no banco e eventualmente exibido no admin da loja é um pré-requisito para sua necessidade, você então precisará implementar um outro Plugin para salvar estes valores por lá em novas colunas ou tabelas.

Quem sabe não abordamos isto em outro artigo. Comente!

Referência: Documentação Oficial (em Inglês)

Módulo final (do exemplo)

Se desejar, faça download do nosso módulo do exemplo acima. Basta preencher o form abaixo.

Últimos posts por Ricardo Martins (exibir todos)
Comentários

Deixe seu comentário

[fbcomments url="https://www.magenteiro.com/blog/magento-2/campo-endereco-checkout-tutorial/"]