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:

🔍 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

  1. Carregar Certificado: Carregar arquivo PFX/P12 com senha
  2. Autenticação: Configurar credenciais SOAP
  3. Consulta distDFe: Enviar requisição com último NSU
  4. Recebimento: Obter resposta com docZip em Base64
  5. Decodificação: Base64 decode
  6. Descompressão: GZip inflate/decompress
  7. Identificação: Detectar tipo (procNFe, resNFe, evento, CTe, MDF-e)
  8. Persistência: Salvar XML no banco/arquivo
  9. Atualização: Registrar novo último NSU
  10. 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:

🔧 Ferramentas e Recursos:

⚠️ 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