DEV Community

Cover image for CNPJ Alfanumérico: Implemente a validação do novo CNPJ em seu projeto
Valdeir S.
Valdeir S.

Posted on

CNPJ Alfanumérico: Implemente a validação do novo CNPJ em seu projeto

Em razão do aumento contínuo do número de empresas e do iminente esgotamento dos CNPJs disponíveis, a Receita Federal do Brasil institui o CNPJ Alfanumérico. A iniciativa tem por objetivo facilitar a identificação de todas as empresas e aprimorar o ambiente de negócios, contribuindo para o desenvolvimento econômico e social do Brasil.

O CNPJ Alfanumérico será atribuído, a partir de Julho de 2026, exclusivamente a novas inscrições.


Formato

O novo formato de CNPJ seguirá com o padrão de 14 caracteres divididos da seguinte forma:

Imagem digital horizontal em estilo de slide com fundo azul escuro, intitulada 'ESTRUTURA DO CNPJ'. Ao centro, o formato do cadastro é decomposto visualmente em três blocos conectados por chaves e setas explicativas. O primeiro bloco exibe 'XX.XXX.XXX', identificado como 'RAIZ' e descrito como valor alfanumérico. O segundo bloco exibe 'YYYY', identificado como 'ORDEM' e também descrito como valor alfanumérico. O terceiro e último bloco exibe 'ZZ', identificado como 'DÍGITO VERIFICADOR', descrito como valor numérico composto por inteiros positivos.

Cálculo do Dígito Verificador (DV)

Para o cálculo do DV, os valores decimais, contidos na Tabela Código ASCII (Veja abaixo os códigos), serão substituídos pelos valores decimais relativos às letras maiúsculas e atribuídos aos valores numéricos — para cada um deles, subtraído o valor 48 — e alfanuméricos do novo CNPJ.

Transformação da Raiz e da Ordem

  1. CNPJ padrão 12.ABC.345/01de
  2. Substitui as letras minúsculas para maiúsculas: 12.ABC.345/01DE
  3. Substitui cada letra por seu código ASCII e subtrai por 48: 12.(65–48)(66–48)(67–48).345/01(68–48)(69–48)
  4. Resultado após substituição e subtração: 12.171819.345/012021

Cálculo do 1º Dígito Verificador

Atribuição de Pesos

Os valores obtidos após os passos anteriores serão multiplicados por pesos, atribuídos da direita para esquerda, do valor 2 até o valor 9. A partir do 8º caractere será reiniciada a atribuição dos pesos pelo valor 2.

  1. CNPJ após transformação: 1 2 . 17 18 19 . 3 4 5 / 0 1 20 21
  2. Atribuição dos pesos e cálculo do somatório:
(1*5)+(2*4)+(17*3)+(18*2)+(19*9)+(3*8)+(4*7)+(5*6)+(0*5)+(1*4)+(20*3)+(21*2)
∑ = 459
Enter fullscreen mode Exit fullscreen mode

Cálculo do 1º dígito verificador

Após encontrar o somatório do passo anterior, é necessário encontrar o resto da divisão do valor por 11. Posteriormente, deverá subtrair 11 pelo valor encontrado.

X = 11 - MOD(459/11)
X = 11 - 8
X = 3
Enter fullscreen mode Exit fullscreen mode

Portanto, o 1º dígito verificador do CNPJ é igual a 3. Agora o CNPJ deverá estar no seguinte formato: “12.ABC.345/01DE-3"

Cálculo do 2º dígito verificador

Para encontrar o 2º DV, basta repetir o processo acima:

A imagem) que explica, passo a passo, o cálculo aplicado a um CNPJ com caracteres alfanuméricos. Na parte superior, o CNPJ original é apresentado com 13 posições numeradas, contendo dígitos e letras. Em seguida, o infográfico mostra o “CNPJ Transformado”, onde as letras são convertidas em valores numéricos correspondentes (valores ASCII). Logo abaixo, aparece a linha de “Pesos”, indicando o peso associado a cada posição do CNPJ. Na sequência, cada valor transformado é multiplicado pelo respectivo peso, gerando resultados individuais. Na parte inferior, esses resultados são somados, e o somatório final é destacado visualmente, indicando o valor total igual a 424. O uso de linhas e símbolos reforçam a correspondência entre posições, valores transformados, pesos e resultados.<br>

Após encontrar o somatório do passo anterior, é necessário encontrar o resto da divisão do valor por 11. Posteriormente, deverá subtrair 11 pelo valor encontrado.

X = 11 - MOD(424/11)
X = 11 - 6
X = 5
Enter fullscreen mode Exit fullscreen mode

Portanto, o 2º dígito verificador do CNPJ é igual a 5. Agora o CNPJ deverá estar no seguinte formato: “12.ABC.345/01DE-3*5*


Implementação em Códigos

JavaScript

class CNPJ {
  static #regexCNPJSemDV = /^([A-Z\d]){14}$/;
  static #regexRemoveMascara = /[^A-Z\d]/g;
  static #tamanhoCNPJSemDV = 12;
  static #pesosDV = [6, 5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2];
  static #valorBase = 48;

  static valido(cnpj) { 
    let cnpjSemMascara = cnpj.toUpperCase().replace(this.#regexRemoveMascara, '')

    if (this.#regexCNPJSemDV.test(cnpjSemMascara)) { 
      let somatorioDV1 = 0; 
      let somatorioDV2 = 0; 
      for (let i = 0; i < this.#tamanhoCNPJSemDV; i++) { 
          const asciiDigito = cnpjSemMascara.charCodeAt(i) - this.#valorBase;
          somatorioDV1 += asciiDigito * this.#pesosDV[i + 1]; 
          somatorioDV2 += asciiDigito * this.#pesosDV[i]; 
      } 
      const dv1 = somatorioDV1 % 11 < 2 ? 0 : 11 - (somatorioDV1 % 11); 
      somatorioDV2 += dv1 * this.#pesosDV[this.#tamanhoCNPJSemDV]; 
      const dv2 = somatorioDV2 % 11 < 2 ? 0 : 11 - (somatorioDV2 % 11); 
      const dv = `${dv1}${dv2}`;
      return cnpjSemMascara.slice(-2) === dv
    }

    return false;
  }
}

CNPJ.valido('12.ABC.345/01de-35') // Output: True
CNPJ.valido('12.ABC.345/01DE-35') // Output: True
CNPJ.valido('12.ABC.345/01DE-00') // Output: False
Enter fullscreen mode Exit fullscreen mode

TypeScript

class CNPJ {
    private static readonly regexCNPJSemDV = /^([A-Z\d]){14}$/;
    private static readonly regexRemoveMascara = /[^A-Z\d]/g;
    private static readonly tamanhoCNPJSemDV = 12;
    private static readonly pesosDV = [6, 5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2];
    private static readonly valorBase = 48;

    public static valido(cnpj: string): bool { 
        let cnpjSemMascara = cnpj.toUpperCase().replace(this.regexRemoveMascara, '')

        if (this.regexCNPJSemDV.test(cnpjSemMascara)) { 
            let somatorioDV1 = 0; 
            let somatorioDV2 = 0; 
            for (let i = 0; i < this.tamanhoCNPJSemDV; i++) { 
                const asciiDigito = cnpjSemMascara.charCodeAt(i) - this.valorBase;
                somatorioDV1 += asciiDigito * this.pesosDV[i + 1]; 
                somatorioDV2 += asciiDigito * this.pesosDV[i]; 
            } 
            const dv1 = somatorioDV1 % 11 < 2 ? 0 : 11 - (somatorioDV1 % 11); 
            somatorioDV2 += dv1 * this.pesosDV[this.tamanhoCNPJSemDV]; 
            const dv2 = somatorioDV2 % 11 < 2 ? 0 : 11 - (somatorioDV2 % 11); 
            const dv = `${dv1}${dv2}`;
            return cnpjSemMascara.slice(-2) === dv;
        }

        return false;
    }
}

CNPJ.valido('12.ABC.345/01de-35') // Output: True
CNPJ.valido('12.ABC.345/01DE-35') // Output: True
CNPJ.valido('12.ABC.345/01DE-00') // Output: False
Enter fullscreen mode Exit fullscreen mode

PHP

<?php
class CNPJ {
    private const REGEX_CNPJ_SEM_DV = '/^([A-Z\d]){14}$/';
    private const REGEX_REMOVE_MASCARA = '/[^A-Z\d]/';
    private const TAMANHO_CNPJ_SEM_DV = 12;
    private const PESOS_DV = [6, 5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2];
    private const VALOR_BASE = 48;

    public static function valido(string $cnpj): bool { 
        $cnpjSemMascara = strtoupper(preg_replace(self::REGEX_REMOVE_MASCARA, '', $cnpj));

        if (preg_match(self::REGEX_CNPJ_SEM_DV, $cnpjSemMascara)) { 
            $somatorioDV1 = 0; 
            $somatorioDV2 = 0; 

            for ($i = 0; $i < self::TAMANHO_CNPJ_SEM_DV; $i++) { 
                $asciiDigito = ord($cnpjSemMascara[$i]) - self::VALOR_BASE;
                $somatorioDV1 += $asciiDigito * self::PESOS_DV[$i + 1]; 
                $somatorioDV2 += $asciiDigito * self::PESOS_DV[$i]; 
            } 

            $dv1 = $somatorioDV1 % 11 < 2 ? 0 : 11 - ($somatorioDV1 % 11); 
            $somatorioDV2 += $dv1 * self::PESOS_DV[self::TAMANHO_CNPJ_SEM_DV]; 
            $dv2 = $somatorioDV2 % 11 < 2 ? 0 : 11 - ($somatorioDV2 % 11); 
            $dv = $dv1 . $dv2;

            return substr($cnpjSemMascara, -2) === $dv;
        }

        return false;
    }
}

// Testes
assert(CNPJ::valido('12.ABC.345/01de-35')); // Output: True
assert(CNPJ::valido('12.ABC.345/01DE-35')); // Output: True
assert(CNPJ::valido('12.ABC.345/01DE-00')); // Fatal error: Uncaught AssertionError
Enter fullscreen mode Exit fullscreen mode

Tabela ASCII

A imagme mostra uma tabela intitulada “Códigos ASCII de A a Z”. A tabela está organizada em duas colunas principais para facilitar a leitura.


Conclusão

É importante atualizar seu código para que a aplicação quebre a partir de julho/2026.

Ficou com alguma dúvida ou tem uma sugestão? Deixe nos comentários, que darei uma olhada.

Top comments (0)