pairus / product-data
SDK oficial da PAIRUS para integração com catálogo GTIN/EAN, predição fiscal (IBS/CBS/IS), saneamento em lote e emissão de NF-e/NFC-e e NFS-e Nacional.
Requires
- php: >=8.1.0
- ext-curl: *
- ext-json: *
Requires (Dev)
- phpunit/phpunit: ^10.0 || ^11.0
Suggests
None
Provides
None
Conflicts
None
Replaces
None
README
SDK oficial da PAIRUS Soluções Tecnológicas para PHP moderno (8.1+). Integração nativa de alta performance com o catálogo global de produtos GTIN/EAN, motor preditivo de inteligência artificial para a Reforma Tributária (IBS, CBS e Imposto Seletivo), saneamento fiscal em lote, emissão de NF-e / NFC-e com Autocura SEFAZ e NFS-e Nacional.
⚡ Quickstart em 3 Linhas
composer require pairus/product-data
use Pairus\PairusClient; $pairus = new PairusClient(apiKey: getenv('PAIRUS_API_KEY')); $produto = $pairus->products->get('7891000100103'); echo "{$produto->xProd} | NCM: {$produto->ncm} | CEST: {$produto->cest}";
🧭 Formas de Uso e Flexibilidade
O SDK foi desenhado para respeitar as melhores práticas do PHP moderno (tipagem estrita, DTOs imutáveis public readonly, named arguments e suporte a arrays associativos flexíveis):
// Forma 1: Argumentos nomeados do PHP 8 (alta legibilidade) $predicao = $pairus->fiscal->predict( regimeTributario: 'simples_nacional', ufOrigem: 'SP', ufDestino: 'RJ', xProd: 'Coca-Cola 2L', gtin: '7894900010015' ); // Forma 2: Injeção de dependência em frameworks (Laravel, Symfony) class FiscalController { public function __construct(private PairusClient $pairus) {} }
📚 Guia de Recursos
1. Produtos e Catálogo Global
// Consulta simples por GTIN $produto = $pairus->products->get('7891000100103'); // Consulta cadastral enriquecida (SEO, dimensões logísticas, imagem HD) $produto = $pairus->products->getEnriched('7891000100103'); // Busca semântica por texto e IA $busca = $pairus->products->search('leite condensado sem lactose', limite: 5); foreach ($busca['resultados'] as $item) { echo "[Score {$item['score']}] {$item['produto']['xProd']} - GTIN: {$item['produto']['GTIN']}" . PHP_EOL; } // Identificação por imagem fotográfica (OCR + Visão Computacional) $scan = $pairus->products->scan('/caminho/foto_embalagem.jpg', tipo: 'gtin'); // Também aceita bytes brutos em memória: // $scan = $pairus->products->scan($bytesFoto, nomeArquivo: 'rotulo.png');
2. Predição Fiscal & Reforma Tributária (IBS / CBS / IS)
Calcula automaticamente a matriz tributária completa para 27 UFs e rotas interestaduais:
$predicao = $pairus->fiscal->predict( regimeTributario: 'simples_nacional', // 'simples_nacional' | 'lucro_presumido' | 'lucro_real' ufOrigem: 'SP', ufDestino: 'MG', finalidade: 'revenda', // 'revenda' | 'consumo_final' | 'industrializacao' destinatarioContribuinte: true, gtin: '7894900010015', xProd: 'REFRIGERANTE COCA COLA 2L' ); $trib = $predicao->dadosTributarios; // CFOP interno (mesma UF) e externo (interestadual): use o que corresponde à operação echo "NCM: {$trib->ncmSugerido} | CFOP: {$trib->cfopInterno} / {$trib->cfopExterno} | CSOSN: {$trib->icmsCstCsosn}" . PHP_EOL; echo "IBS/CBS CST: {$trib->ibscbs->cst} | ClassTrib: {$trib->ibscbs->cClassTrib}" . PHP_EOL; echo "CBS Efetiva: {$trib->ibscbs->cbsAliquotaEfetiva}% | IBS Efetivo: {$trib->ibscbs->ibsAliquotaEfetiva}%" . PHP_EOL;
3. Saneamento Fiscal em Lote
Audite e higienize cadastros inteiros de ERPs e e-commerces em uma única requisição:
$lote = [ ['xProd' => 'CERVEJA HEINEKEN LATA 350ML', 'id' => '7896045506163', 'NCM' => '22030000', 'CEST' => '0302100'], ['xProd' => 'ARROZ BRANCO TIPO 1 5KG', 'NCM' => '10063021'], ]; $resultado = $pairus->fiscal->sanitize($lote); foreach ($resultado['itens'] as $item) { $auditoria = $item['auditoria_fiscal']; $vigente = $auditoria['ncm_vigente'] ? 'vigente' : 'INATIVO'; echo "{$item['xProd']} -> NCM {$item['NCM_informado']} ({$vigente}) | CEST: {$auditoria['cest_sugerido']}" . PHP_EOL; }
4. Emissão de NF-e / NFC-e com Autocura SEFAZ
// NF-e com enquadramento fiscal assistido $nfe = $pairus->emissao->emitirNfe([ 'cnpj_emitente' => '11222333000181', 'natureza_operacao' => 'Venda de Mercadoria', 'destinatario' => ['cpf_cnpj' => '12345678000195', 'razao_social' => 'Cliente Exemplo LTDA', 'uf' => 'SP'], 'itens' => [ ['descricao' => 'Teclado Mecânico USB', 'ncm' => '84716052', 'cfop' => '5102', 'quantidade' => 1, 'valor_unitario' => 250.0], ], ]); echo "{$nfe->statusSefaz} [{$nfe->cStat}] {$nfe->xMotivo}" . PHP_EOL; // NFC-e no PDV: troco gerado pela API e reenvio seguro com Idempotency-Key $nfce = $pairus->emissao->emitirNfce([ 'cnpj_emitente' => '11222333000181', 'tipo_documento' => 'NFCE', 'itens' => [['descricao' => 'Refrigerante 2L', 'ncm' => '22021000', 'valor_unitario' => 9.90, 'quantidade' => 2]], 'pagamentos' => [['forma_pagamento' => '01', 'valor' => 50.0]], ], 'pdv03-cupom-000123'); // Simulação prévia com CUSTO ZERO de créditos $simulacao = $pairus->emissao->simular([ 'cnpj_emitente' => '11222333000181', 'destinatario' => ['cpf_cnpj' => '12345678000195', 'razao_social' => 'Cliente Teste', 'uf' => 'SP'], 'itens' => [['descricao' => 'Item Teste', 'valor_unitario' => 10.0]], ]);
Toda emissão envia o cabeçalho Idempotency-Key. Sem chave informada, o SDK gera um UUID e o reutiliza nas
retentativas automáticas: se a primeira tentativa já tiver emitido a nota, a API devolve essa mesma nota
($nfce->repeticaoIdempotente === true, sem novo faturamento) em vez de emitir outra. A chave vale por 24 h e é
liberada se a nota for rejeitada.
Contingência off-line da NFC-e: com a opção ativada na conta (tela de emissão da Área do Cliente), a venda
não trava quando a SEFAZ não responde: a resposta vem com sucesso verdadeiro, $nfce->statusSefaz igual a CONTINGENCIA
(cStat 9, código da PAIRUS) e o DANFE com a tarja de contingência e a via do estabelecimento, sem consumir créditos.
A nota é transmitida automaticamente depois, e o desfecho chega por webhook (nfe.autorizada,
nfe.contingencia_rejeitada, nfe.substituida_cancelada, nfe.substituida_inutilizada,
nfe.regularizacao_manual). Para recusar a contingência numa venda, envie 'permitir_contingencia' => false.
Autorização com alerta (cStat 120, NT 2026.002): a nota está autorizada e não deve ser reemitida; os alertas da SEFAZ (cMsg/xMsg, até 5) vêm em $nfce->alertasSefaz. Venda em marketplace (NT 2020.006): informe o marketplace no payload, 'intermediador' => ['cnpj' => '03007331000141', 'id_cadastro' => 'MINHA-LOJA'], para a nota sair com indIntermed=1 e o grupo infIntermed; o campo indicador_presenca define o indPres (padrão: 1 na NFC-e e 2 na NF-e). DIFAL: na NF-e interestadual a consumidor final não contribuinte, a API gera o grupo ICMSUFDest com a alíquota modal da UF de destino; para outra alíquota interna ou FCP, envie no item 'difal' => ['aliquota_interna_destino' => 19.0, 'fcp_percentual' => 2.0].
5. NFS-e Nacional de Serviços
$nota = [ 'ambiente' => 'homologacao', 'prestador' => ['cnpj' => '12345678000199', 'inscricao_municipal' => '87654321', 'razao_social' => 'Minha Empresa Ltda'], 'tomador' => ['cpf_cnpj' => '98765432000188', 'razao_social' => 'Cliente Ltda'], 'servico' => [ 'item_lista_servico' => '1.01', 'discriminacao' => 'Serviços de Programação PHP', 'municipio_prestacao_ibge' => '3550308', 'valor_servicos' => 2500.0, 'aliquota_iss' => 2.0, // Opcional: IBS/CBS do serviço (LC 214/2025) 'reforma_tributaria' => ['cClassTrib' => '000001', 'aliquota_cbs' => 0.9], ], ]; // 1. Simulação prévia de tributos (sem custo) $simulacao = $pairus->nfse->simular($nota); // 2. Emissão definitiva $nfse = $pairus->nfse->emitir($nota); echo "NFS-e Nº: {$nfse->numeroNfse} | Consulta: {$nfse->linkVisualizacao}" . PHP_EOL; // 3. Consulta de situação $status = $pairus->nfse->consultar($nfse->chaveAcessoNacional ?? $nfse->numeroNfse); // 4. Cancelamento homologado $cancel = $pairus->nfse->cancelar([ 'numero_nfse' => $nfse->numeroNfse, 'chave_acesso_nacional' => $nfse->chaveAcessoNacional, 'cnpj_prestador' => '12345678000199', 'inscricao_municipal' => '87654321', 'codigo_municipio_ibge' => '3550308', 'motivo_codigo' => '1', // '1' erro de emissão, '2' serviço não prestado, '3' duplicidade, '9' outros 'justificativa' => 'Cancelamento solicitado pelo cliente por erro cadastral', ]);
6. DF-e Inbound & Captura Ativa SEFAZ (Gestão de Compras)
Capture ativamente as notas fiscais emitidas por fornecedores contra o CNPJ da sua empresa via WebService NFeDistribuicaoDFe da SEFAZ Nacional:
// 1. Sincronizar e consultar novos documentos na SEFAZ Nacional $sync = $pairus->dfe->sincronizar(cnpj: '12345678000195', ambiente: 'producao'); echo "Status SEFAZ [{$sync['cstat']}]: {$sync['xmotivo']}" . PHP_EOL; echo "Novos documentos capturados: {$sync['novos_documentos']}" . PHP_EOL; echo "Avanço de NSU: {$sync['ult_nsu']} -> {$sync['max_nsu']}" . PHP_EOL; foreach ($sync['documentos'] as $doc) { echo "NF-e {$doc['numero']}/{$doc['serie']} - R$ {$doc['valor_total']} ({$doc['nome_emitente']})" . PHP_EOL; } // 2. Listar notas fiscais de compras capturadas $compras = $pairus->dfe->listarDocumentos(cnpj: '12345678000195', limite: 50); // 3. Manifestação do Destinatário perante a SEFAZ // Eventos: '210210' (Ciência), '210200' (Confirmação), '210220' (Desconhecimento), '210240' (Não Realizada) $manif = $pairus->dfe->manifestar( chaveAcesso: '35260912345678000195550010000000451234567890', cnpj: '12345678000195', tipoEvento: '210210' // Ciência da Emissão para liberar download do XML completo ); echo "Manifestação homologada. Protocolo: {$manif['protocolo']}" . PHP_EOL; // 4. Download do XML autorizado (procNFe) e DANFE em PDF $chave = '35260912345678000195550010000000451234567890'; $xmlString = $pairus->dfe->baixarXml($chave); file_put_contents("{$chave}.xml", $xmlString); $danfePdfBytes = $pairus->dfe->baixarDanfe($chave); file_put_contents("DANFE_{$chave}.pdf", $danfePdfBytes);
7. Validação Segura de Webhooks (HMAC-SHA256)
use Pairus\Webhooks; use Pairus\Exceptions\InvalidSignatureException; $payload = file_get_contents('php://input'); $signature = $_SERVER['HTTP_X_PAIRUS_SIGNATURE'] ?? ''; try { $event = Webhooks::constructEvent($payload, $signature, getenv('PAIRUS_WEBHOOK_SECRET')); if ($event->event === 'nfe.autorizada') { // Processar faturamento concluído } } catch (InvalidSignatureException $e) { http_response_code(401); exit('Assinatura inválida'); }
📋 Tabela de Parâmetros: Obrigatório vs. Opcional
Predição Fiscal ($pairus->fiscal->predict)
| Parâmetro | Tipo | Obrigatório? | Descrição & Regra Fiscal |
|---|---|---|---|
regimeTributario |
string | Sim | 'simples_nacional', 'lucro_presumido' ou 'lucro_real'. |
ufOrigem |
string | Sim | Sigla da UF do emitente (ex: 'SP'). |
ufDestino |
string | Não | Sigla da UF do destinatário. Se omitido, assume operação interna ($ufOrigem). |
finalidade |
string | Não | 'revenda' (padrão), 'consumo_final' ou 'industrializacao'. |
destinatarioContribuinte |
bool | Não | Define aplicação de DIFAL / ST (padrão: true). |
gtin |
string | Não* | Código de barras GTIN/EAN numérico (8, 12, 13 ou 14 dígitos). |
xProd |
string | Não* | Descrição comercial da mercadoria (para predição por IA/RAG). |
ncm |
string | Não | NCM atual de 8 dígitos para validação e auditoria. |
cest |
string | Não | Código CEST de 7 dígitos para validação de ICMS-ST. |
itens |
array | Não | Lista de itens para cálculo consolidado de NF-e completa em lote. |
*Nota: Pelo menos um identificador (gtin, xProd ou ncm) deve ser informado no modo individual.
NFS-e Nacional ($pairus->nfse->emitir)
| Parâmetro | Tipo | Obrigatório? | Descrição |
|---|---|---|---|
prestador.cnpj |
string | Sim | CNPJ do emissor prestador de serviços. |
tomador.cpf_cnpj |
string | Sim | CPF ou CNPJ do tomador do serviço. |
tomador.razao_social |
string | Sim | Razão social ou nome completo do tomador. |
servico.discriminacao |
string | Sim | Descrição clara dos serviços prestados. |
servico.valor_servicos |
float | Sim | Valor bruto total dos serviços (R$). |
servico.item_lista_servico |
string | Não | Item da LC 116/2003 (ex: '01.01'). |
servico.codigo_tributacao_municipio |
string | Não | Código municipal de tributação da prefeitura. |
servico.aliquota_iss |
float | Não | Alíquota nominal do ISS (ex: 2.0 para 2%). |
servico.iss_retido |
bool | Não | True se o ISS for retido na fonte pelo tomador. |
Manifestação do Destinatário ($pairus->dfe->manifestar)
| Parâmetro | Tipo | Obrigatório? | Descrição & Regras Fiscais |
|---|---|---|---|
chaveAcesso |
string | Sim | Chave de 44 dígitos da NF-e emitida pelo fornecedor. |
cnpj |
string | Sim | CNPJ da sua empresa compradora/destinatária. |
tipoEvento |
string | Sim | '210210' (Ciência), '210200' (Confirmação), '210220' (Desconhecimento), '210240' (Não Realizada). |
justificativa |
string | Condicional | Obrigatória estritamente para '210240' (mínimo de 15 caracteres). |
ambiente |
string | Não | 'producao' (padrão) ou 'homologacao'. |
🛠️ Exemplos em Frameworks
Laravel (Controller & Service)
namespace App\Http\Controllers; use Illuminate\Http\Request; use Pairus\PairusClient; class FiscalController extends Controller { public function consultar(string $gtin, PairusClient $pairus) { try { $produto = $pairus->products->get($gtin); return response()->json($produto); } catch (\Pairus\Exceptions\PairusApiException $e) { return response()->json(['erro' => $e->xMotivo], $e->statusCode); } } }
WordPress / WooCommerce
add_action('woocommerce_process_product_meta', function ($postId) { $gtin = get_post_meta($postId, '_gtin', true); if (!empty($gtin)) { $pairus = new \Pairus\PairusClient(apiKey: defined('PAIRUS_API_KEY') ? PAIRUS_API_KEY : ''); $produto = $pairus->products->get($gtin); update_post_meta($postId, '_ncm', $produto->ncm); update_post_meta($postId, '_cest', $produto->cest); } });
🛡️ Tratamento de Erros e Padrão SEFAZ
Todas as exceções estendem PairusApiException, expondo os códigos de status e descrições do layout SEFAZ:
try { $pairus->products->get('0000000000000'); } catch (\Pairus\Exceptions\AuthenticationException $e) { // Chave de API inválida ou expirada (HTTP 401) echo "Erro de autenticação: {$e->getMessage()}"; } catch (\Pairus\Exceptions\RateLimitException $e) { // Limite de requisições atingido (HTTP 429) echo "Aguarde {$e->retryAfter} segundos."; } catch (\Pairus\Exceptions\PairusApiException $e) { // Erros de negócio ou rejeição fiscal echo "SEFAZ cStat: {$e->cStat} | Motivo: {$e->xMotivo}"; } catch (\Pairus\Exceptions\NetworkException $e) { // Falha de rede após retentativas exponenciais echo "Falha de conexão: {$e->getMessage()}"; }
📄 Licença
Distribuído sob a licença MIT. Consulte o arquivo LICENSE para mais detalhes.