SAT, NFC-e ou NF-e: decida qual documento o caixa emite antes da biblioteca
CF-e SAT, NFC-e e NF-e são documentos diferentes, com equipamento, assinatura e contingência próprios. Veja como separar o fluxo no código, deixar a regra por loja configurável e homologar de verdade.
O sistema da rede de lojas já emitia NF-e para as vendas ao atacado. Quando entrou uma loja de varejo em São Paulo, alguém achou uma biblioteca de SAT no GitHub, ligou no mesmo botão "Emitir nota" e foi para a homologação. O XML não tinha nada a ver com o da NF-e, o equipamento precisava de ativação, a contingência era outra, e o cliente da loja de Minas Gerais recebeu um cupom que não era o documento que a operação dele exigia.
A resposta curta: CF-e SAT, NFC-e e NF-e são documentos fiscais diferentes, para operações diferentes, com leiaute, assinatura e contingência próprios. Antes de escolher biblioteca, defina com o contador qual documento cada loja emite em cada tipo de operação. No código, cada documento tem seu emissor separado, e a escolha entre eles vem de uma regra configurada por loja, não de um if espalhado pela tela de venda.
Isto não substitui a orientação de um contador nem a consulta à legislação do seu estado; o objetivo é mostrar como o sistema deve ser desenhado para acomodar a regra que eles definirem.
O que diferencia os três documentos
Os três são eletrônicos e terminam num XML assinado, o que dá a impressão de serem variações do mesmo tema. Não são.
- NF-e (modelo 55): a nota fiscal eletrônica de uso geral, usada em operações entre empresas, em vendas para outros estados e em muitas situações que exigem documento completo. O seu sistema monta o XML, assina com o certificado digital da empresa e envia para autorização da Secretaria da Fazenda. A representação impressa é o DANFE.
- NFC-e (modelo 65): a nota fiscal de consumidor eletrônica, voltada à venda no varejo para consumidor final. Também é assinada com o certificado da empresa e autorizada pela SEFAZ, mas tem leiaute e regras próprias, e o cupom impresso traz um QR Code para consulta.
- CF-e SAT (modelo 59): o cupom fiscal eletrônico gerado por um equipamento SAT ligado ao computador do caixa, usado no varejo de São Paulo. O seu sistema envia os dados da venda ao equipamento; é ele quem gera, assina e transmite o cupom para a SEFAZ-SP. O equipamento precisa ser ativado e vinculado ao estabelecimento.
Há variações regionais. O Ceará, por exemplo, adotou o MFE, um módulo fiscal com lógica parecida com a do SAT, mas que não é o mesmo produto. E São Paulo, onde o SAT nasceu, passou a admitir a NFC-e e vem conduzindo uma transição entre os dois modelos; o calendário e as condições ficam na página da SEFAZ-SP, e é lá que você confere a situação atual. Some a isso a reforma tributária, que está acrescentando campos novos aos leiautes, e fica claro por que a decisão não pode estar cravada no código. O guia sobre SAT de um estado não servir para outro aprofunda a parte regional.
Como separar o fluxo no código
- Com o contador, faça a matriz de cada loja: tipo de operação, documento exigido, estado.
- Guarde essa matriz como configuração por loja, com data e responsável pela validação.
- Crie um emissor por documento, cada um atrás da mesma interface, sem compartilhar montagem de XML.
- Na venda, descubra a operação, consulte a regra da loja e chame o emissor certo. Se a loja não tiver regra para aquela operação, pare com erro claro.
- Guarde o XML e o retorno de cada documento emitido, com chave de acesso e situação.
- Homologue cada emissor no seu ambiente de homologação, com o equipamento ou certificado real.
A regra da loja como configuração
{
"lojaId": 12,
"uf": "SP",
"documentos": {
"VarejoPresencial": "CFeSat",
"VendaInterestadual": "NFe",
"VendaParaRevenda": "NFe"
},
"validadoPor": "Escritório Contábil Exemplo",
"validadoEm": "2026-09-10"
}
Os nomes das operações são da sua empresa, não da legislação. O que importa é que a decisão "esta operação, nesta loja, gera este documento" está escrita num lugar só, com quem aprovou e quando. Mudou a regra do estado, muda o arquivo, revalida, e o código não é tocado.
Emissores separados e a escolha na venda
public enum DocumentoFiscal { NFe, NFCe, CFeSat }
public enum Operacao { VarejoPresencial, VendaInterestadual, VendaParaRevenda }
public record ResultadoEmissao(bool Autorizado, string? ChaveAcesso, string Xml, string Mensagem);
public interface IEmissorFiscal
{
DocumentoFiscal Tipo { get; }
Task<ResultadoEmissao> EmitirAsync(Venda venda, CancellationToken ct);
}
public class RegraFiscalDaLoja
{
private readonly IReadOnlyDictionary<Operacao, DocumentoFiscal> _documentos;
public RegraFiscalDaLoja(IReadOnlyDictionary<Operacao, DocumentoFiscal> documentos)
=> _documentos = documentos;
public DocumentoFiscal DocumentoPara(Operacao operacao)
=> _documentos.TryGetValue(operacao, out var doc)
? doc
: throw new InvalidOperationException(
$"A loja não tem documento definido para {operacao}. Fale com o fiscal.");
}
public class FechamentoDeVenda
{
private readonly RegraFiscalDaLoja _regra;
private readonly IReadOnlyDictionary<DocumentoFiscal, IEmissorFiscal> _emissores;
private readonly IArquivoFiscal _arquivo;
public FechamentoDeVenda(RegraFiscalDaLoja regra,
IEnumerable<IEmissorFiscal> emissores, IArquivoFiscal arquivo)
{
_regra = regra;
_emissores = emissores.ToDictionary(e => e.Tipo);
_arquivo = arquivo;
}
public async Task<ResultadoEmissao> FecharAsync(Venda venda, CancellationToken ct)
{
var documento = _regra.DocumentoPara(venda.Operacao);
if (!_emissores.TryGetValue(documento, out var emissor))
throw new InvalidOperationException(
$"Este caixa não tem emissor de {documento} instalado.");
var resultado = await emissor.EmitirAsync(venda, ct);
await _arquivo.GuardarAsync(venda.Id, documento, resultado, ct);
return resultado;
}
}
O EmissorSat conversa com o equipamento pela biblioteca que você escolheu; o EmissorNfce e o EmissorNfe montam o XML e falam com os serviços da SEFAZ. Nenhum deles sabe que os outros existem. A loja de Minas, sem SAT instalado, nunca tenta emitir CF-e: a regra dela aponta outro documento, e se apontasse SAT por engano, o caixa pararia com uma mensagem clara em vez de gerar papel errado.
Contingência e homologação, cada uma no seu documento
Quando a internet cai, cada documento tem um caminho diferente. No SAT, o próprio equipamento emite e guarda os cupons para transmitir depois. Na NFC-e, existe emissão em contingência com regras e prazo de transmissão posteriores definidos pela legislação. Na NF-e, há modalidades de contingência próprias. Tratar tudo como "tenta de novo mais tarde" gera documento fora do prazo ou venda sem documento.
Homologue com o equipamento SAT real, ativado em ambiente de testes, e com o certificado de verdade para NFC-e e NF-e. O simulador ajuda no começo, mas não reproduz o tempo de resposta do aparelho, o erro de comunicação USB nem a rejeição que a SEFAZ devolve. A diferença entre os ambientes está explicada em homologação não é produção.
Erros comuns
- Ligar o SAT no mesmo botão da NF-e. A loja emite um documento que a operação dela não admite, e o cliente fica com papel inválido.
- Cravar a regra fiscal em
ifpor estado. Cada mudança de legislação vira deploy, e um caso esquecido emite o documento errado sem aviso. - Reaproveitar a montagem de XML entre documentos. Os leiautes são diferentes, e um ajuste num quebra o outro.
- Homologar só com simulador. Os problemas de ativação, comunicação e rejeição aparecem no primeiro dia da loja.
- Misturar certificado e ambiente. Documento de homologação vai para produção, ou o contrário, e o arquivo fiscal fica inconsistente.
- Não guardar o XML e o retorno. Na hora da fiscalização ou do cancelamento, ninguém acha o documento original.
Checklist
- Existe uma matriz por loja, validada pelo contador, de operação para documento.
- A matriz é configuração, com data e responsável, e não código.
- Cada documento tem emissor próprio atrás de uma interface comum.
- Operação sem regra definida bloqueia a venda com mensagem clara.
- A contingência de cada documento foi testada separadamente.
- O SAT foi homologado com equipamento real ativado.
- Todo XML e retorno da SEFAZ ou do equipamento fica guardado.
Para o funcionamento do SAT no dia a dia do caixa, veja SAT fiscal no PDV, e para as diferenças de XML, XML de SAT não é a NF-e com a raiz trocada. E agora olhe a tela de venda do seu sistema: o botão de fechar sabe qual documento esta loja deve emitir, ou ele emite sempre o mesmo?
Referência: https://github.com/ACBrNet/ACBr.Net.Sat