CNPJ alfanumérico no WooCommerce (WordPress): como adaptar
Adapte o checkout do WooCommerce ao novo CNPJ alfanumérico: valide o campo billing_cnpj com o hook woocommerce_after_checkout_validation e libere letras na máscara JS.
Adaptar o CNPJ alfanumérico no WooCommerce exige dois ajustes: validar o campo billing_cnpj no checkout aceitando letras e trocar a máscara numérica do front-end por uma que aceite A–Z. Este tutorial mostra o código pronto para um mu-plugin (ou functions.php), usando o hook real woocommerce_after_checkout_validation e a função de validação verificada.
O que muda no CNPJ alfanumérico
A partir de julho de 2026, o novo CNPJ mantém 14 posições e a mesma máscara XX.XXX.XXX/XXXX-DD, mas as 12 primeiras posições passam a aceitar letras maiúsculas (A–Z) além de dígitos. Os dois dígitos verificadores continuam numéricos. Os CNPJs numéricos atuais não mudam e seguem válidos — seu checkout precisa aceitar os dois formatos. Veja o panorama completo no nosso guia de implementação do CNPJ alfanumérico.
Por que a validação antiga rejeita CNPJ com letras
O plugin Brazilian Market on WooCommerce (Claudio Sanches) é o mais usado para adicionar o campo billing_cnpj ao checkout. Em versões recentes, os campos de CPF/CNPJ usam type="tel" com uma máscara que assume 14 dígitos numéricos — qualquer letra digitada é descartada ou marcada como inválida. Some-se a isso a validação de DV baseada na regra antiga (só números) e o resultado é que um CNPJ como 12.ABC.345/01DE-35, perfeitamente válido, é recusado na finalização do pedido. A correção é substituir a validação numérica pela alfanumérica e liberar letras na máscara.
Validando CNPJ alfanumérico em PHP
Cole a função de validação abaixo em um mu-plugin (recomendado, em wp-content/mu-plugins/cnpj-alfanumerico.php) ou no functions.php do tema-filho. Ela normaliza a entrada para maiúsculas, confere o formato e recalcula os dígitos verificadores:
<?php
const PESO1 = [5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2];
const PESO2 = [6, 5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2];
function normalizarCnpj(string $s): string {
return preg_replace('/[^A-Z0-9]/', '', strtoupper($s));
}
function digitoCnpj(string $base, array $pesos): int {
$soma = 0;
for ($i = 0; $i < strlen($base); $i++) {
$soma += (ord($base[$i]) - 48) * $pesos[$i];
}
$resto = $soma % 11;
return $resto < 2 ? 0 : 11 - $resto;
}
function calcularDvCnpj(string $base12): string {
$d1 = digitoCnpj($base12, PESO1);
$d2 = digitoCnpj($base12 . $d1, PESO2);
return $d1 . $d2;
}
function validarCnpj(string $cnpj): bool {
$c = normalizarCnpj($cnpj);
if (!preg_match('/^[A-Z0-9]{12}[0-9]{2}$/', $c)) return false;
if (preg_match('/^0{12}/', $c)) return false;
return calcularDvCnpj(substr($c, 0, 12)) === substr($c, 12);
}
// var_dump(validarCnpj('12.ABC.345/01DE-35')); // true
Plugando no checkout com o hook woocommerce_after_checkout_validation
O WooCommerce dispara a action woocommerce_after_checkout_validation depois de validar os campos do checkout clássico — é o ponto correto para validações personalizadas. Para barrar um CNPJ inválido, chame wc_add_notice( ..., 'error' ): a presença de um aviso do tipo error impede que o pedido seja finalizado. O hook recebe os dados já sanitizados em $data, onde está o billing_cnpj:
<?php
add_action('woocommerce_after_checkout_validation', function ($data, $errors) {
// só valida quando o campo CNPJ foi preenchido (pessoa jurídica)
$cnpj = isset($data['billing_cnpj']) ? trim($data['billing_cnpj']) : '';
if ($cnpj === '') {
return;
}
if (!validarCnpj($cnpj)) {
wc_add_notice(
__('O CNPJ informado é inválido. Confira os dígitos (aceitamos o novo formato com letras).', 'meu-tema'),
'error'
);
}
}, 10, 2);
Ajustando a máscara JS do campo (aceitar A–Z, maiúsculas)
No front-end, garanta que o campo aceite letras: troque type="number"/máscara numérica por texto, aplique text-transform:uppercase e use a função de validação golden no blur. O trecho abaixo libera A–Z, força maiúsculas e marca visualmente erros antes do envio:
// Valor de cada caractere = código ASCII - 48 ('0'=0..'9'=9, 'A'=17..'Z'=42)
const PESO1 = [5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2];
const PESO2 = [6, 5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2];
const normalizar = (s) => (s || '').toUpperCase().replace(/[^A-Z0-9]/g, '');
function digito(base, pesos) {
let soma = 0;
for (let i = 0; i < base.length; i++) soma += (base.charCodeAt(i) - 48) * pesos[i];
const resto = soma % 11;
return resto < 2 ? 0 : 11 - resto;
}
function calcularDV(base12) { // base12 = 12 primeiras posições
const d1 = digito(base12, PESO1);
const d2 = digito(base12 + d1, PESO2);
return `${d1}${d2}`;
}
function validarCNPJ(cnpj) {
const c = normalizar(cnpj);
if (!/^[A-Z0-9]{12}[0-9]{2}$/.test(c)) return false;
if (/^0{12}/.test(c)) return false; // base zerada
return calcularDV(c.slice(0, 12)) === c.slice(12);
}
// Liga ao campo do plugin Brazilian Market (#billing_cnpj)
jQuery(function ($) {
const $campo = $('#billing_cnpj');
$campo.attr('maxlength', 18).css('text-transform', 'uppercase');
$campo.on('input', function () {
// aceita letras e dígitos, força maiúsculas, aplica a máscara
const c = normalizar(this.value).slice(0, 14);
this.value = c.replace(/^(..)(...)(...)(....)(..)$/, '$1.$2.$3/$4-$5');
});
$campo.on('blur', function () {
const ok = this.value === '' || validarCNPJ(this.value);
$(this).toggleClass('cnpj-invalido', !ok);
});
});
Se você usa a máscara do próprio plugin (jQuery Mask), desative-a para o campo CNPJ ou ajuste o padrão para SS.SSS.SSS/SSSS-00 (em vez de 00.000.000/0000-00), pois 0 só aceita dígitos e S aceita letras.
Como testar
- Instale o mu-plugin com a função PHP e o hook de validação.
- Enfileire o script JS no checkout e confira o seletor
#billing_cnpj. - Tente finalizar um pedido com um CNPJ alfanumérico válido — deve passar.
- Tente um com DV errado — deve aparecer o aviso de erro e bloquear o pedido.
- Confirme que um CNPJ numérico antigo continua sendo aceito.
Gere massa de teste com o nosso gerador de CNPJ alfanumérico e confira cada resultado no validador de CNPJ alfanumérico. Use os vetores abaixo:
| CNPJ | Tipo | Resultado esperado |
|---|---|---|
12.ABC.345/01DE-35 | Alfanumérico (filial) | Válido |
XP.TO1.234/0001-20 | Alfanumérico (matriz) | Válido |
9F.8E7.D6C/0001-36 | Alfanumérico (matriz) | Válido |
A1.B2C.3D4/E5F6-68 | Alfanumérico (filial) | Válido |
11.222.333/0001-81 | Numérico clássico | Válido |
12.ABC.345/01DE-34 | DV incorreto | Inválido |
Perguntas frequentes
Preciso trocar o plugin Brazilian Market on WooCommerce?
Não necessariamente. Enquanto o plugin não publica suporte oficial ao formato alfanumérico, você sobrescreve a validação com o hook woocommerce_after_checkout_validation e ajusta a máscara via JavaScript, mantendo o campo billing_cnpj que ele já cria. Quando o plugin atualizar, basta remover seu mu-plugin.
Por que usar um mu-plugin em vez do functions.php?
Um mu-plugin (must-use) carrega sempre, não é desativado por engano e sobrevive à troca de tema. Como a validação fiscal é crítica, isolá-la em wp-content/mu-plugins/ evita que uma atualização de tema derrube a regra. O functions.php do tema-filho também funciona, mas é mais frágil.
O campo precisa ser salvo no banco em maiúsculas?
Sim. Guarde o CNPJ como texto (não inteiro), sem máscara e sempre em maiúsculas, para que buscas e comparações funcionem. O WooCommerce já armazena billing_cnpj como meta de texto; garanta apenas a normalização antes de salvar para não misturar maiúsculas e minúsculas.
A validação em JavaScript dispensa a validação no PHP?
Não. O JavaScript melhora a experiência, mas pode ser desligado ou contornado. A validação no servidor, via hook do WooCommerce, é a que realmente garante a integridade do pedido. Use as duas, com a mesma lógica de DV.
Fontes: Receita Federal (IN RFB 2.229/2024) e nota técnica do Serpro sobre o CNPJ alfanumérico. Para outras stacks, veja também CNPJ alfanumérico no Magento 2 e como validar CNPJ alfanumérico em PHP.
Ofertas em destaque
Ver todas →
Amazon
-27%
Hellmann's Maionese Light 500g
Mercado Livre
Kit 10 Pares Meia Invisível Unissex Soquete Algodão Selene 10 Branco Original Soquete Cano Curto G ( 39 A 44 )
Shopee
-60%
Brow Rise Gel Para Sobrancelhas By Ruby Rose Linha Rosa HB-E2503 Hot Sale
Shopee
-56%
Calça Pantalona Lanzinha Feminina Cintura Alta Com Elastico De e Bolso Outono / Inverno Promoção
Amazon
-93%
Tramontina Ducha Elétrica 3 Temperaturas 5500 W 127 V Chuveiro Branco
Amazon
Leite em Pó Ninho Integral Instantâneo Sachê 975g
Mercado Livre
Perfume Lattafa Bade'e Al Oud For Glory Edp Spray 100 Ml
Amazon
-14%
Lenços Umedecidos Huggies Rosto e Corpo Limpeza 4 x 48 Un
Shopee
-33%