FW Tutorial baixar Notas Sefaz
🚀 Captura Automática de XML da SEFAZ via DF-e
Guia completo para implementação em PHP com NFePHP/SPED - Consulta NSU automática
📋 Visão Geral
Objetivo: Automatizar a captura de documentos fiscais eletrônicos (NF-e, CTe, MDF-e) diretamente da SEFAZ, utilizando o serviço de Distribuição DF-e.
O sistema utiliza o certificado digital A1 do CNPJ para autenticação e consulta ao WebService de Distribuição DF-e da SEFAZ. O controle é feito através do NSU (Número Sequencial Único), garantindo que nenhum documento seja perdido ou duplicado.
✅ Vantagens:
- Captura automática de todos os documentos fiscais
- Controle preciso via NSU
- Processamento assíncrono via CRON
- Compatível com NF-e, CTe e MDF-e
🏗️ Arquitetura do Sistema
┌─────────────────────────────────────┐
│ Sistema Local │
│ ┌─────────────────────────────┐ │
│ │ Certificado A1 │ │
│ └─────────────┬───────────────┘ │
└────────────────┼────────────────────┘
│
▼
┌─────────────────────────────────────┐
│ SEFAZ - Distribuição DF-e │
│ (WebService SOAP) │
└─────────────┬───────────────────────┘
│
▼
┌─────────────────────────────────────┐
│ docZip (Base64 + GZip) │
│ 1. Decode Base64 │
│ 2. Decompress GZip │
│ 3. Identificar tipo documento │
│ 4. Salvar XML │
│ 5. Atualizar último NSU │
└─────────────────────────────────────┘
🔢 Entendendo o NSU
Importante: O NSU é a chave para o controle de sincronização!
Conceitos Fundamentais:
- NSU (Número Sequencial Único): Identificador único e sequencial atribuído pela SEFAZ a cada documento
- ultNSU: Último NSU processado pelo seu sistema (ponto de partida para novas consultas)
- maxNSU: Maior NSU disponível no momento na SEFAZ
- Intervalo de consulta: Sempre do ultNSU+1 até maxNSU
🔍 Exemplo de Controle de NSU:
// Verificação de NSU disponível $ultNSU = '000000000000001'; // Último processado $maxNSU = '000000000000150'; // Máximo disponível // Consultar documentos do NSU 2 ao 150 $response = $service->consultarDistribuicao($ultNSU); // Após processamento, atualizar $novoUltNSU = '000000000000150'; $repository->atualizarUltNSU($empresaId, $novoUltNSU);
🔄 Fluxo Completo de Processamento
- Carregar Certificado: Carregar arquivo PFX/P12 com senha
- Autenticação: Configurar credenciais SOAP
- Consulta distDFe: Enviar requisição com último NSU
- Recebimento: Obter resposta com docZip em Base64
- Decodificação: Base64 decode
- Descompressão: GZip inflate/decompress
- Identificação: Detectar tipo (procNFe, resNFe, evento, CTe, MDF-e)
- Persistência: Salvar XML no banco/arquivo
- Atualização: Registrar novo último NSU
- Manifestação: Opcional - manifestar ciência da operação
🔄 Ciclo automático: A cada 5 minutos o CRON executa este fluxo para todas as empresas cadastradas.
📡 Estrutura SOAP - Requisição distDFeInt
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
<soap:Header>
<nfeCabecMsg xmlns="http://www.portalfiscal.inf.br/nfe/wsdl/NFeDistribuicaoDFe">
<cUF>35</cUF>
<versaoDados>1.01</versaoDados>
</nfeCabecMsg>
</soap:Header>
<soap:Body>
<nfeDadosMsg xmlns="http://www.portalfiscal.inf.br/nfe/wsdl/NFeDistribuicaoDFe">
<distDFeInt xmlns="http://www.portalfiscal.inf.br/nfe">
<tpAmb>1</tpAmb>
<cUFAutor>35</cUFAutor>
<CNPJ>12345678000199</CNPJ>
<distNSU>
<ultNSU>000000000000001</ultNSU>
</distNSU>
</distDFeInt>
</nfeDadosMsg>
</soap:Body>
</soap:Envelope>
⚠️ Parâmetros importantes:
- tpAmb: 1=Produção, 2=Homologação
- cUFAutor: Código IBGE do estado (35=SP)
- CNPJ: CNPJ do destinatário (apenas números)
🗄️ Estrutura do Banco de Dados
-- Tabela de empresas
CREATE TABLE empresas (
id INT PRIMARY KEY AUTO_INCREMENT,
cnpj VARCHAR(14) NOT NULL UNIQUE,
razao_social VARCHAR(200),
certificado_path VARCHAR(500),
senha_certificado VARCHAR(100),
uf CHAR(2),
tp_amb TINYINT DEFAULT 2, -- 1=Produção, 2=Homologação
ativo TINYINT DEFAULT 1,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- Controle de NSU
CREATE TABLE nsu_controle (
id INT PRIMARY KEY AUTO_INCREMENT,
id_empresa INT NOT NULL,
ult_nsu VARCHAR(20) NOT NULL DEFAULT '000000000000000',
max_nsu VARCHAR(20),
data_atualizacao TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
FOREIGN KEY (id_empresa) REFERENCES empresas(id)
);
-- Armazenamento de XMLs
CREATE TABLE xmls (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
id_empresa INT NOT NULL,
chave VARCHAR(44) NOT NULL,
nsu VARCHAR(20) NOT NULL,
tipo ENUM('NFE','CTE','MDFE','EVENTO') NOT NULL,
schema_xml VARCHAR(50),
xml_content LONGTEXT NOT NULL,
caminho_arquivo VARCHAR(500),
data_emissao DATETIME,
data_captura TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
INDEX idx_chave (chave),
INDEX idx_nsu (nsu),
FOREIGN KEY (id_empresa) REFERENCES empresas(id)
);
-- Log de sincronização
CREATE TABLE log_sincronizacao (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
id_empresa INT NOT NULL,
data_sincronizacao TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
ult_nsu_antes VARCHAR(20),
ult_nsu_depois VARCHAR(20),
documentos_baixados INT,
status ENUM('SUCESSO','ERRO','PARCIAL'),
mensagem_erro TEXT,
FOREIGN KEY (id_empresa) REFERENCES empresas(id)
);
⏰ Configuração da Rotina Automática
# CRON - Executar a cada 5 minutos */5 * * * * /usr/bin/php /var/www/html/app/cron/sincronizar_dfe.php >> /var/log/dfe_sync.log 2>&1 # Também pode ser configurado com frequências diferentes # Executar a cada 10 minutos em horário comercial */10 6-20 * * * /usr/bin/php /var/www/html/app/cron/sincronizar_dfe.php # Executar a cada hora fora do horário comercial 0 0-5,21-23 * * * /usr/bin/php /var/www/html/app/cron/sincronizar_dfe.php
📊 Monitoramento: Mantenha logs detalhados para auditoria e troubleshooting.
💻 Estrutura de Diretórios PHP
projeto/
├── app/
│ ├── Services/
│ │ ├── DFeService.php # Serviço principal
│ │ ├── CertificadoService.php # Gerenciamento de certificados
│ │ ├── SoapClientService.php # Cliente SOAP
│ │ ├── XmlParserService.php # Parser de XML
│ │ └── ManifestacaoService.php # Manifestação de documentos
│ ├── Models/
│ │ ├── Empresa.php
│ │ ├── NsuControle.php
│ │ └── Xml.php
│ ├── Repositories/
│ │ ├── EmpresaRepository.php
│ │ └── XmlRepository.php
│ └── cron/
│ └── sincronizar_dfe.php # Script do CRON
├── storage/
│ ├── certificados/ # Certificados digitais
│ ├── xmls/ # XMLs baixados
│ └── logs/ # Logs do sistema
├── config/
│ └── database.php
└── vendor/
└── nfephp-org/
└── sped-nfe/ # Biblioteca NFePHP
🔧 Métodos Detalhados
carregarCertificado()
/**
* Carrega certificado digital A1
* @param string $caminhoArquivo Caminho do arquivo PFX/P12
* @param string $senha Senha do certificado
* @return array Dados do certificado
*/
public function carregarCertificado($caminhoArquivo, $senha) {
if (!file_exists($caminhoArquivo)) {
throw new \Exception("Certificado não encontrado");
}
$certificado = file_get_contents($caminhoArquivo);
$certData = openssl_pkcs12_read($certificado, $certs, $senha);
if (!$certData) {
throw new \Exception("Falha ao ler certificado");
}
return [
'cert' => $certs['cert'],
'pkey' => $certs['pkey'],
'valid_to' => openssl_x509_parse($certs['cert'])['validTo_time_t']
];
}
consultarDistribuicao()
/**
* Consulta distribuição DF-e
* @param string $ultNSU Último NSU processado
* @param string $cnpj CNPJ da empresa
* @return array Documentos retornados
*/
public function consultarDistribuicao($ultNSU, $cnpj) {
$xmlEnvio = $this->montarXmlConsulta($ultNSU, $cnpj);
$response = $this->soapClient->send(
'https://www1.nfe.fazenda.gov.br/NFeDistribuicaoDFe/NFeDistribuicaoDFe.asmx',
'distDFeInteresse',
$xmlEnvio
);
return $this->processarResposta($response);
}
descompactarDocZip()
/**
* Descompacta documento Base64+GZip
* @param string $docZipBase64 Documento em Base64
* @return string XML descompactado
*/
public function descompactarDocZip($docZipBase64) {
// Decode Base64
$docZip = base64_decode($docZipBase64);
if ($docZip === false) {
throw new \Exception("Erro ao decodificar Base64");
}
// Verificar se é GZip
if (substr($docZip, 0, 2) === "\x1f\x8b") {
$xml = gzdecode($docZip);
if ($xml === false) {
throw new \Exception("Erro ao descompactar GZip");
}
return $xml;
}
return $docZip;
}
💡 Exemplos Práticos Completos
Script Completo de Sincronização
<?php
// sincronizar_dfe.php
require_once 'vendor/autoload.php';
use App\Services\DFeService;
use App\Repositories\EmpresaRepository;
use App\Repositories\XmlRepository;
class SincronizadorDFe {
private $dfeService;
private $empresaRepo;
private $xmlRepo;
public function __construct() {
$this->dfeService = new DFeService();
$this->empresaRepo = new EmpresaRepository();
$this->xmlRepo = new XmlRepository();
}
public function sincronizar() {
$empresas = $this->empresaRepo->getEmpresasAtivas();
foreach ($empresas as $empresa) {
try {
echo "Processando empresa: {$empresa['cnpj']}\n";
// Carregar certificado
$cert = $this->dfeService->carregarCertificado(
$empresa['certificado_path'],
$empresa['senha_certificado']
);
// Obter último NSU
$ultNSU = $this->empresaRepo->getUltimoNSU($empresa['id']);
// Consultar distribuição
$documentos = $this->dfeService->consultarDistribuicao(
$ultNSU,
$empresa['cnpj']
);
// Processar documentos
$processados = 0;
foreach ($documentos as $doc) {
$xml = $this->dfeService->descompactarDocZip($doc['docZip']);
$tipo = $this->dfeService->identificarDocumento($xml);
$chave = $this->dfeService->extrairChave($xml);
// Salvar XML
$this->xmlRepo->salvar([
'id_empresa' => $empresa['id'],
'chave' => $chave,
'nsu' => $doc['nsu'],
'tipo' => $tipo,
'xml_content' => $xml
]);
$processados++;
}
// Atualizar NSU
if ($processados > 0) {
$ultimoDoc = end($documentos);
$this->empresaRepo->atualizarUltimoNSU(
$empresa['id'],
$ultimoDoc['nsu']
);
}
echo "Processados: {$processados} documentos\n";
} catch (\Exception $e) {
echo "Erro empresa {$empresa['cnpj']}: " . $e->getMessage() . "\n";
// Registrar log de erro
}
}
}
}
// Executar
$sincronizador = new SincronizadorDFe();
$sincronizador->sincronizar();
📚 Manuais e Documentação Oficial SEFAZ
🔗 Links oficiais atualizados da SEFAZ/NFe:
📖 Manuais Técnicos:
-
Manual de Orientação do Contribuinte - Distribuição DF-e:
📥 Acessar Portal de Manuais -
Manual de Integração do Contribuinte - NF-e:
📥 Download Manual NF-e -
Especificação Técnica - Distribuição DF-e:
📥 Documentação WebServices
🔧 Ferramentas e Recursos:
-
Validador de XML NF-e:
🔍 Acessar Validador -
Ambiente de Homologação:
🧪 Ambiente de Testes -
Biblioteca NFePHP (GitHub):
💻 NFePHP no GitHub
⚠️ Nota importante: Sempre verifique a versão mais recente dos manuais no portal oficial, pois podem ocorrer atualizações e mudanças nas especificações técnicas.
✅ Checklist de Implementação
Infraestrutura:
- ✔ Servidor com PHP 7.4+
- ✔ Extensão SOAP habilitada
- ✔ Extensão OpenSSL habilitada
- ✔ Extensão Zlib habilitada
- ✔ Permissão de escrita nos diretórios de storage
Certificação Digital:
- ✔ Certificado A1 válido
- ✔ Cadeia de certificação completa
- ✔ Senha do certificado correta
- ✔ Teste de autenticação realizado
Funcionalidades:
- ✔ Consulta NSU funcionando
- ✔ Download de XML funcionando
- ✔ Descompactação GZip funcionando
- ✔ Identificação de documentos funcionando
- ✔ Persistência em banco funcionando
- ✔ CRON configurado
- ✔ Logs implementados
- ✔ Manifestação configurada (opcional)
- ✔ Backup automático de XMLs