Grupos exclusivos de desconto no WhatsApp — Faca parte agora! Participar

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.

CNPJ alfanumérico no WooCommerce (WordPress): como adaptar

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
<?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
<?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:

JavaScript
// 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

Passo a passo
  • 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:

CNPJTipoResultado esperado
12.ABC.345/01DE-35Alfanumérico (filial)Válido
XP.TO1.234/0001-20Alfanumérico (matriz)Válido
9F.8E7.D6C/0001-36Alfanumérico (matriz)Válido
A1.B2C.3D4/E5F6-68Alfanumérico (filial)Válido
11.222.333/0001-81Numérico clássicoVálido
12.ABC.345/01DE-34DV incorretoInvá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.

Assistente PP
Assistente PP
Online agora
Powered by Primeira Solução