Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions packages/cnpj-dv/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# lacus/cnpj-dv

## 1.0.0

### 🚀 Stable Version Released!

Utility class to calculate check digits on CNPJ (Cadastro Nacional da Pessoa Jurídica). Main features:

- **Flexible input**: Accepts string or array of strings (formatted or raw).
- **Format agnostic**: Automatically strips non-numeric characters from input.
- **Lazy evaluation & caching**: Check digits are calculated only when accessed for the first time.
- **Minimal dependencies**: [`lacus/utils`](https://packagist.org/packages/lacus/utils) only.
- **Error handling**: Specific types for type, length, and invalid input scenarios (`TypeError` / `Exception` hierarchy).

For detailed usage and API reference, see the [README](./README.md).
9 changes: 9 additions & 0 deletions packages/cnpj-dv/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
MIT License

Copyright (c) 2026 Julio L. Muller

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
171 changes: 171 additions & 0 deletions packages/cnpj-dv/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
![cnpj-dv for PHP](https://br-utils.vercel.app/img/cover_cnpj-dv.jpg)

[![Packagist Version](https://img.shields.io/packagist/v/lacus/cnpj-dv)](https://packagist.org/packages/lacus/cnpj-dv)
[![Packagist Downloads](https://img.shields.io/packagist/dm/lacus/cnpj-dv)](https://packagist.org/packages/lacus/cnpj-dv)
[![PHP Version](https://img.shields.io/packagist/php-v/lacus/cnpj-dv)](https://www.php.net/)
[![Test Status](https://img.shields.io/github/actions/workflow/status/LacusSolutions/br-utils-php/ci.yml?label=ci/cd)](https://github.com/LacusSolutions/br-utils-php/actions)
[![Last Update Date](https://img.shields.io/github/last-commit/LacusSolutions/br-utils-php)](https://github.com/LacusSolutions/br-utils-php)
[![Project License](https://img.shields.io/github/license/LacusSolutions/br-utils-php)](https://github.com/LacusSolutions/br-utils-php/blob/main/LICENSE)

> 🚀 **Full support for the [new alphanumeric CNPJ format](https://github.com/user-attachments/files/23937961/calculodvcnpjalfanaumerico.pdf).**

> 🌎 [Acessar documentação em português](https://github.com/LacusSolutions/br-utils-php/blob/main/packages/cnpj-dv/README.pt.md)

A PHP utility to calculate check digits on CNPJ (Brazilian Business Tax ID).

## PHP Support

| ![PHP 8.2](https://img.shields.io/badge/PHP-8.2-777BB4?logo=php&logoColor=white) | ![PHP 8.3](https://img.shields.io/badge/PHP-8.3-777BB4?logo=php&logoColor=white) | ![PHP 8.4](https://img.shields.io/badge/PHP-8.4-777BB4?logo=php&logoColor=white) | ![PHP 8.5](https://img.shields.io/badge/PHP-8.5-777BB4?logo=php&logoColor=white) |
| --- | --- | --- | --- |
| Passing ✔ | Passing ✔ | Passing ✔ | Passing ✔ |

## Features

- ✅ **Alphanumeric CNPJ**: Full support for the new alphanumeric CNPJ format (introduced in 2026)
- ✅ **Flexible input**: Accepts `string` or `array` of strings
- ✅ **Format agnostic**: Strips non-alphanumeric characters from string input and uppercases letters
- ✅ **Auto-expansion**: Multi-character strings in arrays are joined and parsed like a single string
- ✅ **Input validation**: Rejects ineligible CNPJs (all-zero base ID `00000000`, all-zero branch `0000`, or 12 numeric-only repeated digits)
- ✅ **Lazy evaluation**: Check digits are calculated only when accessed (via properties)
- ✅ **Caching**: Calculated values are cached for subsequent access
- ✅ **Property-style API**: `first`, `second`, `both`, `cnpj` (via magic `__get`)
- ✅ **Minimal dependencies**: Only [`lacus/utils`](https://packagist.org/packages/lacus/utils)
- ✅ **Error handling**: Specific types for type, length, and invalid CNPJ scenarios (`TypeError` vs `Exception` semantics)

## Installation

```bash
# using Composer
$ composer require lacus/cnpj-dv
```

## Quick Start

```php
<?php

use Lacus\BrUtils\Cnpj\CnpjCheckDigits;

$checkDigits = new CnpjCheckDigits('914157320007');

$checkDigits->first; // '9'
$checkDigits->second; // '3'
$checkDigits->both; // '93'
$checkDigits->cnpj; // '91415732000793'
```

With alphanumeric CNPJ (new format):

```php
<?php

use Lacus\BrUtils\Cnpj\CnpjCheckDigits;

$checkDigits = new CnpjCheckDigits('MGKGMJ9X0001');

$checkDigits->first; // '6'
$checkDigits->second; // '8'
$checkDigits->both; // '68'
$checkDigits->cnpj; // 'MGKGMJ9X000168'
```

## Usage

The main resource of this package is the class `CnpjCheckDigits`. Through an instance, you access CNPJ check-digit information:

- **`__construct`**: `new CnpjCheckDigits(string|array $cnpjInput)` — 12–14 alphanumeric characters after sanitization (formatting stripped from strings; letters uppercased). Only the **first 12** characters are used as the base; if you pass 13 or 14 characters (e.g. a full CNPJ including prior check digits), characters 13–14 are **ignored** and the digits are recalculated.
- **`first`**: First check digit (13th character of the full CNPJ). Lazy, cached.
- **`second`**: Second check digit (14th character of the full CNPJ). Lazy, cached.
- **`both`**: Both check digits concatenated as a string.
- **`cnpj`**: The complete CNPJ as a string of 14 characters (12 base characters + 2 check digits).

### Input formats

The `CnpjCheckDigits` class accepts multiple input formats:

**String input:** raw digits and/or letters, or formatted CNPJ (e.g. `91.415.732/0007-93`, `MG.KGM.J9X/0001-68`). Non-alphanumeric characters are removed; lowercase letters are uppercased.

**Array of strings:** each element must be a string; values are concatenated and then parsed like a single string (e.g. `['9','1','4',…]`, `['9141','5732','0007']`, `['MG','KGM','J9X','0001']`). Non-string elements are not allowed.

### Errors & exceptions handling

This package uses **TypeError vs Exception** semantics: *type errors* indicate incorrect API use (e.g. wrong type); *exceptions* indicate invalid or ineligible data (e.g. invalid length or business rules). You can catch specific classes or use the abstract bases.

- **CnpjCheckDigitsTypeError** (_abstract_) — base for type errors; extends PHP’s `TypeError`
- **CnpjCheckDigitsInputTypeError** — input is not `string` or `array` of strings (or array contains a non-string element)
- **CnpjCheckDigitsException** (_abstract_) — base for data/flow exceptions; extends `Exception`
- **CnpjCheckDigitsInputLengthException** — sanitized length is not 12–14
- **CnpjCheckDigitsInputInvalidException** — base ID `00000000`, branch ID `0000`, or 12 identical numeric digits (repeated-digit pattern)

```php
<?php

use Lacus\BrUtils\Cnpj\CnpjCheckDigits;
use Lacus\BrUtils\Cnpj\Exceptions\CnpjCheckDigitsException;
use Lacus\BrUtils\Cnpj\Exceptions\CnpjCheckDigitsInputInvalidException;
use Lacus\BrUtils\Cnpj\Exceptions\CnpjCheckDigitsInputLengthException;
use Lacus\BrUtils\Cnpj\Exceptions\CnpjCheckDigitsInputTypeError;

// Input type (e.g. integer not allowed)
try {
new CnpjCheckDigits(12345678000100);
} catch (CnpjCheckDigitsInputTypeError $e) {
echo $e->getMessage();
}

// Length (must be 12–14 alphanumeric characters after sanitization)
try {
new CnpjCheckDigits('12345678901');
} catch (CnpjCheckDigitsInputLengthException $e) {
echo $e->getMessage();
}

// Invalid (e.g. all-zero base or branch, or repeated numeric digits)
try {
new CnpjCheckDigits('000000000001');
} catch (CnpjCheckDigitsInputInvalidException $e) {
echo $e->getMessage();
}

// Any data exception from the package
try {
// risky code
} catch (CnpjCheckDigitsException $e) {
// handle
}
```

### Other available resources

- **`CNPJ_MIN_LENGTH`**: `12` — class constant `CnpjCheckDigits::CNPJ_MIN_LENGTH`, and global `Lacus\BrUtils\Cnpj\CNPJ_MIN_LENGTH` when the autoloaded `cnpj-dv.php` file is loaded.
- **`CNPJ_MAX_LENGTH`**: `14` — class constant `CnpjCheckDigits::CNPJ_MAX_LENGTH`, and global `Lacus\BrUtils\Cnpj\CNPJ_MAX_LENGTH` when `cnpj-dv.php` is loaded.

## Calculation algorithm

The package computes check digits with the official Brazilian modulo-11 rules extended to alphanumeric characters:

1. **Character value:** each character contributes `ord(character) − 48` (so `0`–`9` stay 0–9; letters use their ASCII offset from `0`).
2. **Weights:** from **right to left**, multiply by weights that cycle **2, 3, 4, 5, 6, 7, 8, 9**, then repeat from 2.
3. **First check digit (13th position):** apply steps 1–2 to the first **12** base characters; let `r = sum % 11`. The digit is `0` if `r < 2`, otherwise `11 − r`.
4. **Second check digit (14th position):** apply steps 1–2 to the first 12 characters **plus** the first check digit; same formula for `r`.

## Contribution & Support

We welcome contributions! Please see our [Contributing Guidelines](https://github.com/LacusSolutions/br-utils-php/blob/main/CONTRIBUTING.md) for details. If you find this project helpful, please consider:

- ⭐ Starring the repository
- 🤝 Contributing to the codebase
- 💡 [Suggesting new features](https://github.com/LacusSolutions/br-utils-php/issues)
- 🐛 [Reporting bugs](https://github.com/LacusSolutions/br-utils-php/issues)

## License

This project is licensed under the MIT License — see the [LICENSE](https://github.com/LacusSolutions/br-utils-php/blob/main/LICENSE) file for details.

## Changelog

See [CHANGELOG](https://github.com/LacusSolutions/br-utils-php/blob/main/packages/cnpj-dv/CHANGELOG.md) for a list of changes and version history.

---

Made with ❤️ by [Lacus Solutions](https://github.com/LacusSolutions)
143 changes: 143 additions & 0 deletions packages/cnpj-dv/README.pt.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
![cnpj-dv para PHP](https://br-utils.vercel.app/img/cover_cnpj-dv.jpg)

> 🚀 **Suporte total ao [novo formato alfanumérico de CNPJ](https://github.com/user-attachments/files/23937961/calculodvcnpjalfanaumerico.pdf).**

> 🌎 [Access documentation in English](https://github.com/LacusSolutions/br-utils-php/blob/main/packages/cnpj-dv/README.md)

Utilitário em PHP para calcular os dígitos verificadores de CNPJ (Cadastro Nacional da Pessoa Jurídica).

## Recursos

- ✅ **CNPJ alfanumérico**: Suporte completo ao novo formato alfanumérico de CNPJ (a partir de 2026)
- ✅ **Entrada flexível**: Aceita `string` ou `array` de strings
- ✅ **Agnóstico ao formato**: Remove caracteres não alfanuméricos da entrada em string e converte letras para maiúsculas
- ✅ **Junção em array**: Strings com vários caracteres em arrays são concatenadas e interpretadas como uma única sequência
- ✅ **Validação de entrada**: Rejeita CNPJs inelegíveis (base toda zero `00000000`, filial `0000`, ou 12 dígitos numéricos repetidos)
- ✅ **Avaliação lazy**: Dígitos verificadores são calculados apenas quando acessados (via propriedades)
- ✅ **Cache**: Valores calculados são armazenados em cache para acessos subsequentes
- ✅ **API estilo propriedades**: `first`, `second`, `both`, `cnpj` (via `__get` mágico)
- ✅ **Dependências mínimas**: Apenas [`lacus/utils`](https://packagist.org/packages/lacus/utils)
- ✅ **Tratamento de erros**: Tipos específicos para tipo, tamanho e CNPJ inválido (semântica `TypeError` vs `Exception`)

## Instalação

```bash
# usando Composer
$ composer require lacus/cnpj-dv
```

## Início rápido

```php
<?php

use Lacus\BrUtils\Cnpj\CnpjCheckDigits;

$checkDigits = new CnpjCheckDigits('914157320007');

$checkDigits->first; // '9'
$checkDigits->second; // '3'
$checkDigits->both; // '93'
$checkDigits->cnpj; // '91415732000793'
```

## Utilização

O principal recurso deste pacote é a classe `CnpjCheckDigits`. Por meio da instância, você acessa as informações dos dígitos verificadores do CNPJ:

- **`__construct`**: `new CnpjCheckDigits(string|array $cnpjInput)` — 12–14 caracteres alfanuméricos após a sanitização (formatação removida em strings; letras em maiúsculas). Apenas os **primeiros 12** caracteres entram como base; com 13 ou 14 caracteres (ex.: CNPJ completo com DV anteriores), os caracteres 13 e 14 são **ignorados** e os dígitos são recalculados.
- **`first`**: Primeiro dígito verificador (13º caractere do CNPJ completo). Lazy, em cache.
- **`second`**: Segundo dígito verificador (14º caractere do CNPJ completo). Lazy, em cache.
- **`both`**: Ambos os dígitos verificadores concatenados em uma string.
- **`cnpj`**: O CNPJ completo como string de 14 caracteres (12 da base + 2 dígitos verificadores).

### Formatos de entrada

A classe `CnpjCheckDigits` aceita múltiplos formatos de entrada:

**String:** dígitos e/ou letras crus, ou CNPJ formatado (ex.: `91.415.732/0007-93`, `MG.KGM.J9X/0001-68`). Caracteres não alfanuméricos são removidos; letras minúsculas viram maiúsculas.

**Array de strings:** cada elemento deve ser string; os valores são concatenados e interpretados como uma única string (ex.: `['9','1','4',…]`, `['9141','5732','0007']`, `['MG','KGM','J9X','0001']`). Elementos que não são string não são permitidos.

### Erros e exceções

Este pacote usa a distinção **TypeError vs Exception**: *erros de tipo* indicam uso incorreto da API (ex.: tipo errado); *exceções* indicam dados inválidos ou inelegíveis (ex.: tamanho ou regras de negócio). Você pode capturar classes específicas ou as bases abstratas.

- **CnpjCheckDigitsTypeError** (_abstract_) — base para erros de tipo; estende o `TypeError` do PHP
- **CnpjCheckDigitsInputTypeError** — entrada não é `string` nem `array` de strings (ou o array contém elemento que não é string)
- **CnpjCheckDigitsException** (_abstract_) — base para exceções de dados/fluxo; estende `Exception`
- **CnpjCheckDigitsInputLengthException** — tamanho após sanitização não é 12–14
- **CnpjCheckDigitsInputInvalidException** — base `00000000`, filial `0000`, ou 12 dígitos numéricos idênticos (padrão de repetição)

```php
<?php

use Lacus\BrUtils\Cnpj\CnpjCheckDigits;
use Lacus\BrUtils\Cnpj\Exceptions\CnpjCheckDigitsException;
use Lacus\BrUtils\Cnpj\Exceptions\CnpjCheckDigitsInputInvalidException;
use Lacus\BrUtils\Cnpj\Exceptions\CnpjCheckDigitsInputLengthException;
use Lacus\BrUtils\Cnpj\Exceptions\CnpjCheckDigitsInputTypeError;

// Tipo de entrada (ex.: inteiro não permitido)
try {
new CnpjCheckDigits(12345);
} catch (CnpjCheckDigitsInputTypeError $e) {
echo $e->getMessage();
}

// Tamanho (deve ser 12–14 caracteres alfanuméricos após sanitização)
try {
new CnpjCheckDigits('12345678901');
} catch (CnpjCheckDigitsInputLengthException $e) {
echo $e->getMessage();
}

// Inválido (ex.: base ou filial zeradas, ou dígitos numéricos repetidos)
try {
new CnpjCheckDigits('000000000001');
} catch (CnpjCheckDigitsInputInvalidException $e) {
echo $e->getMessage();
}

// Qualquer exceção de dados do pacote
try {
// código arriscado
} catch (CnpjCheckDigitsException $e) {
// tratar
}
```

### Outros recursos disponíveis

- **`CNPJ_MIN_LENGTH`**: `12` — constante de classe `CnpjCheckDigits::CNPJ_MIN_LENGTH`, e constante global `Lacus\BrUtils\Cnpj\CNPJ_MIN_LENGTH` quando `cnpj-dv.php` é carregado pelo autoload do Composer.
- **`CNPJ_MAX_LENGTH`**: `14` — constante de classe `CnpjCheckDigits::CNPJ_MAX_LENGTH`, e constante global `Lacus\BrUtils\Cnpj\CNPJ_MAX_LENGTH` quando `cnpj-dv.php` é carregado pelo autoload do Composer.

## Algoritmo de cálculo

O pacote calcula os dígitos verificadores com as regras oficiais brasileiras de módulo 11 estendidas a caracteres alfanuméricos:

1. **Valor do caractere:** cada caractere contribui com `ord(caractere) − 48` (assim `0`–`9` permanecem 0–9; letras usam o deslocamento ASCII em relação a `0`).
2. **Pesos:** da **direita para a esquerda**, multiplicar pelos pesos que ciclam **2, 3, 4, 5, 6, 7, 8, 9** e voltam a 2.
3. **Primeiro dígito verificador (13ª posição):** aplicar os itens 1–2 aos **primeiros 12** caracteres da base; seja `r = soma % 11`. O dígito é `0` se `r < 2`, senão `11 − r`.
4. **Segundo dígito verificador (14ª posição):** aplicar os itens 1–2 aos 12 primeiros caracteres **mais** o primeiro dígito verificador; mesma fórmula para `r`.

## Contribuição e suporte

Contribuições são bem-vindas! Consulte as [Diretrizes de contribuição](https://github.com/LacusSolutions/br-utils-php/blob/main/CONTRIBUTING.md). Se o projeto for útil para você, considere:

- ⭐ Dar uma estrela no repositório
- 🤝 Contribuir com código
- 💡 [Sugerir novas funcionalidades](https://github.com/LacusSolutions/br-utils-php/issues)
- 🐛 [Reportar bugs](https://github.com/LacusSolutions/br-utils-php/issues)

## Licença

Este projeto está sob a licença MIT — veja o arquivo [LICENSE](https://github.com/LacusSolutions/br-utils-php/blob/main/LICENSE).

## Changelog

Veja o [CHANGELOG](https://github.com/LacusSolutions/br-utils-php/blob/main/packages/cnpj-dv/CHANGELOG.md) para alterações e histórico de versões.

---

Feito com ❤️ por [Lacus Solutions](https://github.com/LacusSolutions)
Loading
Loading