dfe
Documentos Fiscais Eletrônicos Brasileiros — crate Rust para integração com os webservices da SEFAZ.
Índice
- Instalação
- Funcionalidades
- Emissão NF-e / NFC-e
- Cancelamento
- Manifestação do Destinatário
- Distribuição de DF-e
- DANFE — Geração de PDF
- ESC/POS — Impressoras Térmicas
- Status do Webservice
- Tratamento de Erros
- Tipos de ICMS suportados
- Validação de CNPJ / CPF
- Testes
- Notas importantes
- Roadmap
- Licença
Instalação
[]
= "0.5.7"
Schemas XSD (
PL_010b_NT2025_002_v1.21) estão embutidos no binário viainclude_bytes!.
OpenSSL — compilação a partir do código-fonte (vendored)
Esta crate depende do openssl com features = ["vendored"]. Isso significa que o OpenSSL não precisa estar instalado no sistema — ele é baixado e compilado automaticamente durante o cargo build. A desvantagem é que a primeira compilação leva alguns minutos a mais.
Porém, o sistema de build do OpenSSL é escrito em Perl, então o Perl deve estar instalado e acessível no PATH antes de compilar. Sem ele, o build falhará com um erro parecido com:
Could not find perl
Windows
Instale o Strawberry Perl (recomendado — inclui compilador C e ferramentas Unix necessárias):
- Baixe o instalador
.msiem https://strawberryperl.com - Execute o instalador (o PATH é atualizado automaticamente)
- Abra um novo terminal e confirme:
perl -v - Execute
cargo buildnormalmente
O Strawberry Perl já vem com
dmakeegcc, o que evita dependência do MSVC ou do Visual Studio Build Tools.
Linux
O Perl geralmente já está disponível. Verifique:
Se não estiver instalado:
# Debian/Ubuntu
# Fedora/RHEL
macOS
O Perl já vem pré-instalado com o macOS. Nenhuma ação necessária.
Funcionalidades
| Funcionalidade | Descrição |
|---|---|
| Emissão NF-e / NFC-e | Autorização via SOAP para SEFAZ estadual (modelos 55 e 65) |
| Cancelamento | Evento 110111 para NF-e e NFC-e |
| Manifestação do destinatário | Ciência, confirmação, desconhecimento e operação não realizada |
| Distribuição de DF-e | Consulta ao Ambiente Nacional por NSU ou chave de acesso |
| DANFE | Geração de PDF em A4 e 80mm (NF-e e NFC-e) com suporte a logotipo |
| ESC/POS | EscPosBuilder (layout livre) + EscPosNFCeBuilder (NFC-e pronto) |
| Validação XSD | Schemas SEFAZ embutidos no binário — sem arquivos externos |
| Validação CNPJ/CPF | Verificação de dígito verificador |
| Status do webservice | Consulta de disponibilidade por UF e ambiente |
Emissão NF-e / NFC-e
use NFeBuilder;
use ;
use Dest;
let resposta = new
.cert
.ide
.emitente
.destinatario
.itens
.total // totais calculados automaticamente dos itens
.transporte
.pagamento
.informacoes_adicionais
// NFC-e: obrigatório também .id_csc() e .csc()
.emitir
.await?;
println!;
println!;
println!;
// resposta.xml → XML autorizado (nfeProc) completo
Métodos do NFeBuilder
| Método | Obrigatório | Descrição |
|---|---|---|
.cert(path, pass) |
✅ | Caminho e senha do certificado .pfx |
.ide(Ide) |
✅ | Identificação do documento |
.emitente(Emit) |
✅ | Dados do emitente |
.itens(Vec<Det>) |
✅ | Lista de itens; totais calculados automaticamente |
.total(Total) |
✅ | Informar apenas frete, seguro, ST, FCP — demais campos auto-calculados |
.transporte(Transp) |
✅ | Modalidade de frete e dados do transportador |
.pagamento(Pag) |
✅ | Forma de pagamento |
.destinatario(Dest) |
— | Obrigatório para NF-e mod 55 |
.informacoes_adicionais(InfAdic) |
— | Informações complementares e ao fisco |
.id_csc(str) |
— | ID do CSC — obrigatório NFC-e |
.csc(str) |
— | Valor do CSC — obrigatório NFC-e |
.desconto_rateio(Decimal) |
— | Desconto global rateado proporcionalmente nos itens |
.emitir() |
— | Valida, assina e transmite para a SEFAZ |
Totais automáticos
Os campos v_bc, v_icms, v_prod, v_pis, v_cofins, v_desc e v_nf são calculados automaticamente dos itens. No Total informe apenas despesas extras:
| Campo | Quando usar |
|---|---|
v_frete, v_seg, v_outro |
Frete, seguro e outras despesas |
v_ii, v_ipi, v_ipi_devol |
Impostos específicos |
v_bc_st, v_st |
ST global (itens com ICMS10/30/70 auto-somam) |
v_fcp, v_fcpst, v_fcpst_ret |
Fundo de Combate à Pobreza |
v_fcpuf_dest, v_icms_uf_dest, v_icms_uf_remet |
DIFAL |
Para uma venda simples sem extras: Total::default().
Cancelamento
use CancelarBuilder;
let r = new
.cert
.tp_amb // 1 = Produção | 2 = Homologação
.chave
.protocolo
.justificativa // mín. 15 chars
.mod_ // opcional — padrão 55; 65 para NFC-e
.send
.await?;
println!; // "135" = evento registrado
println!;
// r.send_xml → XML enviado
// r.receive_xml → XML de resposta
| Método | Obrigatório | Descrição |
|---|---|---|
.cert(path, pass) |
✅ | Certificado .pfx |
.tp_amb(u8) |
✅ | Ambiente (1 = Produção, 2 = Homologação) |
.chave(str) |
✅ | Chave de acesso de 44 dígitos |
.protocolo(str) |
✅ | Protocolo de autorização da NF-e |
.justificativa(str) |
✅ | Mínimo 15 caracteres |
.mod_(u32) |
— | Modelo do documento (padrão: 55) |
Manifestação do Destinatário
Eventos enviados ao Ambiente Nacional (AN). O Manifestacao é compartilhado entre os quatro eventos.
use ;
use ;
let params = Manifestacao ;
// 210210 — Ciência da Operação
let r = ciencia_operacao.await?;
// 210200 — Confirmação da Operação
let r = confirmacao_operacao.await?;
// 210220 — Desconhecimento da Operação
let r = desconhecimento_operacao.await?;
// 210240 — Operação Não Realizada (requer justificativa mín. 15 chars)
let r = operacao_nao_realizada.await?;
println!;
println!;
Distribuição de DF-e
Consulta documentos fiscais de interesse do CNPJ no Ambiente Nacional.
use ;
// Últimos documentos
let r = new
.cert_path
.cert_pass
.cnpj
.uf // código IBGE da UF (SP = 35)
.ambiente
.send
.await?;
println!;
if let Some = r.lote_dist_dfe_int
// A partir de um NSU específico
let r = new
.cert_path.cert_pass
.cnpj.uf.ambiente
.nsu
.send.await?;
// Por chave de acesso
let r = new
.cert_path.cert_pass
.cnpj.uf.ambiente
.chave_acesso
.send.await?;
DANFE — Geração de PDF
Gera o DANFE em PDF a partir do XML autorizado (nfeProc). O modelo (55 ou 65) é detectado automaticamente do campo <mod> no XML.
use DanfeBuilder;
// NF-e A4 — salvar como arquivo
let caminho = new
.xml // caminho .xml ou string XML diretamente
.paper_size // padrão quando omitido
.as_file
.build
.await?;
println!;
// NF-e A4 — com logotipo do emitente, retornar base64
let b64 = new
.xml
.paper_size
.logo // .png/.jpg, base64 puro ou data URI
.as_base64
.build
.await?;
// NF-e 80mm
let b64 = new
.xml
.paper_size
.as_base64
.build
.await?;
// NFC-e 80mm — QR Code lateral
let b64 = new
.xml
.paper_size
.qr_side // QR Code à esquerda (~33mm); chave e protocolo à direita
.as_base64
.build
.await?;
Métodos do DanfeBuilder
| Método | Obrigatório | Descrição |
|---|---|---|
.xml(src) |
✅ | Caminho .xml ou string do nfeProc |
.paper_size(str) |
— | "a4" (padrão), "80mm" ou "54mm" |
.as_file(path) |
✅¹ | Salva o PDF em disco; retorna o caminho |
.as_base64() |
✅¹ | Retorna o PDF como string base64 |
.logo(src) |
— | Logotipo do emitente — apenas A4 |
.qr_side() |
— | Layout QR lateral — apenas NFC-e 80mm |
¹ Use .as_file() ou .as_base64() — nunca os dois.
Formatos implementados
| Tamanho | Modelo 55 (NF-e) | Modelo 65 (NFC-e) |
|---|---|---|
"a4" |
✅ (suporta .logo()) |
❌ |
"80mm" |
✅ | ✅ (suporta .qr_side()) |
"54mm" |
❌ | ❌ |
ESC/POS — Impressoras Térmicas
EscPosBuilder — layout personalizado
use EscPosBuilder;
let bytes = new
.paper_width // 80mm ou 58mm
.align_center
.bold
.text
.bold
.align_left
.text
.divider
.text
.divider
.align_right
.bold
.text
.bold
.cut
.build; // → Vec<u8>
// Enviar para impressora
write?; // Windows
write?; // Linux
| Método | Descrição |
|---|---|
.paper_width(mm) |
Largura do papel: 80 ou 58. Padrão: 80 |
.align_left() / .align_center() / .align_right() |
Alinhamento |
.bold(bool) |
Negrito |
.underline(bool) |
Sublinhado |
.font_size(u8) |
Tamanho da fonte (1 = normal, 2 = duplo) |
.text(str) |
Insere texto |
.divider() |
Linha separadora proporcional à largura do papel |
.barcode_128(str) |
Code 128 nativo ESC/POS |
.qr_code(str, size) |
QR Code nativo ESC/POS |
.image(bytes) |
Imagem rasterizada PNG/JPEG → bitmap 1-bit (GS v 0) |
.feed(n) |
Avança n linhas |
.cut() |
Corte total |
.partial_cut() |
Corte parcial |
.build() |
Retorna Vec<u8> |
EscPosNFCeBuilder — impressão de NFC-e
use EscPosNFCeBuilder;
// QR Code centralizado (padrão)
let bytes = new
.xml // ou string XML diretamente
.paper_width // padrão: 80mm; 58mm também suportado
.build?; // → Result<Vec<u8>, DfeError>
// QR Code à esquerda (compacto)
let bytes = new
.xml
.qr_side
.build?;
write?;
Layout do cupom:
NOME DO EMITENTE
CNPJ: XX.XXX.XXX/XXXX-XX IE: XXXXXXXX SP
Rua Exemplo, 100 - Centro / Cidade/SP
------------------------------------------------
DOCUMENTO AUXILIAR DA NFC-E
------------------------------------------------
# DESCRICAO
QTD UN R$ VL.UNIT R$ TOTAL
------------------------------------------------
Qtd. Itens: N
TOTAL R$ XXX,XX
------------------------------------------------
FORMA DE PAGAMENTO VALOR
Dinheiro R$ XXX,XX
------------------------------------------------
Consulte pela Chave de Acesso em
www.nfce.fazenda.sp.gov.br/consulta
CHAVE DE ACESSO
3524 0600 0000 0000 ...
[CODE 128]
[QR CODE]
------------------------------------------------
PROTOCOLO DE AUTORIZACAO
135XXXXXX - DD/MM/YYYY HH:MM:SS
NF-e No 000000001 Serie 1 DD/MM/YYYY HH:MM:SS
------------------------------------------------
Valor Aproximado dos Tributos R$ X,XX (Fonte: IBPT)
Status do Webservice
use NFeService;
let r = new
.cert_path
.cert_pass
.uf
.environment // 1 = Produção | 2 = Homologação
.send
.await?;
println!; // "107" = Serviço em operação
println!;
println!;
Tratamento de Erros
Todas as funções públicas retornam Result<T, DfeError>.
use DfeError;
match resultado
| Variante | Quando ocorre |
|---|---|
Certificado |
Falha ao abrir o .pfx ou senha incorreta |
Xml |
Erro de parsing ou serialização XML |
Assinatura |
Falha na assinatura digital RSA-SHA1 |
Webservice |
Erro HTTP ou resposta inesperada da SEFAZ |
Validacao |
Campo obrigatório ausente ou fora das regras XSD |
Configuracao |
Falha ao ler configuração ou credenciais |
Io |
Erro de leitura/escrita em disco |
Tipos de ICMS suportados
| Variante | CST/CSOSN | Regime | Construtor |
|---|---|---|---|
Icms00 |
00 | Normal CRT=3 | Icms::icms00(orig, mod_bc, v_bc, p_icms, v_icms) |
Icms10 |
10 | Normal CRT=3 | Icms::icms10(orig, mod_bc, v_bc, p_icms, v_icms, mod_bcst, p_mvast, v_bcst, p_icmsst, v_icmsst) |
Icms20 |
20 | Normal CRT=3 | Icms::icms20(orig, mod_bc, p_red_bc, v_bc, p_icms, v_icms) |
Icms30 |
30 | Normal CRT=3 | Icms::icms30(orig, mod_bcst, p_mvast, v_bcst, p_icmsst, v_icmsst) |
Icms40 |
40/41/50 | Normal CRT=3 | Icms::icms40(orig, cst) |
Icms51 |
51 | Normal CRT=3 | Icms::icms51(orig) + campos via struct literal |
Icms60 |
60 | Normal CRT=3 | Icms::icms60(orig) |
Icms70 |
70 | Normal CRT=3 | Icms::icms70(orig, mod_bc, v_bc, p_icms, v_icms, mod_bcst, p_mvast, v_bcst, p_icmsst, v_icmsst) |
Icms90 |
90 | Normal CRT=3 | Icms::icms90(orig) + campos opcionais via struct literal |
Sn101 |
CSOSN 101 | Simples CRT=1 | Icms::sn101(orig, p_cred_sn, v_cred_icmssn) |
Sn102 |
CSOSN 102/103/300/400 | Simples CRT=1 | Icms::sn102(orig, csosn) |
Sn500 |
CSOSN 500 | Simples CRT=1 | Icms::sn500(orig) |
Sn900 |
CSOSN 900 | Simples CRT=1 | Icms::sn900(orig) + campos opcionais via struct literal |
IPI por item
use Ipi;
// CST 50 — saída tributada por alíquota ad valorem
ipi: Some
// CST 53 — saída não tributada
ipi: Some
PIS / COFINS
use ;
// CST 01/02 — alíquota
Aliq
// CST 03 — por quantidade
Qtde
// CST 04-09 — não tributado
Nt
// CST 05 — substituição tributária
St
// CST 99 — outros (zeros automáticos)
Outr
Validação de CNPJ / CPF
use ;
assert!;
assert!;
assert!;
assert!;
Testes
Os testes estão em src/bin/tests/ e cobrem:
| Suite | Arquivo | Descrição |
|---|---|---|
| DANFE NF-e A4 | test_danfe_nfe_a4.rs |
Geração A4 modelo 55 (base64, arquivo, erro modelo 65) |
| DANFE NFC-e 80mm | test_danfe_nfce.rs |
Geração 80mm modelo 65 (multi-pagamento, CPF, qr_side, erros) |
| XML Extractor | test_xml_extractor.rs |
Parsing de nfeProc a partir de string e arquivo |
| Integração | mod.rs |
Status SEFAZ, emissão NF-e/NFC-e, cancelamento, DANFE¹ |
¹ Os testes de integração requerem certificado .pfx válido e conectividade com a SEFAZ em homologação.
Notas importantes
- Sempre teste em homologação (
tp_amb: 2) antes de produção. - O certificado
.pfxé lido do disco a cada operação — nunca cacheado em memória. - Em
tp_amb = 2, o campox_proddo primeiro item é substituído automaticamente por"NOTA FISCAL EMITIDA EM AMBIENTE DE HOMOLOGACAO - SEM VALOR FISCAL"(exigência SEFAZ). - Os webservices cobertos são da SEFAZ/SP e do Ambiente Nacional. Para outras UFs, contribua adicionando URLs em
interno/ws.rs.
Roadmap
| Item | Status |
|---|---|
ICMS10/20/30/51/70 |
✅ |
ICMS90 / Sn900 completos |
✅ |
DIFAL (v_icms_uf_dest, v_icms_uf_remet) |
✅ |
IPI por item (Det.ipi) |
✅ |
| PIS/COFINS ST (CST 05) | ✅ |
| IBS / CBS (reforma tributária) | ✅ |
| Validação de CNPJ/CPF | ✅ |
ESC/POS EscPosBuilder |
✅ |
ESC/POS EscPosNFCeBuilder |
✅ |
| Contingência (EPEC / FS-DA) | 🔜 |
Licença
MIT — veja LICENSE.