Fale Comigo
Menu

Blog · Engenharia de software

CNPJ alfanumérico já é realidade: o que muda nos sistemas e como preparamos o Pet Táxi

O Brasil passou a ter oficialmente seu primeiro CNPJ alfanumérico e isto ocorreu em 31 de julho de 2026. A inscrição 00.000.000/E08G-12, atribuída a uma filial do Banco do Brasil, marcou a efetiva entrada em operação de uma mudança que vinha sendo preparada desde 2024. Para a maioria das empresas, o impacto visual parece pequeno. O CNPJ continua tendo 14 posições, continua sendo apresentado no conhecido formato e os CNPJs já existentes permanecem válidos.

Para quem desenvolve software, entretanto, a mudança é bem mais profunda. Ela obriga sistemas construídos ao longo de décadas a responder a uma pergunta aparentemente simples: o CNPJ foi tratado como um número ou como aquilo que ele realmente é: um identificador?

O que efetivamente mudou

As 12 primeiras posições do CNPJ no novo padrão, podem conter números de 0 a 9 e letras de A a Z. As duas últimas posições continuam reservadas aos dígitos verificadores e permanecem numéricas. Em termos simplificados, NN.NNN.NNN/NNNN-NN passa a admitir SS.SSS.SSS/SSSS-NN, onde S pode ser número ou letra e N, nas duas últimas posições, continua sendo número.

Isso não significa que todos os CNPJs passarão imediatamente a conter letras. A própria Receita Federal esclarece que novas inscrições ainda podem receber identificadores exclusivamente numéricos enquanto essas combinações estiverem disponíveis. Também não existe conversão dos CNPJs antigos. Quem já possui um CNPJ numérico continua com ele normalmente.

A mudança amplia o espaço disponível para novas inscrições sem romper a compatibilidade com os milhões de identificadores já existentes.

E o dígito verificador?

Uma preocupação natural para quem mantém sistemas próprios é o algoritmo de validação. O cálculo continua utilizando módulo 11. A diferença está na forma de transformar os caracteres em valores antes de aplicar os pesos.

Para os caracteres alfanuméricos, a especificação utiliza o valor decimal correspondente na tabela ASCII e subtrai 48. Assim, os números continuam produzindo seus próprios valores naturais, enquanto as letras passam a possuir valores válidos para o cálculo.

A letra A, por exemplo, possui valor ASCII 65. Para o cálculo do CNPJ: 65 - 48 = 17

A Receita Federal publicou documentação técnica específica sobre o cálculo e disponibilizou exemplos para que desenvolvedores possam adaptar validadores e realizar testes de conformidade.

Trecho 01 · validação e dígitos verificadores
$cnpj = normalizarCnpj($valor);
if ($cnpj === null || $cnpj === '' ||
    preg_match('/^([0-9])\1{13}$/D', $cnpj) === 1) {
    return false;
}

$calcular = static function (string $base, array $pesos): int {
    $soma = 0;
    foreach ($pesos as $indice => $peso) {
        $soma += (ord($base[$indice]) - 48) * $peso;
    }
    $resto = $soma % 11;
    return $resto < 2 ? 0 : 11 - $resto;
};

$base = substr($cnpj, 0, 12);
$d1 = $calcular($base, [5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2]);
if ($d1 !== (int) $cnpj[12]) { return false; }

$d2 = $calcular($base . $d1, [6, 5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2]);
return $d2 === (int) $cnpj[13];

Essa alteração parece pequena, mas revela por que simplesmente mudar a máscara de um formulário está longe de ser suficiente.

O verdadeiro problema está nas suposições escondidas no software

Durante muitos anos, uma técnica extremamente comum para tratar CNPJ em sistemas foi remover tudo aquilo que não fosse número. Para um CNPJ tradicional, 12.345.678/0001-95, remover pontos, barra, hífen e qualquer outro caractere não numérico resultava em 12345678000195. Funcionava. Por isso, inúmeras aplicações acabaram utilizando, direta ou indiretamente, a seguinte premissa: normalizar CNPJ = manter apenas dígitos.

Com o novo padrão, isso deixa de ser verdade. Pegue o primeiro CNPJ alfanumérico real emitido pela Receita, 00.000.000/E08G-12; se uma rotina antiga mantiver somente os números, o resultado será 000000000812. As letras E e G desapareceram.

O identificador, que originalmente possuía 14 posições, passa a ter apenas 12. Não estamos diante de um problema estético de formatação. Houve perda de informação. É nesse ponto que sistemas aparentemente preparados podem começar a falhar.

Um campo pode aceitar letras corretamente enquanto uma integração elimina essas mesmas letras alguns milissegundos depois. O banco pode estar preparado, mas uma API intermediária não. A validação pode funcionar, enquanto a busca não encontra o registro. A consulta cadastral pode falhar mesmo que o formulário aparente estar perfeito.

Foi justamente por isso que a Receita Federal alertou não apenas para formulários, mas para armazenamento, validação, processamento, integrações, sistemas fiscais, ERPs e bases de dados.

Como tratamos essa mudança no sistema do Pet Táxi

No Pet Táxi, temos um sistema próprio para apoiar a operação da empresa. Entre outras informações, ele trabalha com cadastros de pessoas jurídicas, consultas cadastrais, clientes, contatos, endereços e dados utilizados na operação.

Quando analisamos o impacto do novo CNPJ, a decisão foi não tratar o problema apenas na interface. Fizemos uma revisão do percurso completo percorrido pelo identificador. Isso levou a uma distinção importante entre apresentação e identidade.

Para uma pessoa, faz sentido visualizar 00.000.000/E08G-12. Para o sistema, a representação canônica utilizada internamente é 00000000E08G12. A diferença é fundamental.

Na normalização, retiramos aquilo que pertence à apresentação, como pontos, barra e hífen, sem destruir letras ou números que pertencem ao próprio identificador.

Trecho 02 · normalização canônica do CNPJ
function normalizarCnpj(string $valor): ?string
{
    $valor = strtoupper(trim($valor));
    if ($valor === '') { return ''; }
    if (preg_match('/^[A-Z0-9]{12}[0-9]{2}$/D', $valor) === 1) {
        return $valor;
    }
    if (preg_match('/^[A-Z0-9]{2}\.[A-Z0-9]{3}\.[A-Z0-9]{3}\/[A-Z0-9]{4}-[0-9]{2}$/D', $valor) !== 1) {
        return null;
    }
    return str_replace(['.', '/', '-'], '', $valor);
}

Essa regra permite que o mesmo mecanismo continue aceitando perfeitamente um CNPJ tradicional, como 11.222.333/0001-81 e passe a aceitar também o formato alfanumérico. A retrocompatibilidade não foi sacrificada.

Nossa implementação central de CNPJ já trabalha com as 12 posições alfanuméricas, mantém os dois verificadores numéricos, converte letras para uma representação canônica em maiúsculas e aplica o cálculo do dígito verificador conforme o novo modelo. A validação realizada no navegador existe como auxílio à experiência do usuário; a decisão definitiva permanece no servidor.

Uma regra importante: uma única verdade sobre o CNPJ

Outro cuidado foi evitar que diferentes partes do sistema criassem interpretações próprias sobre o que constitui um CNPJ válido.

É relativamente fácil acabar com uma função na tela de cadastro, outra no módulo de orçamento, outra no endpoint de consulta e mais uma dentro de alguma integração. O problema aparece quando uma delas evolui e as demais não.

Por isso, no backend, normalização, validação e formatação foram concentradas em uma regra comum. Cadastro, leitura e apresentação trabalham sobre o mesmo conceito de identificador. Essa talvez seja uma das lições mais importantes dessa mudança.

Compatibilidade não é acrescentar letras a uma expressão regular. É impedir que diferentes partes do sistema tenham definições diferentes da mesma informação.

Banco de dados também faz parte da mudança

Outro ponto que merece atenção é a persistência. CNPJ não deve ser armazenado como uma grandeza matemática. Ninguém soma dois CNPJs, calcula média de CNPJs ou multiplica um CNPJ por outro. Ele é um identificador. Consequentemente, sua representação natural em banco de dados é textual.

Na revisão do nosso sistema, verificamos também essa camada. O armazenamento utilizado para o CNPJ já era textual, com capacidade para as 14 posições e controle de unicidade, portanto não foi necessária alteração estrutural no banco.

Isso é relevante porque sistemas que tenham utilizado tipos numéricos para CNPJ precisarão de uma mudança mais profunda do que simplesmente alterar o frontend.

Integrações são onde muitos problemas podem se esconder

Uma das partes mais interessantes da revisão apareceu na comunicação entre componentes.

Mesmo quando um formulário e o backend principal já compreendem CNPJ alfanumérico, uma pequena rotina intermediária pode ainda possuir a antiga lógica de “manter somente números”. Em uma auditoria do fluxo encontramos justamente ocorrências desse padrão em pontos auxiliares da aplicação.

Elas não exigiram reconstruir o sistema. Exigiram corrigir a abstração.

Em vez de remover todo caractere não numérico, o sistema passou a remover apenas aquilo que é formatação quando estiver tratando CNPJ.

Também garantimos que o identificador canônico seja enviado sem alteração para o serviço de consulta cadastral utilizado pela aplicação. A camada de integração, por sua vez, trabalha com o CNPJ como texto e não modifica seu conteúdo.

Trecho 03 · consulta cadastral
$input = isset($_GET['cnpj']) && is_string($_GET['cnpj'])
    ? $_GET['cnpj'] : '';

$cnpjNormalizado = normalizarCnpj($input);
$cnpj = $cnpjNormalizado ?? '';

if ($cnpjNormalizado === null || strlen($cnpj) !== 14 ||
    !cnpjValido($cnpj)) {
    $reply(400, ['erro' => 'CNPJ inválido.']);
}

$raw = (new BrasilApiCnpjService())->consultar($cnpj);

Esse detalhe resume boa parte do desafio da migração: uma única linha de código baseada na premissa antiga pode comprometer um fluxo inteiro.

Pesquisa também precisa conhecer letras

Outra consequência pouco comentada está nas pesquisas internas. Não basta conseguir cadastrar 00.000.000/E08G-12. O usuário pode posteriormente procurar por 00.000.000/E08G-12 por 00000000E08G12 ou até por um fragmento como E08G.

Uma pesquisa construída exclusivamente a partir dos dígitos também falharia nesse cenário.

Nossa busca de pessoas jurídicas trabalha com uma normalização específica para CNPJ, preservando os caracteres alfanuméricos. Isso permite tratar máscara e representação canônica sem transformar o identificador em um número.

Trecho 04 · pesquisa por CNPJ
$valor = preg_replace('/[.\/\-\s]+/', '', strtoupper(trim($valor))) ?? '';
return preg_match('/^[A-Z0-9]+$/D', $valor) === 1 ? $valor : '';
$termoCnpj = normalizarPesquisaCnpj($termo);
$cnpjLike = '%' . $termoCnpj . '%';
OR (
    :tem_cnpj = 1
    AND pj.cnpj LIKE :termo_cnpj
)
':tem_cnpj' => $termoCnpj !== '' ? 1 : 0,
':termo_cnpj' => $cnpjLike,

Testar com um CNPJ real muda tudo

Durante a fase de preparação, desenvolvedores precisavam trabalhar com exemplos e números simulados. Desde 31 de julho de 2026 existe um excelente caso de regressão: 0.000.000/E08G-12

Ele é especialmente útil porque contém letras e possui dígitos verificadores reais. No nosso processo de validação, esse identificador passou por normalização, validação, formatação, frontend, backend, integração e apresentação.

O resultado esperado ficou bem definido, entrada formatada, 00.000.000/E08G-12, representação canônica, 00000000E08G12, validação, válido; apresentação novamente, 00.000.000/E08G-12. Também mantivemos casos de teste com CNPJ exclusivamente numérico para garantir que solucionar 2026 não significasse quebrar tudo o que veio antes.

Trecho 05 · testes de regressão do novo formato
cnpj_test(
    normalizarCnpj('00.000.000/E08G-12') === '00000000E08G12',
    'Máscara alfanumérica não normalizada.'
);

cnpj_test(
    cnpjValido('00.000.000/E08G-12'),
    'Exemplo oficial rejeitado.'
);

cnpj_test(
    !cnpjValido('00.000.000/E08G-A2'),
    'Letra no primeiro verificador aceita.'
);

cnpj_test(
    formatarCnpj('00000000E08G12') === '00.000.000/E08G-12',
    'Formatação alfanumérica incorreta.'
);

A implementação foi ainda submetida a verificações de sintaxe e testes de regressão específicos para o novo formato. A auditoria final não encontrou tratamentos exclusivamente numéricos ainda aplicados diretamente ao CNPJ nos fluxos revisados.

Tecnologia bem feita muitas vezes é aquela que o cliente nem percebe

Para quem utiliza o Pet Táxi como cliente, nada disso deveria ser perceptível. Essa é justamente a intenção.

Se uma nova empresa possuir um CNPJ alfanumérico, o sistema deve simplesmente aceitá-lo. A consulta deve funcionar. O cadastro deve ser salvo. A pesquisa deve encontrá-lo. O orçamento deve apresentá-lo corretamente. Sem procedimentos especiais. Sem cadastro paralelo. Sem alguém precisar explicar ao sistema que aquele CNPJ “tem letras”.

Há bastante engenharia por trás de uma experiência que, para o usuário, deveria parecer absolutamente normal.

O CNPJ alfanumérico deixa uma lição maior

A mudança do CNPJ é um bom exemplo de como sistemas carregam pressupostos durante anos. Enquanto esses pressupostos continuam verdadeiros, raramente são percebidos.

Durante décadas, “CNPJ contém somente números” era uma premissa aparentemente segura. Desde 31 de julho de 2026, deixou de ser. O formato visual quase não mudou. O significado técnico mudou bastante.  E talvez a principal conclusão seja esta: CNPJ nunca foi realmente um número. Sempre foi um identificador que, por coincidência histórica, utilizava somente algarismos.

Agora essa diferença ficou impossível de ignorar.

No Pet Táxi, aproveitamos a mudança não apenas para tornar um campo compatível com letras, mas para revisar o ciclo completo dessa informação no sistema: entrada, normalização, validação, persistência, integração, pesquisa, apresentação e testes.

É o tipo de trabalho que normalmente permanece invisível.

E é exatamente assim que deveria ser. Quando a tecnologia está preparada antes de se tornar um problema operacional, o cliente não precisa conhecer a complexidade que existe por trás dela.

Referências

Temas: CNPJ alfanumérico · engenharia de software · sistemas sob medida · integração · testes

Tem um sistema que precisa evoluir sem quebrar o que já funciona?

Antes de alterar código, vale entender quais premissas antigas ainda atravessam a operação.