NFEEmissor 0.3.3

dotnet add package NFEEmissor --version 0.3.3
                    
NuGet\Install-Package NFEEmissor -Version 0.3.3
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="NFEEmissor" Version="0.3.3" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="NFEEmissor" Version="0.3.3" />
                    
Directory.Packages.props
<PackageReference Include="NFEEmissor" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add NFEEmissor --version 0.3.3
                    
#r "nuget: NFEEmissor, 0.3.3"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package NFEEmissor@0.3.3
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=NFEEmissor&version=0.3.3
                    
Install as a Cake Addin
#tool nuget:?package=NFEEmissor&version=0.3.3
                    
Install as a Cake Tool

Logo

NuGet Downloads Build Publish License

Emissor NF-e em .NET para geração, assinatura, autorização em homologação/produção, eventos fiscais, consulta SEFAZ e DANFE, com API stateless, CLI e pacotes NuGet.

Status: projeto em evolução. A emissão em homologação e produção já foram testadas, mas o uso em produção exige validação fiscal, jurídica e operacional no cenário da sua empresa.

Leia Antes De Usar

Sobre a responsabilidade pelo uso

Este projeto nasceu de uma necessidade real e foi construído com cuidado, mas NF-e é um ecossistema complexo. Regras tributárias mudam, cada UF tem suas peculiaridades, cada regime fiscal tem suas exigências, e cada empresa tem um cenário diferente dos demais.

Antes de usar em produção: teste muito. Valide no ambiente de homologação da SEFAZ. Revise os XMLs gerados com alguém que entenda do processo fiscal da sua empresa.

A legislação, as regras de CSOSN/CST, os parâmetros de ICMS, PIS e COFINS variam por UF, regime tributário e atividade econômica, e essa variação é sua responsabilidade conhecer e configurar corretamente.

Ao usar este projeto, você assume total responsabilidade pelos documentos emitidos. O autor disponibiliza o código de boa-fé, mas não presta suporte fiscal nem se responsabiliza por erros, rejeições ou penalidades.

O que este projeto faz

Este projeto emite NF-e modelo 55 usando .NET, certificado digital A1 e webservices da SEFAZ.

Ele possui:

  • Nfe.Api: API HTTP para emissão assíncrona, eventos fiscais, consulta de status e consulta da chave na SEFAZ.
  • Nfe.Core: geração de XML, assinatura digital, envio para SEFAZ, eventos e validações.
  • Nfe.Cli: utilitário local para gerar e assinar XML de NF-e, eventos e inutilização sem enviar para a SEFAZ.

Dependências principais:

  • NFEConsulta: usada para consulta de status do serviço e consulta de NF-e pela chave de acesso.
  • NFEDanfe: usada para geração de DANFE em PDF a partir de XML autorizado (procNFe.xml).
  • NFeSchemaDownloader: usada pela API para sincronizar schemas XSD oficiais quando necessário.

Pacotes NuGet

O empacotamento é separado por responsabilidade:

  • NFEEmissor: biblioteca principal para geração, assinatura e autorização.
  • NFEEmissor.Cli: ferramenta dotnet tool com o comando nfe-emissor para gerar XML assinado localmente.

Nfe.Api não é empacotado como NuGet; ele é uma aplicação HTTP para rodar via Docker ou publicação própria.

Para empacotar localmente:

dotnet pack NfeEmissor.Packages.slnx -o ./artifacts/packages

Para instalar o CLI como tool a partir de um pacote local:

dotnet tool install --global NFEEmissor.Cli \
  --add-source ./artifacts/packages \
  --version 0.3.2

Depois de instalado:

nfe-emissor --help

Quando os pacotes estiverem publicados no NuGet:

dotnet add package NFEEmissor --version 0.3.2
dotnet tool install --global NFEEmissor.Cli --version 0.3.2

Licença: MIT.

Requisitos

  • Docker e Docker Compose.
  • Certificado digital A1 em PEM ou PFX.
  • Dados fiscais reais e coerentes com o certificado.

Os certificados devem ficar em certs/. Essa pasta é ignorada pelo Git.

Exemplo esperado:

certs/cert.pem
certs/key.pem
certs/cert.pfx

Subindo a API

docker compose up -d --build

A API fica disponível em:

http://localhost:5000

Serviços auxiliares:

  • Redis: localhost:6379
  • Seq: http://localhost:8085

Healthcheck:

curl -sS "http://localhost:5000/health"

Modelo stateless

A API foi desenhada para não ser o repositório definitivo dos documentos fiscais.

  • Não há banco de dados obrigatório.
  • Redis é usado apenas para fila, idempotência curta, backoff temporário da SEFAZ e status com TTL.
  • Certificados e senhas colocados na fila Redis são protegidos com AES-256-GCM antes de serem serializados.
  • O status retorna o xmlResult (procNFe.xml) e, quando solicitado, danfePdfBase64.
  • A aplicação cliente deve persistir o XML autorizado e o DANFE em seu próprio storage, banco, disco, S3/MinIO ou sistema fiscal.
  • Para integrar persistência sem mudar o fluxo da API, implemente INfeStorage. A implementação padrão é NoopNfeStorage, que não grava nada.

Por padrão, o resultado temporário expira em 12 horas. Depois disso, a API pode retornar 404 para o correlationId.

Para produção ou múltiplas réplicas da API, configure uma chave compartilhada para proteger as credenciais temporárias da fila:

export Nfe__QueueProtectionKey="use-um-segredo-com-pelo-menos-32-caracteres"

Sem essa configuração, a aplicação usa uma chave aleatória local gerada ao iniciar o processo. Isso é suficiente para desenvolvimento em uma única instância, mas mensagens antigas da fila não poderão ser processadas após restart.

API HTTP

Os exemplos abaixo usam http://localhost:5000 e cobrem os principais endpoints:

  • POST /api/v1/nfe/emitir
  • GET /api/v1/nfe/status/{correlationId}
  • GET /api/v1/nfe/consulta
  • GET /api/v1/nfe/status-servico
  • POST /api/v1/nfe/cancelar
  • POST /api/v1/nfe/cce
  • POST /api/v1/nfe/inutilizar
  • POST /api/v1/certificado/info
  • GET /health
  • GET /api/v1/nfe/schemas

Emitindo uma NF-e

Use o arquivo nota-teste.json como base. Em homologação, mantenha:

{
  "ambienteEmissao": "2",
  "destinatario": {
    "nomeRazaoSocial": "NF-E EMITIDA EM AMBIENTE DE HOMOLOGACAO - SEM VALOR FISCAL"
  }
}

Emitir usando certificado PEM

CERT=$(base64 -w0 certs/cert.pem)
KEY=$(base64 -w0 certs/key.pem)

curl -sS -X POST "http://localhost:5000/api/v1/nfe/emitir?gerarDanfe=false" \
  -H "Content-Type: application/json" \
  -H "X-Cert-Pem-Base64: $CERT" \
  -H "X-Key-Pem-Base64: $KEY" \
  --data-binary @nota-teste.json

Resposta esperada:

{
  "correlationId": "3f8a5d63ad894b998b810e509fdf9c4c",
  "status": "Pendente",
  "message": "A nota fiscal foi colocada na fila de processamento."
}

Emitir usando certificado PFX

CERT=$(base64 -w0 certs/cert.pfx)

curl -sS -X POST "http://localhost:5000/api/v1/nfe/emitir?gerarDanfe=false" \
  -H "Content-Type: application/json" \
  -H "X-Certificado-Base64: $CERT" \
  -H "X-Certificado-Senha: sua-senha" \
  --data-binary @nota-teste.json

Consultando o status local da emissão

Depois de emitir, consulte pelo correlationId retornado:

curl -sS "http://localhost:5000/api/v1/nfe/status/3f8a5d63ad894b998b810e509fdf9c4c"

Resposta autorizada:

{
  "correlationId": "3f8a5d63ad894b998b810e509fdf9c4c",
  "status": "Autorizada",
  "chaveAcesso": "35260612345678000195550010000000011000000010",
  "protocolo": "135000000000000",
  "xmlResult": "<?xml version=\"1.0\" encoding=\"utf-8\"?><nfeProc ...",
  "danfePdfBase64": "JVBERi0xLjQK...",
  "expiraEm": "2026-06-25T18:00:00+00:00",
  "ttlSegundos": 43200,
  "storage": {
    "persistido": false,
    "xmlProcNfeUri": null,
    "danfePdfUri": null
  }
}

Salve xmlResult como procNFe.xml. Se danfePdfBase64 vier preenchido, decodifique o Base64 e salve como PDF.

Consultando a chave direto na SEFAZ

Use o endpoint de consulta quando você já tiver uma chave NF-e de 44 dígitos.

Consulta em homologação com PEM

CERT=$(base64 -w0 certs/cert.pem)
KEY=$(base64 -w0 certs/key.pem)

curl -sS "http://localhost:5000/api/v1/nfe/consulta?chave=35260612345678000195550010000000011000000010&uf=SP&ambiente=2" \
  -H "X-Cert-Pem-Base64: $CERT" \
  -H "X-Key-Pem-Base64: $KEY"

Resposta:

{
  "status": "100",
  "motivo": "Autorizado o uso da NF-e",
  "protocolo": "135000000000000",
  "xmlRetorno": null
}

Consulta em produção

Troque ambiente=2 por ambiente=1:

curl -sS "http://localhost:5000/api/v1/nfe/consulta?chave=SUA_CHAVE&uf=SP&ambiente=1" \
  -H "X-Cert-Pem-Base64: $CERT" \
  -H "X-Key-Pem-Base64: $KEY"

Consultando status do serviço SEFAZ

CERT=$(base64 -w0 certs/cert.pfx)

curl -sS "http://localhost:5000/api/v1/nfe/status-servico?uf=SP&ambiente=2" \
  -H "X-Certificado-Base64: $CERT" \
  -H "X-Certificado-Senha: sua-senha"

Se preferir PEM, o endpoint também aceita X-Cert-Pem-Base64 e X-Key-Pem-Base64 no lugar do PFX.

Cancelamento, CC-e e inutilização

Os eventos fiscais usam os mesmos headers de certificado da emissão e consulta. A API aceita PFX:

CERT=$(base64 -w0 certs/cert.pfx)

Ou PEM:

CERT=$(base64 -w0 certs/cert.pem)
KEY=$(base64 -w0 certs/key.pem)

Cancelar NF-e

Use o cancelamento quando a NF-e já foi autorizada e ainda está dentro das regras/prazo da SEFAZ.

curl -sS -X POST "http://localhost:5000/api/v1/nfe/cancelar" \
  -H "Content-Type: application/json" \
  -H "X-Certificado-Base64: $CERT" \
  -H "X-Certificado-Senha: sua-senha" \
  -d '{
    "ambiente": "2",
    "uf": "SP",
    "chaveAcesso": "35260612345678000195550010000000011000000010",
    "cnpjEmitente": "12345678000195",
    "protocoloAutorizacao": "135000000000000",
    "justificativa": "Erro operacional identificado apos autorizacao"
  }'

Resposta autorizada:

{
  "status": "135",
  "motivo": "Evento registrado e vinculado a NF-e",
  "chaveAcesso": "35260612345678000195550010000000011000000010",
  "tipoEvento": "110111",
  "sequenciaEvento": 1,
  "protocolo": "135000000000001",
  "xmlProcEventoNfe": "<procEventoNFe ..."
}

Carta de Correção Eletrônica

Use CC-e apenas para correções permitidas pela legislação. Ela não pode corrigir valores de imposto, remetente/destinatário, data de emissão ou saída.

curl -sS -X POST "http://localhost:5000/api/v1/nfe/cce" \
  -H "Content-Type: application/json" \
  -H "X-Cert-Pem-Base64: $CERT" \
  -H "X-Key-Pem-Base64: $KEY" \
  -d '{
    "ambiente": "2",
    "uf": "SP",
    "chaveAcesso": "35260612345678000195550010000000011000000010",
    "cnpjEmitente": "12345678000195",
    "sequenciaEvento": 1,
    "correcao": "Correção do texto das informações adicionais da nota fiscal"
  }'

Inutilizar numeração

Use inutilização para comunicar uma quebra de sequência de numeração que não será usada.

curl -sS -X POST "http://localhost:5000/api/v1/nfe/inutilizar" \
  -H "Content-Type: application/json" \
  -H "X-Certificado-Base64: $CERT" \
  -H "X-Certificado-Senha: sua-senha" \
  -d '{
    "ambiente": "2",
    "uf": "SP",
    "cnpjEmitente": "12345678000195",
    "ano": "2026",
    "modelo": "55",
    "serie": "1",
    "numeroInicial": 10,
    "numeroFinal": 12,
    "justificativa": "Quebra de sequência por erro operacional interno"
  }'

Resposta autorizada:

{
  "status": "102",
  "motivo": "Inutilizacao de numero homologado",
  "uf": "35",
  "ano": "26",
  "cnpjEmitente": "12345678000195",
  "serie": "1",
  "numeroInicial": 10,
  "numeroFinal": 12,
  "protocolo": "135000000000002"
}

Lendo informações do certificado

CERT=$(base64 -w0 certs/cert.pfx)

curl -sS -X POST "http://localhost:5000/api/v1/certificado/info" \
  -H "X-Certificado-Base64: $CERT" \
  -H "X-Certificado-Senha: sua-senha"

Gerando XML assinado sem enviar para a SEFAZ

Use o CLI quando quiser apenas gerar e assinar o XML localmente.

Com PEM:

docker run --rm \
  -v "$PWD:/src" \
  -w /src \
  mcr.microsoft.com/dotnet/sdk:10.0 \
  dotnet run --project src/Nfe.Cli/Nfe.Cli.csproj -- \
    emitir \
    --json nota-teste.json \
    --cert certs/cert.pem \
    --key certs/key.pem \
    --output-dir out

Com PFX:

docker run --rm \
  -v "$PWD:/src" \
  -w /src \
  mcr.microsoft.com/dotnet/sdk:10.0 \
  dotnet run --project src/Nfe.Cli/Nfe.Cli.csproj -- \
    emitir \
    --json nota-teste.json \
    --cert certs/cert.pfx \
    --senha sua-senha \
    --output-dir out

O XML assinado será salvo em out/.

O CLI também gera XML assinado de eventos e inutilização sem enviar para a SEFAZ:

dotnet run --project src/Nfe.Cli/Nfe.Cli.csproj -- \
  cancelar \
  --json cancelamento.json \
  --cert certs/cert.pfx \
  --senha sua-senha \
  --output-dir out

dotnet run --project src/Nfe.Cli/Nfe.Cli.csproj -- \
  cce \
  --json cce.json \
  --cert certs/cert.pem \
  --key certs/key.pem \
  --output-dir out

dotnet run --project src/Nfe.Cli/Nfe.Cli.csproj -- \
  inutilizar \
  --json inutilizacao.json \
  --cert certs/cert.pfx \
  --senha sua-senha \
  --output-dir out

Gerando DANFE em PDF

Use um XML autorizado/processado (*-procNFe.xml). XML apenas assinado, sem protocolo de autorização, não é suficiente para um DANFE fiscalmente válido.

Na API, informe gerarDanfe=true ao emitir:

curl -sS -X POST "http://localhost:5000/api/v1/nfe/emitir?gerarDanfe=true" \
  -H "Content-Type: application/json" \
  -H "X-Cert-Pem-Base64: $CERT" \
  -H "X-Key-Pem-Base64: $KEY" \
  --data-binary @nota-teste.json

O status retornará danfePdfBase64. Decodifique esse valor e salve como PDF na aplicação cliente.

A geração de PDF usa QuestPDF por meio da dependência NFEDanfe; o projeto configura a licença como LicenseType.Community antes de gerar o PDF:

QuestPDF.Settings.License = LicenseType.Community;

O pacote NFEEmissor.Cli não inclui geração de DANFE para evitar um pacote de ferramenta muito grande. Use a API ou a dependência NFEDanfe diretamente para DANFE.

CNPJ alfanumérico e Reforma Tributária

O projeto aceita CNPJ com letras, preservando os 14 caracteres alfanuméricos no XML e na chave de acesso. Pontuação é removida automaticamente:

{
  "cnpj": "12.ABC.345/0001-88"
}

Também há suporte inicial ao grupo IBSCBS nos impostos do item. O projeto escreve os campos informados e agrega os totais em IBSCBSTot, mas não calcula automaticamente enquadramento, CST, cClassTrib ou alíquotas. Esses valores devem vir do sistema fiscal/tributário do emissor.

O validador XSD pode ser apontado para pacotes de schema mais recentes, como PL_010C/CNPJ Alfa, por configuração:

export Nfe__SchemasPath="/caminho/para/schemas/v4"
export Nfe__TiposBasicosSchema="tiposBasico_PL_010C_v1.30.xsd"
export Nfe__NfeSchema="nfe_PL_010C_v1.30.xsd"
export Nfe__ValidateXsdBeforeSend="true"

Se os nomes não forem informados, o projeto tenta descobrir automaticamente tiposBasico*.xsd e nfe_v*.xsd no diretório configurado.

Na API, Nfe__ValidateXsdBeforeSend vem habilitado por padrão. Se os schemas não estiverem disponíveis ou o XML não validar, a NF-e não é assinada nem enviada para a SEFAZ. Para diagnosticar quais schemas foram carregados:

curl -sS "http://localhost:5000/api/v1/nfe/schemas"

No CLI, a validação XSD é explícita:

nfe-emissor emitir \
  --json nota-teste.json \
  --cert certs/cert.pfx \
  --senha sua-senha \
  --validar-xsd \
  --schemas-path schemas/v4 \
  --tipos-basicos-schema tiposBasico_PL_010C_v1.30.xsd \
  --nfe-schema nfe_PL_010C_v1.30.xsd

Exemplo:

{
  "impostos": {
    "ibsCbs": {
      "cst": "410",
      "codigoClassificacaoTributaria": "410999",
      "baseCalculo": 100.0,
      "ibsUf": {
        "aliquota": 0.1,
        "valor": 0.1
      },
      "ibsMunicipio": {
        "aliquota": 0.0,
        "valor": 0.0
      },
      "cbs": {
        "aliquota": 0.9,
        "valor": 0.9
      }
    }
  }
}

GTIN

Quando codigoEan ou codigoEanTributavel forem informados, o projeto valida GTIN-8, GTIN-12, GTIN-13 ou GTIN-14 pelo dígito verificador antes de gerar o XML. Quando o produto não possuir GTIN, omita o campo ou informe SEM GTIN.

Exemplo:

{
  "codigoEan": "7891234567895",
  "codigoEanTributavel": "7891234567895"
}

Exemplo mínimo de payload

{
  "ambienteEmissao": "2",
  "serie": "1",
  "numeroNfe": 8,
  "naturezaOperacao": "VENDA DE MERCADORIA",
  "tipoOperacao": "1",
  "formatoImpressaoDanfe": "1",
  "tipoEmissao": "1",
  "finalidadeEmissao": "1",
  "consumidorFinal": "1",
  "indicadorPresencaComprador": "9",
  "emitente": {
    "cnpj": "12345678000195",
    "razaoSocial": "EMPRESA EMITENTE TESTE LTDA",
    "nomeFantasia": "EMPRESA EMITENTE TESTE LTDA",
    "inscricaoEstadual": "110042490114",
    "cnaeFiscal": "2500000",
    "codigoRegimeTributario": "3",
    "endereco": {
      "logradouro": "RUA TESTE",
      "numero": "100",
      "bairro": "CENTRO",
      "codigoMunicipio": "3547809",
      "nomeMunicipio": "SAO PAULO",
      "uf": "SP",
      "cep": "01001000",
      "codigoPais": "1058",
      "nomePais": "BRASIL"
    }
  },
  "destinatario": {
    "cnpj": "99999999000191",
    "nomeRazaoSocial": "NF-E EMITIDA EM AMBIENTE DE HOMOLOGACAO - SEM VALOR FISCAL",
    "indicadorIe": "9",
    "endereco": {
      "logradouro": "AVENIDA CLIENTE",
      "numero": "200",
      "bairro": "JARDINS",
      "codigoMunicipio": "3550308",
      "nomeMunicipio": "SAO PAULO",
      "uf": "SP",
      "cep": "02002000",
      "codigoPais": "1058",
      "nomePais": "Brasil"
    }
  },
  "produtos": [
    {
      "codigoProduto": "EB.007",
      "descricao": "CACAMBA No2 METALICA ONDULADA 1040X959X660 VW.00001 TARA 70KG",
      "ncmSh": "73090090",
      "cfop": "5102",
      "unidadeComercial": "PC",
      "quantidadeComercial": 3.0,
      "valorUnitarioComercial": 500.0,
      "valorBruto": 1500.0,
      "unidadeTributavel": "PC",
      "quantidadeTributavel": 3.0,
      "valorUnitarioTributavel": 500.0,
      "indicadorComposicaoTotal": "1",
      "impostos": {
        "icms": {
          "cst": "00",
          "origem": "0",
          "baseCalculo": 1500.0,
          "aliquota": 18.0,
          "valor": 270.0
        },
        "pis": {
          "cst": "01",
          "baseCalculo": 1500.0,
          "aliquota": 1.65,
          "valor": 24.75
        },
        "cofins": {
          "cst": "01",
          "baseCalculo": 1500.0,
          "aliquota": 7.6,
          "valor": 114.0
        }
      }
    }
  ],
  "transporte": {
    "modalidadeFrete": "9"
  },
  "pagamentos": [
    {
      "meioPagamento": "15",
      "valor": 1500.0
    }
  ]
}

Observações importantes

  • ambienteEmissao: 1 para produção, 2 para homologação.
  • indicadorComposicaoTotal: 1 compõe o total da NF-e, 0 não compõe.
  • Em homologação, a razão social do destinatário deve ser NF-E EMITIDA EM AMBIENTE DE HOMOLOGACAO - SEM VALOR FISCAL.
  • CST com benefício fiscal pode exigir cBenef, conforme regra da UF.
  • O projeto aplica backoff temporário quando a SEFAZ retorna 656 - Consumo Indevido.
  • certs/, out/, tmp-nfe-out/, schemas/ e *-procNFe.xml são ignorados pelo Git.

🔗 Projetos relacionados

Projeto Descrição
NFeSchemaDownloader Mantém os Schemas XML (XSD) da SEFAZ sempre atualizados automaticamente
NFEConsulta Consulta NF-e, valida XML e verifica status oficial da SEFAZ
NFEDanfe Biblioteca .NET para gerar DANFE em PDF a partir de XML de NF-e autorizada.

Testes

docker run --rm \
  -v "$PWD:/src" \
  -w /src \
  mcr.microsoft.com/dotnet/sdk:10.0 \
  dotnet test tests/Nfe.UnitTests/Nfe.UnitTests.csproj

👨‍💻 Autor

Fabyo Guimarães Oliveira

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.3.3 99 6/28/2026
0.3.2 104 6/26/2026
0.2.1 106 6/25/2026
0.2.0 104 6/25/2026