Appearance
Estrutura
O sistema utiliza a API do CNPJÁ para consultar e obter dados de empresas em tempo real a partir de um número de CNPJ. Essa integração é fundamental para agilizar o cadastro de novos clientes, preenchendo automaticamente informações como razão social e endereço.
Visão Geral
A integração foi projetada para automatizar o preenchimento de dados em diversos cenários:
- Página de Inscrição (Landing Page): Quando um novo cliente digita o CNPJ, o sistema busca os dados na API e preenche o formulário de cadastro.
- Criação de Endereço a partir do CNPJ: Action dedicada (
CreateAddressFromCnpj) que busca e cria um endereço completo a partir do CNPJ. - Enriquecimento de Dados: Qualquer parte do sistema pode utilizar a integração para obter dados atualizados de empresas.
Componentes Principais
A funcionalidade é centralizada em um serviço que abstrai a comunicação com a API, sendo consumido por outros componentes da aplicação.
Cnpja
Este é o serviço principal responsável por toda a comunicação com a API do CNPJÁ.
- Localização:
app/Integrations/Cnpja/Cnpja.php
Responsabilidades:
- Autenticação: Envia o token de autorização no cabeçalho de cada requisição.
- Consulta: Monta e executa a requisição para o endpoint
office/{cnpj}da API, incluindo o parâmetroregistrations=BRpara obter as inscrições estaduais. - Cache: Armazena as respostas da API em cache por uma hora (
ONE_HOUR = 3600 segundos) para evitar consultas repetidas e economizar créditos. A chave do cache é padronizada comocnpj_response_{cnpj}. - Controle de Rate Limit: Utiliza o
RateLimiterdo Laravel para garantir que o sistema não exceda o limite de requisições por minuto definido no arquivo de configuração (services.cnpja.attempts). - Tratamento de Dados: Normaliza a resposta da API em um array padronizado, incluindo:
- CNPJ
- Inscrição Estadual (filtrada pelo estado do endereço principal)
- Razão Social
- Telefone (concatenação de área + número)
- Endereço completo (rua, número, complemento, bairro, cidade, estado, CEP)
- Logging: Todas as requisições e respostas são logadas para facilitar a depuração.
- Tratamento de Erros: Retorna
nullse o CNPJ for inválido ou se a API retornar erro.
php
// app/Integrations/Cnpja/Cnpja.php
public function fetchCnpjData(string $cnpj): ?array
{
$cnpj = format($cnpj)->onlyNumbers();
return Cache::remember("cnpj_response_{$cnpj}", self::ONE_HOUR, function () use ($cnpj) {
$key = 'rate_limit:cnpj_api';
while ($this->limiter->tooManyAttempts($key, config('services.cnpja.attempts'))) {
sleep(config('services.cnpja.attempts'));
}
$this->limiter->hit($key, self::ONE_MINUTE);
$response = Http::withHeaders([
'Authorization' => $this->token,
])->get(config('services.cnpja.url') . "office/{$cnpj}?registrations=BR");
// ... Tratamento da resposta e normalização ...
return [
'cnpj' => $data['taxId'] ?? null,
'state_registration' => $stateRegistration ?? null,
'legal_name' => $data['company']['name'] ?? null,
'phone' => $phone,
'address' => [
'street' => $data['address']['street'] ?? null,
'number' => $data['address']['number'] ?? null,
'complement' => $data['address']['details'] ?? null,
'neighborhood' => $data['address']['district'] ?? null,
'city' => $data['address']['city'] ?? null,
'state' => $data['address']['state'] ?? null,
'zip' => $data['address']['zip'] ?? null,
],
];
});
}LandingPage (Livewire Component)
Este componente de front-end utiliza o serviço Cnpja para proporcionar uma experiência de usuário fluida na página de inscrição.
- Localização:
app/Livewire/LandingPage.php
Funcionamento:
- O usuário digita o CNPJ no campo
client.cnpj. - O evento
afterStateUpdatedé disparado noonBlurdo campo, que por sua vez emite um evento Livewire chamadofillDataFromCnpj. - Um indicador de carregamento (
components.loading-cnpj) é exibido na tela. - O método
fillDataFromCnpjé executado:- Primeiro, ele verifica se o CNPJ já pertence a um cliente existente no banco de dados local.
- Se não existir, ele invoca o
CnpjConsultServicepara buscar os dados na API. - Com os dados em mãos, ele preenche automaticamente os campos do formulário, como Razão Social, Inscrição Estadual e Endereço.
- Caso a API retorne um erro ou o CNPJ seja inválido, uma mensagem de erro é exibida para o usuário.
php
// app/Livewire/LandingPage.php
#[\Livewire\Attributes\On('fillDataFromCnpj')]
public function fillDataFromCnpj(string $onlyDigits): void
{
// ...
$client = Client::where('cnpj', $onlyDigits)->first();
if ($client) {
// Preenche com dados locais
} else {
// Busca na API CNPJÁ
$cnpjData = app(Cnpja::class)->fetchCnpjData($onlyDigits);
if (empty($cnpjData['cnpj'])) {
$this->addError('data.client.cnpj', __('validation.custom.cnpj.invalid'));
// ...
return;
}
// Preenche o formulário com os dados da API
}
$this->form->fill(['client' => $clientData]);
// ...
}CreateAddressFromCnpj
Esta action é responsável por criar um endereço completo a partir de um CNPJ. Utiliza o padrão de Actions do Laravel.
- Localização:
app/Actions/Address/CreateAddressFromCnpj.php
Funcionamento:
- Utiliza o serviço
Cnpjapara buscar os dados do CNPJ. - Se o CNPJ for inválido ou a API retornar erro, retorna
null. - Se houver dados de cidade e estado, busca ou cria o registro de
Cityno banco de dados. - Utiliza a action
CreateAddresspara criar o endereço com os dados obtidos. - Retorna um array contendo o endereço criado e a inscrição estadual.
Retorno:
- Array
[Address $address, ?string $stateRegistration]em caso de sucesso nullse o CNPJ for inválido
Uso:
php
// Pode ser executado de forma síncrona
[$address, $stateRegistration] = CreateAddressFromCnpj::run($cnpj);
// Ou de forma assíncrona como Job
CreateAddressFromCnpj::dispatch($cnpj);Exemplo de implementação:
php
// app/Actions/Address/CreateAddressFromCnpj.php
public function handle(string $cnpj): ?array
{
$cnpjService = app(Cnpja::class);
$cnpjData = $cnpjService->fetchCnpjData($cnpj);
if (blank($cnpjData)) {
return null;
}
$cityId = null;
$checkCity = filled($cnpjData['address']['city'] ?? null)
&& filled($cnpjData['address']['state'] ?? null);
if ($checkCity) {
$state = State::where('abbreviation', $cnpjData['address']['state'])->first();
if ($state) {
$city = City::firstOrCreate([
'name' => $cnpjData['address']['city'],
'state_id' => $state->id,
]);
$cityId = $city->id;
}
}
$addressData = data_get($cnpjData, 'address', []);
return [CreateAddress::run([
'postal_code' => data_get($addressData, 'zip'),
'street' => data_get($addressData, 'street'),
'neighborhood' => data_get($addressData, 'neighborhood'),
'number' => data_get($addressData, 'number'),
'complement' => data_get($addressData, 'complement'),
'city_id' => $cityId,
]), data_get($cnpjData, 'state_registration')];
}Configuração
Para que a integração funcione corretamente, as seguintes variáveis de ambiente devem ser configuradas no arquivo .env:
dotenv
CNPJA_URL=https://api.cnpja.com/
CNPJA_TOKEN=sua_chave_de_api
CNPJA_ATTEMPTS=3CNPJA_URL: A URL base da API.CNPJA_TOKEN: Sua chave de API obtida no painel do CNPJÁ.CNPJA_ATTEMPTS: O número de tentativas por minuto permitidas peloRateLimiter(geralmente 3, conforme a documentação da API).
Essas variáveis são consumidas através do arquivo de configuração config/services.php.