Emissor de NF-e e NFC-e com SPED PHP

Um guia passo a passo para desenvolvedores brasileiros

v1.0 Atualizado: 28/10/2025

📋 Introdução à NFC-e

NFC-e significa Nota Fiscal do Consumidor Eletrônica - um documento digital que substitui o cupom fiscal em vendas presenciais.

A Nota Fiscal do Consumidor Eletrônica (NFC-e) é um documento digital emitido para registrar operações comerciais presenciais (como vendas em lojas), substituindo a nota fiscal de modelo 1 ou 2 e o cupom fiscal.

🎯 Principais Vantagens

  • Agilidade no processo de venda
  • Redução de custos com papel
  • Envio automático por e-mail/SMS
  • Consulta via QR Code
  • Validação online na SEFAZ

📊 Características Técnicas

  • Modelo: 65
  • XML assinado digitalmente
  • DANFE NFC-e simplificado
  • QR Code para consulta
  • Ambiente de homologação

🔗 Fluxo da NFC-e

1. Emissão do XML

Sistema gera o XML com todos os dados da venda seguindo o layout oficial da SEFAZ.

2. Assinatura Digital

XML é assinado com certificado digital A1 ou A3 da empresa emissora.

3. Transmissão SEFAZ

Envio para o webservice da Secretaria da Fazenda do estado.

4. Autorização

SEFAZ valida e retorna protocolo de autorização.

⚠️ Importante: A NFC-e é destinada exclusivamente para operações presenciais (venda ao consumidor final). Para vendas a distância, utilize a NFe modelo 55.

⚙️ Requisitos Obrigatórios

Antes de iniciar o desenvolvimento, é fundamental ter em mãos todos os requisitos legais e técnicos:

🔐 Certificado Digital

Obrigatório: Funciona como identidade digital da empresa.

  • Tipo A1: Arquivo .pfx
  • Tipo A3: Token ou cartão
  • Requisito: CNPJ da empresa
  • Habilitada: Venda de Produtos

📄 Inscrição Estadual

Empresa deve ter IE ativa no estado de emissão.

  • Contribuinte ICMS
  • IE válida e regular
  • Credenciamento SEFAZ

🌐 Credenciamento SEFAZ

Autorização para emissão de NFC-e.

  • Ambiente homologação
  • Ambiente produção
  • CSC (NFC-e específico)

🔑 CSC - Código de Segurança do Contribuinte

Exclusivo para NFC-e: Usado para assinar o QR Code no DANFE.

🚨 ATENÇÃO: Não confunda CSC com certificado digital!

Item Finalidade Onde é usado
Certificado Digital Assina o XML da nota Comunicação com SEFAZ
CSC Assina o QR Code DANFE NFC-e

🛡️ Proteja o CSC!

  • Nunca publique em código aberto
  • Não compartilhe com terceiros
  • Armazene com segurança
  • Use variáveis de ambiente

🎯 Ambientes de Trabalho

Ambiente Finalidade Status Recomendação
Homologação Testes e desenvolvimento TESTES Use exaustivamente antes de produção
Produção Operações reais PRODUÇÃO Somente após testes completos

📚 A Biblioteca SPED PHP

SPED PHP antiga NFePHP, é a biblioteca mais completa e atualizada para comunicação com os WebServices da SEFAZ na comunidade PHP brasileira.

🎯 O que a SPED PHP faz?

  • ✅ Geração e validação de XMLs
  • ✅ Assinatura digital com certificado
  • ✅ Comunicação com webservices SEFAZ
  • ✅ Consulta e tratamento de retornos
  • ✅ Geração de DANFE
  • ✅ Cancelamento e inutilização

📦 Estrutura de Pacotes

Pacote Repositório Função Principal Status
sped-nfe GitHub NF-e e NFC-e com SEFAZ ATIVO
sped-common Dependência Funcionalidades comuns ATIVO
sped-docs GitHub Documentação oficial ATIVO

⚡ Requisitos do Sistema

Versões do PHP Suportadas

Versão PHP Status Recomendação
PHP 5.6+ LEGADO Não recomendado
PHP 7.x SUPORTE Compatível
PHP 8.x RECOMENDADO Melhor performance
PHP 8.3+ ATUAL Setembro/2025

🔧 Extensões PHP Necessárias

Extensão Finalidade Obrigatória
curl Comunicação HTTP
dom Manipulação XML
openssl Assinatura digital
soap Webservices SEFAZ
xml Processamento XML
json Configurações
mbstring Strings multibyte
zip Compactação

📥 Instalação via Composer

# Instalar o pacote principal
composer require nfephp-org/sped-nfe

# Ou adicionar no composer.json
{
    "require": {
        "nfephp-org/sped-nfe": "^5.0"
    }
}

💡 Dica: Sempre use a versão mais recente para garantir compatibilidade com as atualizações da SEFAZ.

🔄 Processo de Emissão em 4 Etapas

Emitir uma NFC-e envolve um fluxo específico que sua aplicação deve seguir rigorosamente.

📋 Montagem do XML

Sua aplicação deve preencher todas as tags do XML seguindo rigorosamente o leiaute definido pela SEFAZ.

Estrutura Básica do XML:

<NFe xmlns="http://www.portalfiscal.inf.br/nfe">
  <infNFe Id="NFe35150900000000000000650010000000010000000000" versao="4.00">
    <ide>
      <cUF>35</cUF>
      <cNF>00000000</cNF>
      <natOp>VENDA AO CONSUMIDOR</natOp>
      <mod>65</mod>
      <serie>1</serie>
      <nNF>1</nNF>
      <dhEmi>2025-09-25T10:00:00-03:00</dhEmi>
      <tpNF>1</tpNF>
      <idDest>1</idDest>
      <tpAmb>2</tpAmb>
    </ide>
    <!-- ... demais seções -->
  </infNFe>
</NFe>

⚠️ Atenção: O XML deve seguir exatamente o schema XSD publicado pela SEFAZ. Qualquer divergência resultará em rejeição.

🔐 Assinatura Digital

O XML gerado deve ser assinado digitalmente usando o certificado digital A1 ou A3 da empresa.

O que a assinatura garante:

  • Autenticidade: Prova que foi gerado pela empresa emissora
  • Integridade: Impede alterações após assinatura
  • Não-repúdio: Empresa não pode negar emissão

Exemplo de Assinatura:

// Com NFePHP
$nfe->assinarNFe();

// Manualmente (exemplo simplificado)
openssl_pkcs7_sign(
    $xmlFile, 
    $signedFile, 
    $certificate, 
    $privateKey, 
    [], 
    PKCS7_BINARY | PKCS7_DETACHED
);

🌐 Transmissão para a SEFAZ

O XML assinado é enviado para o WebService da SEFAZ do estado do emitente.

Fluxo de Transmissão:

  1. Conectar ao webservice SOAP da SEFAZ
  2. Enviar XML via protocolo HTTPS
  3. Aguardar processamento
  4. Receber recibo de processamento

URLs dos Webservices (Exemplos):

Estado Homologação Produção
São Paulo https://homologacao.nfce.fazenda.sp.gov.br https://nfe.fazenda.sp.gov.br
Rio de Janeiro https://hom.nfce.fazenda.rj.gov.br https://nfce.fazenda.rj.gov.br
Minas Gerais https://hnfe.fazenda.mg.gov.br https://nfe.fazenda.mg.gov.br

📨 Tratamento do Retorno

A SEFAZ retorna um protocolo de autorização ou um código de rejeição.

Possíveis Retornos:

Código Status Ação
100 AUTORIZADA Nota autorizada com sucesso
101 CANCELADA Nota cancelada
110 DENEGADA Nota denegada pela SEFAZ
2xx REJEITADA Corrigir erro e reenviar

Exemplo de Retorno de Sucesso:

<protNFe versao="4.00">
  <infProt>
    <tpAmb>2</tpAmb>
    <verAplic>SP_NFCE_4.0</verAplic>
    <chNFe>35240912345678000123650010000001234567890123</chNFe>
    <dhRecbto>2025-09-25T10:05:00-03:00</dhRecbto>
    <nProt>135220000000123</nProt>
    <digVal>Wm9tQWRpZ0hhc2hEYURpZ0hhc2hEYQ==</digVal>
    <cStat>100</cStat>
    <xMotivo>Autorizado o uso da NFC-e</xMotivo>
  </infProt>
</protNFe>

🎯 Resumo do Fluxo para o Usuário

Etapa O que faz Quando está "OK" Responsabilidade
Assinar Aplica assinatura digital com certificado XML contém tag <Signature> válida Sistema
Validar Verifica estrutura e regras de negócio XML cumple layout e regras SEFAZ Sistema + Desenvolvedor
Transmitir Envia XML ao webservice SEFAZ Retorno com protocolo de autorização Sistema + SEFAZ

💻 Exemplo Prático de Implementação

Veja na prática como implementar um emissor de NFC-e usando a biblioteca SPED PHP.

📦 Estrutura do Projeto

Primeiro, vamos entender a estrutura de arquivos recomendada:

Estrutura de Diretórios
projeto-nfce/
├── composer.json
├── index.php
├── config/
│   └── config.json
├── src/
│   ├── EmissorNFCe.php
│   └── Database.php
├── certificates/
│   └── certificado.pfx
├── storage/
│   ├── xmls/
│   ├── pdfs/
│   └── logs/
└── vendor/
    └── nfephp-org/

1. Configuração Inicial

📝 composer.json

{
    "name": "seu-projeto/nfce-emissor",
    "description": "Sistema emissor de NFC-e com PHP",
    "type": "project",
    "require": {
        "nfephp-org/sped-nfe": "^5.0",
        "ext-curl": "*",
        "ext-dom": "*",
        "ext-openssl": "*",
        "ext-soap": "*",
        "ext-zip": "*",
        "ext-json": "*",
        "ext-mbstring": "*"
    },
    "autoload": {
        "psr-4": {
            "App\\": "src/"
        }
    }
}
🎯 Comandos de Instalação:
# Instalar dependências
composer install

# Ou se já tem o composer.json, apenas:
composer update

# Verificar extensões PHP necessárias
php -m | grep -E "(curl|dom|openssl|soap|zip|json|mbstring)"

⚙️ config/config.json

{
    "atualizacao": "2025-09-25 10:00:00",
    "tpAmb": 2,
    "razaosocial": "SUA EMPRESA LTDA",
    "cnpj": "12345678000123",
    "siglaUF": "SP",
    "schemes": "PL_009_V4",
    "versao": "4.00",
    "tokenIBPT": "",
    "CSC": "SEU_CODIGO_CSC",
    "CSCid": "1",
    "pathNFSeFiles": "/var/www/nfse/",
    "pathSalvar": "/var/www/nfe/arquivos/",
    "pathLogo": "/var/www/nfe/logo.png",
    "pathCertificado": "/var/www/nfe/certificates/",
    "certPfx": "certificado.pfx",
    "certPassword": "sua_senha_secreta",
    "certPhrase": "",
    "aProxyConf": {
        "proxyIp": "",
        "proxyPort": "",
        "proxyUser": "",
        "proxyPass": ""
    },
    "aMailConf": {
        "mailAuth": true,
        "mailFrom": "nfe@empresa.com.br",
        "mailSmtp": "smtp.empresa.com.br",
        "mailUser": "nfe@empresa.com.br",
        "mailPass": "sua_senha_email",
        "mailProtocol": "ssl",
        "mailPort": "587",
        "mailFromMail": "nfe@empresa.com.br",
        "mailFromName": "SUA EMPRESA LTDA"
    }
}
⚠️ Importante:

Substitua todos os valores pelos dados reais da sua empresa. O tpAmb deve ser 1 para produção.

🗃️ Estrutura do Banco de Dados

-- Tabela de empresas (emitente)
CREATE TABLE empresas (
    id INT PRIMARY KEY AUTO_INCREMENT,
    razao_social VARCHAR(255) NOT NULL,
    nome_fantasia VARCHAR(255),
    cnpj VARCHAR(14) UNIQUE NOT NULL,
    ie VARCHAR(20),
    regime_tributario VARCHAR(1),
    -- ... outros campos
);

-- Tabela de produtos
CREATE TABLE produtos (
    id INT PRIMARY KEY AUTO_INCREMENT,
    codigo VARCHAR(50) UNIQUE NOT NULL,
    descricao VARCHAR(255) NOT NULL,
    ncm VARCHAR(8) NOT NULL,
    cest VARCHAR(7),
    unidade VARCHAR(10) NOT NULL,
    valor DECIMAL(10,2) NOT NULL,
    -- campos fiscais
    origem VARCHAR(1) DEFAULT '0',
    cst_icms VARCHAR(3),
    aliquota_icms DECIMAL(5,2),
    cst_pis VARCHAR(2) DEFAULT '06',
    cst_cofins VARCHAR(2) DEFAULT '06'
);

-- Tabela de NFC-e
CREATE TABLE nfce (
    id INT PRIMARY KEY AUTO_INCREMENT,
    numero INT NOT NULL,
    serie INT DEFAULT 1,
    chave VARCHAR(44) UNIQUE,
    status VARCHAR(20) DEFAULT 'pendente',
    xml_enviado TEXT,
    xml_autorizado TEXT,
    protocolo VARCHAR(50),
    data_emissao DATETIME,
    valor_total DECIMAL(10,2),
    -- ... outros campos
);

2. Classe Principal do Emissor

PHP - EmissorNFCe.php
<?php

namespace App;

use NFePHP\NFe\Tools;
use NFePHP\Common\Certificate;
use Exception;

class EmissorNFCe
{
    private $tools;
    private $config;
    
    public function __construct($configPath)
    {
        $this->carregarConfiguracao($configPath);
        $this->inicializarTools();
    }
    
    private function carregarConfiguracao($configPath)
    {
        if (!file_exists($configPath)) {
            throw new Exception("Arquivo de configuração não encontrado: $configPath");
        }
        
        $this->config = json_decode(file_get_contents($configPath), true);
        
        if (json_last_error() !== JSON_ERROR_NONE) {
            throw new Exception("Erro ao decodificar JSON de configuração: " . json_last_error_msg());
        }
    }
    
    private function inicializarTools()
    {
        $certificate = Certificate::readPfx(
            file_get_contents($this->config['pathCertificado'] . $this->config['certPfx']),
            $this->config['certPassword']
        );
        
        $this->tools = new Tools($this->config, $certificate);
        $this->tools->model('65'); // NFC-e
    }
    
    public function emitir($dadosVenda)
    {
        try {
            // 1. Montar XML
            $xml = $this->montarXML($dadosVenda);
            
            // 2. Assinar
            $xmlAssinado = $this->tools->signNFe($xml);
            
            // 3. Validar
            $this->validarNFe($xmlAssinado);
            
            // 4. Enviar para SEFAZ
            $resp = $this->tools->sefazEnviaLote([$xmlAssinado], $dadosVenda['idLote']);
            
            // 5. Consultar recibo
            $protocolo = $this->consultarRecibo($resp['infRec']['nRec']);
            
            return [
                'sucesso' => true,
                'chave' => $this->tools->getChave(),
                'protocolo' => $protocolo,
                'xml' => $xmlAssinado
            ];
            
        } catch (Exception $e) {
            return [
                'sucesso' => false,
                'erro' => $e->getMessage()
            ];
        }
    }
    
    private function montarXML($dados)
    {
        // Configuração básica
        $this->tools->tagide(
            $dados['cUF'],
            $dados['cNF'],
            $dados['natOp'],
            $dados['mod'],
            $dados['serie'],
            $dados['nNF'],
            $dados['dhEmi'],
            $dados['tpNF'],
            $dados['idDest'],
            $dados['cMunFG'],
            $dados['tpImp'],
            $dados['tpEmis'],
            $dados['tpAmb'],
            $dados['finNFe'],
            $dados['indFinal'],
            $dados['indPres'],
            $dados['procEmi']
        );
        
        // Emitente
        $this->tools->tagemit(
            $this->config['cnpj'],
            $this->config['razaosocial'],
            $this->config['nomefantasia'] ?? '',
            $dados['enderEmit']['xLgr'],
            $dados['enderEmit']['nro'],
            $dados['enderEmit']['xBairro'],
            $dados['enderEmit']['cMun'],
            $dados['enderEmit']['xMun'],
            $dados['enderEmit']['UF'],
            $dados['enderEmit']['CEP'],
            $dados['enderEmit']['cPais'] ?? '1058',
            $dados['enderEmit']['xPais'] ?? 'BRASIL',
            $dados['enderEmit']['fone'] ?? '',
            $this->config['ie'],
            $this->config['crt'] ?? '1'
        );
        
        // Destinatário (opcional para NFC-e)
        if (isset($dados['destinatario'])) {
            $this->tools->tagdest(
                $dados['destinatario']['cnpj'] ?? '',
                $dados['destinatario']['cpf'] ?? '',
                $dados['destinatario']['xNome'] ?? '',
                $dados['destinatario']['enderDest']['xLgr'] ?? '',
                $dados['destinatario']['enderDest']['nro'] ?? '',
                $dados['destinatario']['enderDest']['xBairro'] ?? '',
                $dados['destinatario']['enderDest']['cMun'] ?? '',
                $dados['destinatario']['enderDest']['xMun'] ?? '',
                $dados['destinatario']['enderDest']['UF'] ?? '',
                $dados['destinatario']['enderDest']['CEP'] ?? '',
                $dados['destinatario']['enderDest']['cPais'] ?? '1058',
                $dados['destinatario']['enderDest']['xPais'] ?? 'BRASIL',
                $dados['destinatario']['enderDest']['fone'] ?? '',
                $dados['destinatario']['indIEDest'] ?? '9',
                $dados['destinatario']['IE'] ?? ''
            );
        } else {
            // Consumidor não identificado
            $this->tools->tagdest('', '', 'CONSUMIDOR NÃO IDENTIFICADO');
        }
        
        // Produtos
        foreach ($dados['produtos'] as $item) {
            $this->tools->tagprod(
                $item['cProd'],
                $item['cEAN'] ?? 'SEM GTIN',
                $item['xProd'],
                $item['NCM'],
                $item['CEST'] ?? '',
                $item['CFOP'],
                $item['uCom'],
                $item['qCom'],
                $item['vUnCom'],
                $item['vProd'],
                $item['cEANTrib'] ?? 'SEM GTIN',
                $item['uTrib'],
                $item['qTrib'],
                $item['vUnTrib'],
                $item['indTot'] ?? '1'
            );
            
            // Impostos
            $this->tools->tagICMS(
                $item['imposto']['ICMS']['orig'] ?? '0',
                $item['imposto']['ICMS']['CST'] ?? '',
                $item['imposto']['ICMS']['CSOSN'] ?? '102',
                $item['imposto']['ICMS']['modBC'] ?? '0',
                $item['imposto']['ICMS']['vBC'] ?? '0.00',
                $item['imposto']['ICMS']['pICMS'] ?? '0.00',
                $item['imposto']['ICMS']['vICMS'] ?? '0.00'
            );
        }
        
        // Pagamento
        $this->tools->tagpag($dados['pagamento']['tPag'], $dados['pagamento']['vPag']);
        
        return $this->tools->getXML();
    }
    
    private function validarNFe($xml)
    {
        // Validação contra schema XSD
        $this->tools->validar($xml);
    }
    
    private function consultarRecibo($numeroRecibo)
    {
        // Aguardar processamento
        sleep(5);
        
        $attempts = 0;
        while ($attempts < 10) {
            $resp = $this->tools->sefazConsultaRecibo($numeroRecibo);
            
            if ($resp['cStat'] == '104') {
                // Lote em processamento, aguardar
                sleep(3);
                $attempts++;
                continue;
            }
            
            if ($resp['cStat'] == '100') {
                return $resp['nProt']; // Nota autorizada
            }
            
            if ($resp['cStat'] == '101' || $resp['cStat'] == '110') {
                throw new Exception("Nota cancelada ou denegada: " . $resp['xMotivo']);
            }
            
            // Outros status de erro
            throw new Exception("Erro na consulta: " . $resp['xMotivo']);
        }
        
        throw new Exception("Tempo limite excedido para consulta do recibo");
    }
}

3. Exemplo de Uso

PHP - index.php (Exemplo de uso)
<?php
require_once 'vendor/autoload.php';
use App\EmissorNFCe;

try {
    // Inicializar emissor
    $emissor = new EmissorNFCe('config/config.json');
    
    // Dados da venda
    $dadosVenda = [
        'idLote' => 1,
        'cUF' => '35',
        'cNF' => rand(10000000, 99999999),
        'natOp' => 'VENDA AO CONSUMIDOR',
        'mod' => '65',
        'serie' => '1',
        'nNF' => '1',
        'dhEmi' => date('c'),
        'tpNF' => '1',
        'idDest' => '1',
        'cMunFG' => '3520509',
        'tpImp' => '4',
        'tpEmis' => '1',
        'tpAmb' => '2',
        'finNFe' => '1',
        'indFinal' => '1',
        'indPres' => '1',
        'procEmi' => '0',
        
        'enderEmit' => [
            'xLgr' => 'Rua Exemplo',
            'nro' => '123',
            'xBairro' => 'Centro',
            'cMun' => '3520509',
            'xMun' => 'Indaiatuba',
            'UF' => 'SP',
            'CEP' => '13330000',
            'fone' => '19999999999'
        ],
        
        'produtos' => [
            [
                'cProd' => '001',
                'xProd' => 'Produto de Exemplo',
                'NCM' => '39269090',
                'CFOP' => '5102',
                'uCom' => 'UN',
                'qCom' => '1.0000',
                'vUnCom' => '50.00',
                'vProd' => '50.00',
                'uTrib' => 'UN',
                'qTrib' => '1.0000',
                'vUnTrib' => '50.00',
                'imposto' => [
                    'ICMS' => [
                        'orig' => '0',
                        'CSOSN' => '102'
                    ]
                ]
            ]
        ],
        
        'pagamento' => [
            'tPag' => '01', // Dinheiro
            'vPag' => '50.00'
        ]
    ];
    
    // Emitir NFC-e
    $resultado = $emissor->emitir($dadosVenda);
    
    if ($resultado['sucesso']) {
        echo "✅ NFC-e emitida com sucesso!";
        echo "Chave: " . $resultado['chave'];
        echo "Protocolo: " . $resultado['protocolo'];
        
        // Salvar XML no banco de dados
        salvarNFCeNoBanco($resultado);
        
    } else {
        echo "❌ Erro na emissão: " . $resultado['erro'];
    }
    
} catch (Exception $e) {
    echo "❌ Erro: " . $e->getMessage();
}

function salvarNFCeNoBanco($resultado) {
    // Implementar lógica de salvamento no banco
    // Exemplo com PDO:
    /*
    $pdo = new PDO('mysql:host=localhost;dbname=nfce', 'usuario', 'senha');
    $stmt = $pdo->prepare("INSERT INTO nfce (chave, protocolo, xml_autorizado, status) VALUES (?, ?, ?, 'autorizada')");
    $stmt->execute([$resultado['chave'], $resultado['protocolo'], $resultado['xml']]);
    */
}
?>

4. Tratamento de Erros Comuns

Erro Causa Solução
Certificate cannot be read Certificado inválido ou senha incorreta Verificar caminho e senha do certificado
SOAP-ERROR: Parsing WSDL Problema de conexão com SEFAZ Verificar internet e URL do webservice
cStat: 217 XML mal formado Validar contra schema XSD
cStat: 656 CNPJ não credenciado Credenciar empresa na SEFAZ
cStat: 403 Certificado inválido Verificar validade do certificado

🎯 Fluxo Completo de Emissão

  1. Configuração: Carregar certificado e configurações
  2. Montagem: Construir XML com dados da venda
  3. Assinatura: Assinar digitalmente o XML
  4. Validação: Validar contra schema XSD
  5. Transmissão: Enviar para SEFAZ
  6. Consulta: Consultar recibo de processamento
  7. Armazenamento: Salvar XML autorizado

⚠️ Próximos Passos

Este exemplo mostra a emissão básica. Em um sistema real, você precisará implementar:

  • Contingência para falhas de internet
  • Cancelamento de NFC-e
  • Inutilização de numeração
  • Consulta situação da NFC-e
  • Geração de DANFE NFC-e
  • Envio de email automático

👥 Cadastros Necessários para o Sistema

Para emitir NFC-e/NFe, seu sistema precisa ter cadastros organizados e completos. Veja as telas essenciais:

🏢 Cadastro do Emitente (Sua Empresa)

Necessário apenas uma vez - esses dados vão em todas as notas.

Campo Obrigatório Observação Exemplo
Razão Social Nome registrado no CNPJ EMPRESA EXEMPLO LTDA
Nome Fantasia Nome comercial LOJA EXEMPLO
CNPJ Somente números 12.345.678/0001-23
Inscrição Estadual Se contribuinte de ICMS 123.456.789.112
Inscrição Municipal ⛔/✅ Para NFSe ou se exigido 12345-6
Regime Tributário Simples Nacional, Lucro Presumido, Lucro Real Simples Nacional
Endereço Completo Logradouro, número, bairro, cidade, UF, CEP Rua Exemplo, 123, Centro
Certificado Digital A1 (.pfx) ou A3 (token) certificado.pfx
CSC e ID CSC (NFC-e) Exclusivo para NFC-e CSC: ABC123, ID: 1

📝 Exemplo de Estrutura de Dados:

{
  "empresa": {
    "razao_social": "EMPRESA EXEMPLO LTDA",
    "nome_fantasia": "LOJA EXEMPLO",
    "cnpj": "12345678000123",
    "ie": "123456789112",
    "regime_tributario": "1",
    "endereco": {
      "logradouro": "Rua Central",
      "numero": "100",
      "bairro": "Centro",
      "cidade": "Indaiatuba",
      "uf": "SP",
      "cep": "13330000"
    },
    "contato": {
      "telefone": "19999999999",
      "email": "contato@empresa.com.br"
    }
  }
}

👤 Cadastro de Clientes / Destinatários

Cada cliente precisa estar cadastrado para emissão correta da NFe.

Campo Obrigatório Observação NFe NFC-e
Tipo de Pessoa Física/Jurídica
Nome/Razão Social Nome completo
CNPJ/CPF Documento oficial
Inscrição Estadual ⛔/✅ Se contribuinte ICMS
Endereço Completo Para cálculo de impostos
Indicador de IE Contribuinte, Isento, Não Contribuinte
E-mail Para envio da DANFE

🎯 Diferenciação NFe vs NFC-e:

  • NFe: Cliente completo é obrigatório
  • NFC-e: Cliente pode ser "Consumidor não identificado"
  • NFC-e: CPF/CNPJ opcional (só se cliente quiser)

📦 Cadastro de Produtos

Produtos precisam ter todos os dados fiscais definidos, pois vão para o XML da NFe.

Campo Obrigatório Observação Exemplo
Código Interno Código único no seu sistema PROD001
Descrição do Produto Nome comercial Notebook Dell i7
NCM Classificação Fiscal (8 dígitos) 8471.30.10
CEST ⛔/✅ Obrigatório para produtos ST 01.001.00
CFOP padrão Geralmente 5.101/5.102 5102
Unidade de Medida UN, KG, MT, LT, etc. UN
Valor Unitário Preço de venda R$ 150,00
CST/CSOSN ICMS Depende do regime tributário 102 (Simples Nacional)
Alíquota de ICMS Se for contribuinte 18%
PIS/COFINS CST 01 (tributado) ou 06 (isento) 06
Origem da Mercadoria 0-Nacional, 1-Estrangeira, etc. 0 (Nacional)

⚠️ Atenção com Tributação:

Os campos fiscais (NCM, CST, alíquotas) devem ser preenchidos corretamente para evitar problemas com a SEFAZ.

⚙️ Configurações Fiscais e Parâmetros

Configurações gerais do sistema emissor.

📊 Numeração das Notas

  • Série: 1 (padrão)
  • Número Inicial: 1
  • Sequência: Automática
  • Modelo: 55 ou 65

🌐 Ambiente

  • Homologação: Para testes
  • Produção: Para uso real
  • Tipo de Emissão: Normal
  • Contingência: Offline (NFC-e)

🔐 Segurança

  • Certificado Digital: Caminho e senha
  • CSC NFC-e: Código e ID
  • Token SEFAZ: Se necessário

📋 Exemplo de Arquivo de Configuração (config.json):

{
  "atualizacao": "2025-09-25 10:00:00",
  "tpAmb": 2,
  "razaosocial": "EMPRESA EXEMPLO LTDA",
  "cnpj": "12345678000123",
  "siglaUF": "SP",
  "pathSalvar": "/var/www/nfe/arquivos/",
  "certPfx": "/var/www/nfe/certificado.pfx",
  "certPassword": "senha_secreta",
  "certPhrase": "",
  "CSC": "CODIGO_CSC_NFCE",
  "CSCid": "1",
  "aProxyConf": {
    "proxyIp": "",
    "proxyPort": "",
    "proxyUser": "",
    "proxyPass": ""
  }
}

📋 Resumo das Telas Necessárias

Tela Finalidade Obrigatória Complexidade
Emitente Dados da empresa Média
Clientes Cadastro de destinatários ✅ (NFe) / ⛔ (NFC-e) Média
Produtos Cadastro com dados fiscais Alta
CFOP/Natureza Operações fiscais Baixa
Configurações Parâmetros do sistema Média
Transportadoras Frete (opcional) Baixa

💡 Dicas de Implementação

  • Validação: Valide CNPJ/CPF, CEP, e-mails
  • Backup: Mantenha backup dos cadastros
  • Auditoria: Registre alterações importantes
  • Performance: Indexe campos de busca no banco
  • Segurança: Proteja dados sensíveis (certificado, CSC)

📄 Modelos de XML - NFe e NFC-e

Modelos completos de XML para NFe (modelo 55) e NFC-e (modelo 65) em ambiente de homologação.

📋 Modelo 55 – NFe Completa (Homologação)

Nota Fiscal Eletrônica padrão - utilizada para vendas não-presenciais.

XML - NFe Modelo 55
<?xml version="1.0" encoding="UTF-8"?>
<NFe xmlns="http://www.portalfiscal.inf.br/nfe">
  <infNFe Id="NFe35240912345678000123550010000001234567890123" versao="4.00">

    <!-- Identificação -->
    <ide>
      <cUF>35</cUF>
      <cNF>12345678</cNF>
      <natOp>VENDA DE MERCADORIA</natOp>
      <mod>55</mod>
      <serie>1</serie>
      <nNF>1234</nNF>
      <dhEmi>2025-09-24T16:00:00-03:00</dhEmi>
      <tpNF>1</tpNF>
      <idDest>1</idDest>
      <cMunFG>3520509</cMunFG>
      <tpImp>1</tpImp>
      <tpEmis>1</tpEmis>
      <cDV>3</cDV>
      <tpAmb>2</tpAmb>
      <finNFe>1</finNFe>
      <indFinal>1</indFinal>
      <indPres>1</indPres>
      <procEmi>0</procEmi>
      <verProc>1.0</verProc>
    </ide>

    <!-- Emitente -->
    <emit>
      <CNPJ>12345678000123</CNPJ>
      <xNome>EMPRESA EXEMPLO LTDA</xNome>
      <xFant>EMPRESA EXEMPLO</xFant>
      <enderEmit>
        <xLgr>Rua Central</xLgr>
        <nro>100</nro>
        <xBairro>Centro</xBairro>
        <cMun>3520509</cMun>
        <xMun>Indaiatuba</xMun>
        <UF>SP</UF>
        <CEP>13330000</CEP>
        <cPais>1058</cPais>
        <xPais>BRASIL</xPais>
        <fone>19999999999</fone>
      </enderEmit>
      <IE>123456789112</IE>
      <CRT>1</CRT>
    </emit>

    <!-- Destinatário -->
    <dest>
      <CPF>12345678901</CPF>
      <xNome>JOÃO DA SILVA</xNome>
      <enderDest>
        <xLgr>Av. Brasil</xLgr>
        <nro>500</nro>
        <xBairro>Jardim</xBairro>
        <cMun>3520509</cMun>
        <xMun>Indaiatuba</xMun>
        <UF>SP</UF>
        <CEP>13330000</CEP>
        <cPais>1058</cPais>
        <xPais>BRASIL</xPais>
        <fone>19988887777</fone>
      </enderDest>
      <indIEDest>9</indIEDest>
    </dest>

    <!-- Produto -->
    <det nItem="1">
      <prod>
        <cProd>001</cProd>
        <cEAN>SEM GTIN</cEAN>
        <xProd>Produto Exemplo</xProd>
        <NCM>39269090</NCM>
        <CFOP>5102</CFOP>
        <uCom>UN</uCom>
        <qCom>1.0000</qCom>
        <vUnCom>100.00</vUnCom>
        <vProd>100.00</vProd>
        <cEANTrib>SEM GTIN</cEANTrib>
        <uTrib>UN</uTrib>
        <qTrib>1.0000</qTrib>
        <vUnTrib>100.00</vUnTrib>
        <indTot>1</indTot>
      </prod>
      <imposto>
        <ICMS>
          <ICMSSN102>
            <orig>0</orig>
            <CSOSN>102</CSOSN>
          </ICMSSN102>
        </ICMS>
        <PIS>
          <PISNT><CST>06</CST></PISNT>
        </PIS>
        <COFINS>
          <COFINSNT><CST>06</CST></COFINSNT>
        </COFINS>
      </imposto>
    </det>

    <!-- Totais -->
    <total>
      <ICMSTot>
        <vBC>0.00</vBC>
        <vICMS>0.00</vICMS>
        <vICMSDeson>0.00</vICMSDeson>
        <vFCP>0.00</vFCP>
        <vBCST>0.00</vBCST>
        <vST>0.00</vST>
        <vFCPST>0.00</vFCPST>
        <vFCPSTRet>0.00</vFCPSTRet>
        <vProd>100.00</vProd>
        <vFrete>0.00</vFrete>
        <vSeg>0.00</vSeg>
        <vDesc>0.00</vDesc>
        <vII>0.00</vII>
        <vIPI>0.00</vIPI>
        <vIPIDevol>0.00</vIPIDevol>
        <vPIS>0.00</vPIS>
        <vCOFINS>0.00</vCOFINS>
        <vOutro>0.00</vOutro>
        <vNF>100.00</vNF>
      </ICMSTot>
    </total>

    <!-- Transporte -->
    <transp>
      <modFrete>9</modFrete>
    </transp>

    <!-- Pagamento -->
    <pag>
      <detPag>
        <tPag>01</tPag>
        <vPag>100.00</vPag>
      </detPag>
    </pag>

    <!-- Informações Adicionais -->
    <infAdic>
      <infCpl>Documento emitido em ambiente de homologação - SEM VALOR FISCAL</infCpl>
    </infAdic>

    <!-- Responsável Técnico -->
    <infRespTec>
      <CNPJ>12345678000123</CNPJ>
      <xContato>SUPORTE SISTEMA</xContato>
      <email>suporte@empresa.com.br</email>
      <fone>19999999999</fone>
    </infRespTec>

  </infNFe>
</NFe>
Baixar XML - Modelo 55

🎯 Características do Modelo 55 (NFe):

  • Mod: 55
  • Uso: Vendas não-presenciais (e-commerce, faturamento)
  • Destinatário: Obrigatório com dados completos
  • DANFE: Impressão obrigatória em alguns casos
  • Validação: Mais rigorosa que NFC-e

🛍️ Modelo 65 – NFC-e Completa (Homologação)

Nota Fiscal do Consumidor Eletrônica - para vendas presenciais.

XML - NFC-e Modelo 65
<?xml version="1.0" encoding="UTF-8"?>
<NFe xmlns="http://www.portalfiscal.inf.br/nfe">
  <infNFe Id="NFe35240912345678000123650010000001234567890123" versao="4.00">

    <!-- Identificação -->
    <ide>
      <cUF>35</cUF>
      <cNF>87654321</cNF>
      <natOp>VENDA AO CONSUMIDOR</natOp>
      <mod>65</mod>
      <serie>1</serie>
      <nNF>2345</nNF>
      <dhEmi>2025-09-24T16:00:00-03:00</dhEmi>
      <tpNF>1</tpNF>
      <idDest>1</idDest>
      <cMunFG>3520509</cMunFG>
      <tpImp>4</tpImp>
      <tpEmis>1</tpEmis>
      <cDV>3</cDV>
      <tpAmb>2</tpAmb>
      <finNFe>1</finNFe>
      <indFinal>1</indFinal>
      <indPres>1</indPres>
      <procEmi>0</procEmi>
      <verProc>1.0</verProc>
    </ide>

    <!-- Emitente -->
    <emit>
      <CNPJ>12345678000123</CNPJ>
      <xNome>EMPRESA EXEMPLO LTDA</xNome>
      <xFant>EMPRESA EXEMPLO</xFant>
      <enderEmit>
        <xLgr>Rua Central</xLgr>
        <nro>100</nro>
        <xBairro>Centro</xBairro>
        <cMun>3520509</cMun>
        <xMun>Indaiatuba</xMun>
        <UF>SP</UF>
        <CEP>13330000</CEP>
        <cPais>1058</cPais>
        <xPais>BRASIL</xPais>
        <fone>19999999999</fone>
      </enderEmit>
      <IE>123456789112</IE>
      <CRT>1</CRT>
    </emit>

    <!-- Destinatário (opcional na NFC-e) -->
    <dest>
      <xNome>CONSUMIDOR NÃO IDENTIFICADO</xNome>
    </dest>

    <!-- Produto -->
    <det nItem="1">
      <prod>
        <cProd>001</cProd>
        <cEAN>SEM GTIN</cEAN>
        <xProd>Produto Teste NFCe</xProd>
        <NCM>39269090</NCM>
        <CFOP>5102</CFOP>
        <uCom>UN</uCom>
        <qCom>1.0000</qCom>
        <vUnCom>50.00</vUnCom>
        <vProd>50.00</vProd>
        <cEANTrib>SEM GTIN</cEANTrib>
        <uTrib>UN</uTrib>
        <qTrib>1.0000</qTrib>
        <vUnTrib>50.00</vUnTrib>
        <indTot>1</indTot>
      </prod>
      <imposto>
        <ICMS>
          <ICMSSN102>
            <orig>0</orig>
            <CSOSN>102</CSOSN>
          </ICMSSN102>
        </ICMS>
        <PIS><PISNT><CST>06</CST></PISNT></PIS>
        <COFINS><COFINSNT><CST>06</CST></COFINSNT></COFINS>
      </imposto>
    </det>

    <!-- Totais -->
    <total>
      <ICMSTot>
        <vBC>0.00</vBC>
        <vICMS>0.00</vICMS>
        <vProd>50.00</vProd>
        <vNF>50.00</vNF>
      </ICMSTot>
    </total>

    <!-- Transporte -->
    <transp>
      <modFrete>9</modFrete>
    </transp>

    <!-- Pagamento -->
    <pag>
      <detPag>
        <tPag>01</tPag>
        <vPag>50.00</vPag>
      </detPag>
    </pag>

    <!-- Informações Suplementares: QRCode -->
    <infNFeSupl>
      <qrCode>
        https://www.sefaz.sp.gov.br/nfce/qrcode?p=35240912345678000123650010000001234567890123|2|1|XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
      </qrCode>
    </infNFeSupl>

    <infRespTec>
      <CNPJ>12345678000123</CNPJ>
      <xContato>SUPORTE SISTEMA</xContato>
      <email>suporte@empresa.com.br</email>
      <fone>19999999999</fone>
    </infRespTec>

  </infNFe>
</NFe>
Baixar XML - Modelo 65

🎯 Características do Modelo 65 (NFC-e):

  • Mod: 65
  • Uso: Vendas presenciais (balcão, loja física)
  • Destinatário: Opcional (pode ser consumidor não identificado)
  • QR Code: Obrigatório para consulta
  • DANFE: Formato reduzido, não obrigatório impressão
  • CSC: Código específico para assinar QR Code

✅ Modelos de Notas Autorizadas (com Protocolo)

Estrutura completa de notas após autorização da SEFAZ, incluindo o protocolo.

XML - NFe Autorizada com Protocolo
<?xml version="1.0" encoding="UTF-8"?>
<nfeProc xmlns="http://www.portalfiscal.inf.br/nfe" versao="4.00">

  <!-- NFe completa -->
  <NFe xmlns="http://www.portalfiscal.inf.br/nfe">
    <infNFe Id="NFe35240912345678000123550010000001234567890123" versao="4.00">
      <!-- Conteúdo completo da NFe -->
    </infNFe>
  </NFe>

  <!-- Protocolo de Autorização -->
  <protNFe versao="4.00">
    <infProt>
      <tpAmb>2</tpAmb>
      <verAplic>SP_NFE_4.0</verAplic>
      <chNFe>35240912345678000123550010000001234567890123</chNFe>
      <dhRecbto>2025-09-24T16:05:00-03:00</dhRecbto>
      <nProt>135220000000000</nProt>
      <digVal>Wm9tQWRpZ0hhc2hEYURpZ0hhc2hEYQ==</digVal>
      <cStat>100</cStat>
      <xMotivo>Autorizado o uso da NF-e</xMotivo>
    </infProt>
  </protNFe>

</nfeProc>
XML - NFC-e Autorizada com Protocolo
<?xml version="1.0" encoding="UTF-8"?>
<nfeProc xmlns="http://www.portalfiscal.inf.br/nfe" versao="4.00">

  <!-- NFC-e completa -->
  <NFe xmlns="http://www.portalfiscal.inf.br/nfe">
    <infNFe Id="NFe35240912345678000123650010000001234567890123" versao="4.00">
      <!-- Conteúdo completo da NFC-e -->
    </infNFe>
  </NFe>

  <!-- Protocolo de Autorização -->
  <protNFe versao="4.00">
    <infProt>
      <tpAmb>2</tpAmb>
      <verAplic>SP_NFCE_4.0</verAplic>
      <chNFe>35240912345678000123650010000001234567890123</chNFe>
      <dhRecbto>2025-09-24T16:05:00-03:00</dhRecbto>
      <nProt>135220000000001</nProt>
      <digVal>VmFsZURpZ0hhc2hEYURpZ0hhc2hEYQ==</digVal>
      <cStat>100</cStat>
      <xMotivo>Autorizado o uso da NFC-e</xMotivo>
    </infProt>
  </protNFe>

</nfeProc>

📊 Status de Autorização (cStat):

Código Status Significado Ação
100 AUTORIZADA Nota autorizada com sucesso Armazenar XML completo
101 CANCELADA Nota cancelada Manter para auditoria
110 DENEGADA SEFAZ negou autorização Verificar problemas cadastrais
2xx REJEITADA Erro no XML ou dados Corrigir e reenviar

📊 Diferenças entre NFe e NFC-e

Característica NFe (Modelo 55) NFC-e (Modelo 65)
Finalidade Vendas não-presenciais Vendas presenciais
Destinatário Obrigatório com dados completos Opcional (consumidor não identificado)
DANFE Impressão obrigatória em alguns casos Não obrigatório, formato reduzido
QR Code Não utiliza Obrigatório para consulta
CSC Não utiliza Obrigatório para assinar QR Code
Validação Mais rigorosa Mais simplificada
Forma de Emissão Webservice normal Webservice específico NFC-e
Contingência FS-DA, EPEC, etc. Offline (limite de valor)

✅ Quando usar NFe (55)

  • E-commerce e vendas online
  • Faturamento para empresas
  • Vendas para outros estados
  • Produtos com controle especial
  • Quando precisa de dados completos do cliente

🛍️ Quando usar NFC-e (65)

  • Vendas em balcão/loja física
  • Restaurantes e food service
  • Varejo em geral
  • Quando o cliente não fornece dados
  • Agilidade no processo de venda

⚠️ Importante:

Não é possível converter NFe em NFC-e ou vice-versa. A escolha do modelo deve ser feita no momento da emissão baseada na operação comercial.

🔧 Ferramentas Úteis

🔍 Consultas Públicas

📚 Documentação Oficial

💡 Considerações Finais e Melhores Práticas

Desenvolver um emissor de NFC-e/NFe é um projeto complexo que requer atenção a detalhes técnicos e legais. Aqui estão as considerações finais para seu sucesso.

🎯 Pontos Críticos de Atenção

📚 Conhecimento Multidisciplinar

A SPED PHP é uma ferramenta, não uma solução completa. Você precisa entender:

  • Legislação fiscal atualizada
  • Regimes tributários (Simples, Lucro Presumido, etc.)
  • Especificações técnicas da SEFAZ
  • Protocolos de segurança e certificação digital

⚖️ Responsabilidade Fiscal

Você é responsável pela correta tributação. A biblioteca apenas comunica com a SEFAZ.

  • Valide cálculos com um contador
  • Mantenha-se atualizado com mudanças legais
  • Implemente auditoria e logs detalhados

🏛️ Variações Estaduais

Cada estado tem particularidades:

  • Prazos diferentes para cancelamento
  • URLs específicas de webservice
  • Regras de contingência variadas
  • Limites de valor para emissão offline

🛠️ Arquitetura Recomendada para Produção

1. Ambiente de Homologação Sólido

NUNCA emita notas sem testar exaustivamente!

  • Configure ambiente idêntico à produção
  • Teste todos os cenários possíveis
  • Valide com dados reais da empresa
  • Simule falhas e contingências

2. Tratamento Robusto de Erros

Implemente um sistema completo de tratamento de erros:

  • Logs detalhados de todas as operações
  • Tratamento específico para cada código SEFAZ
  • Retentativas automáticas para falhas temporárias
  • Notificações em tempo real para problemas críticos

3. Segurança em Primeiro Lugar

Proteja os dados sensíveis do sistema:

  • Certificado A1: Armazene em local seguro com permissões restritas
  • Certificado A3: Use HSM ou token físico
  • CSC NFC-e: Nunca em código-fonte, use variáveis de ambiente
  • XMLs: Criptografe em repouso e em trânsito

4. Performance e Escalabilidade

Otimize para múltiplas emissões simultâneas:

  • Use cache para dados mestres (produtos, clientes)
  • Implemente filas para processamento assíncrono
  • Otimize consultas ao banco de dados
  • Considere balanceamento de carga para alta demanda

🔧 Checklist para Ir para Produção

Item Status Verificação
Certificado Digital Válido, do tipo A1 ou A3, com CNPJ da empresa
Credenciamento SEFAZ Empresa credenciada para NFC-e no estado
Ambiente Homologação Testado exaustivamente por pelo menos 2 semanas
CSC NFC-e Configurado e testado no ambiente de produção
Backup e Recovery Procedimentos de backup testados e documentados
Contingência Sistema de contingência implementado e testado
Validação Contábil Cálculos validados por profissional contábil

🚨 Erros Comuns e Suas Soluções

Sintomas: Erros 403, "Certificate cannot be read"

  • Verifique a senha: Use o mesmo certificado no site da SEFAZ
  • Validade: Certificado deve estar dentro do prazo
  • Formato A1: Use .pfx com senha correta
  • Formato A3: Configure driver e pin corretamente

Sintomas: Timeouts, erros SOAP, conexão recusada

  • Firewall: Libere portas 443 e 8443
  • Proxy: Configure se necessário
  • DNS: Verifique resolução dos domínios SEFAZ
  • Certificado SSL: Atualize cadeia de certificados

Sintomas: Erros 217, 214, rejeição por schema

  • XSD: Use schemas atualizados da SEFAZ
  • Encoding: Garanta UTF-8 em todo o processo
  • Tags obrigatórias: Verifique todas as tags requeridas
  • Formatação: Valide números e datas corretamente

Sintomas: Erros 506, 578, 656, rejeição por regra de negócio

  • Numeração: Controle sequência corretamente
  • Cálculos: Verifique totais e impostos
  • Credenciamento: Empresa deve estar habilitada
  • CNPJ: Verifique situação cadastral

🔗 Recursos e Suporte

👥 Comunidade e Suporte

🔧 Ferramentas de Desenvolvimento

📚 Documentação Oficial

⚠️ Aviso Legal Importante

Este guia desenvovido pela ferramentas da web tem propósitos educacionais e de desenvolvimento. A implementação em ambiente de produção deve ser realizada por profissionais qualificados com amplo conhecimento da legislação fiscal brasileira. Sempre consulte um contador ou especialista fiscal antes de colocar qualquer sistema emissor em produção.

O desenvolvedor é integralmente responsável pela correta implementação e conformidade fiscal do sistema.

🎉 Próximos Passos Recomendados

  1. Estudo Profundo: Domine a legislação fiscal e técnica
  2. Ambiente de Testes: Configure homologação completa
  3. Desenvolvimento Iterativo: Implemente funcionalidades gradualmente
  4. Validação Contábil: Teste com profissional da área
  5. Migração Controlada: Transição gradual para produção
  6. Monitoramento Contínuo: Mantenha-se atualizado com mudanças

🚀 Bom trabalho e sucesso no seu projeto!