如何在Magento 2结账页面添加Taxvat字段(巴西CPF场景)
Hey there! Let's get that CPF validation and field configuration polished for your Magento 2 checkout. You've already laid the groundwork by adding the taxvat field via layoutProcessor—now let's make it robust and compliant with Brazilian CPF requirements.
1. Update the Field Configuration in Your LayoutProcessor
First, refine the taxvat field definition to include input masking, proper validation rules, and correct data mapping:
$shippingFields['taxvat'] = [ 'component' => 'Magento_Ui/js/form/element/input', 'label' => __('CPF'), 'config' => [ 'customScope' => 'shippingAddress', 'template' => 'ui/form/field', 'elementTmpl' => 'ui/form/element/input', 'mask' => '000.000.000-00' // Adds CPF input formatting for user convenience ], 'placeholder' => __('CPF *'), 'validation' => [ 'required-entry' => true, 'min_text_length' => 11, 'max_text_length' => 11, 'validate-cpf' => true // Custom validation rule we'll create next ], 'sortOrder' => 25, // Adjust position to fit your checkout flow (e.g., after email) 'dataScope' => 'shippingAddress.taxvat' // Ensures data saves to the correct address field ];
2. Add Custom Frontend CPF Validation
Magento doesn't include a built-in CPF validator, so we'll create one. Create a validation script in your custom module:
File: app/code/YourVendor/YourModule/view/frontend/web/js/validation.js
define([ 'jquery', 'mage/validation' ], function ($) { 'use strict'; $.validator.addMethod( 'validate-cpf', function (value) { // Clean non-numeric characters from input const cleanCpf = value.replace(/[^\d]/g, ''); // Reject invalid length or all repeated digits if (cleanCpf.length !== 11 || /^(\d)\1{10}$/.test(cleanCpf)) { return false; } // Calculate first verification digit let sum = 0; for (let i = 0; i < 9; i++) { sum += parseInt(cleanCpf[i]) * (10 - i); } let remainder = sum % 11; const digit1 = remainder < 2 ? 0 : 11 - remainder; if (parseInt(cleanCpf[9]) !== digit1) { return false; } // Calculate second verification digit sum = 0; for (let i = 0; i < 10; i++) { sum += parseInt(cleanCpf[i]) * (11 - i); } remainder = sum % 11; const digit2 = remainder < 2 ? 0 : 11 - remainder; return parseInt(cleanCpf[10]) === digit2; }, $.mage.__('Please enter a valid CPF number.') ); return function () {}; });
Next, register this validator with RequireJS:
File: app/code/YourVendor/YourModule/view/frontend/requirejs-config.js
var config = { config: { mixins: { 'mage/validation': { 'YourVendor_YourModule/js/validation': true } } } };
3. Add Backend Validation (Critical!)
Frontend validation can be bypassed, so we need to add server-side checks. Create a plugin to validate the CPF when saving shipping information:
File: app/code/YourVendor/YourModule/Plugin/Checkout/Model/ShippingInformationManagement.php
<?php namespace YourVendor\YourModule\Plugin\Checkout\Model; use Magento\Checkout\Model\ShippingInformationManagement; use Magento\Framework\Exception\LocalizedException; use Magento\Quote\Model\QuoteRepository; class ShippingInformationManagementPlugin { protected $quoteRepository; public function __construct(QuoteRepository $quoteRepository) { $this->quoteRepository = $quoteRepository; } public function beforeSaveAddressInformation( ShippingInformationManagement $subject, $cartId, \Magento\Checkout\Api\Data\ShippingInformationInterface $addressInformation ) { $shippingAddress = $addressInformation->getShippingAddress(); $taxvat = $shippingAddress->getTaxvat(); if (empty($taxvat)) { throw new LocalizedException(__('CPF is required.')); } // Clean CPF of non-numeric characters $cleanCpf = preg_replace('/[^\d]/', '', $taxvat); if (!$this->validateCpf($cleanCpf)) { throw new LocalizedException(__('Please enter a valid CPF number.')); } // Save the cleaned CPF back to the address $shippingAddress->setTaxvat($cleanCpf); } private function validateCpf(string $cpf): bool { if (strlen($cpf) !== 11 || preg_match('/^(\d)\1{10}$/', $cpf)) { return false; } // Validate first digit $sum = 0; for ($i = 0; $i < 9; $i++) { $sum += (int)$cpf[$i] * (10 - $i); } $remainder = $sum % 11; $digit1 = $remainder < 2 ? 0 : 11 - $remainder; if ((int)$cpf[9] !== $digit1) { return false; } // Validate second digit $sum = 0; for ($i = 0; $i < 10; $i++) { $sum += (int)$cpf[$i] * (11 - $i); } $remainder = $sum % 11; $digit2 = $remainder < 2 ? 0 : 11 - $remainder; return (int)$cpf[10] === $digit2; } }
Register the plugin in your module's di.xml:
File: app/code/YourVendor/YourModule/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\ShippingInformationManagement"> <plugin name="validate_checkout_cpf" type="YourVendor\YourModule\Plugin\Checkout\Model\ShippingInformationManagementPlugin" sortOrder="10"/> </type> </config>
4. Final Steps
After making these changes, clear Magento's cache and deploy static content:
bin/magento cache:clean bin/magento setup:static-content:deploy pt_BR en_US # Adjust languages as needed
This setup will:
- Give users a formatted input field for CPF
- Validate the CPF format and checksum on the frontend
- Enforce validation on the backend to prevent invalid entries
- Save a clean, numeric CPF to the customer's shipping address
内容的提问来源于stack exchange,提问作者Jônatas Zulske

