Gerador de NF-e adaptado para o SAT: por que o equipamento recusa e como separar
O CF-e-SAT tem leiaute, fluxo e assinatura próprios. Reaproveitar o gerador da NF-e com duas tags trocadas produz cupom recusado no balcão. Veja as diferenças e um desenho com um emissor por documento.
Sábado, 11h, a loja de calçados em Campinas está com fila. O time tinha copiado a rotina que gera a NF-e, trocado a raiz para CFe, renomeado duas tags e apontado para o SAT. Cada venda volta recusada pelo equipamento, e a operadora do caixa não sabe se a venda vale. A resposta curta: o XML do CF-e-SAT não é a NF-e com a raiz trocada. Ele tem leiaute próprio, quem assina é o equipamento e boa parte dos campos que a NF-e exige o seu sistema nem deve mandar. Tenha um gerador por documento, escolhido pela configuração da loja, e teste cada um no ambiente de testes do próprio documento.
Este guia mostra as diferenças que derrubam o reaproveitamento e um desenho de código que impede a mistura. Para o contexto de quando usar SAT, veja SAT fiscal no PDV; para a diferença conceitual entre os documentos, SAT não é a nota eletrônica com outro nome.
Regras fiscais variam por estado e mudam com o tempo. Isto não substitui o contador nem a documentação oficial da Sefaz do seu estado.
Por que "quase igual" não funciona
NF-e, NFC-e e CF-e-SAT resolvem problemas parecidos, mas o fluxo de cada um é diferente, e o XML reflete o fluxo:
- Na NF-e e na NFC-e, o seu sistema gera o XML completo, com numeração, data de emissão e chave de acesso, assina com o certificado digital da empresa e transmite para o serviço web da Sefaz. A NFC-e usa o mesmo leiaute da NF-e, com modelo 65 e um grupo para o QR Code.
- No SAT, usado em São Paulo, o seu sistema (o aplicativo comercial) monta apenas os dados da venda e entrega ao equipamento por uma biblioteca do fabricante. O equipamento completa a numeração e a data, assina com o certificado dele e cuida da transmissão. O Ceará tem um modelo próprio de equipamento fiscal, com especificação própria; não é o SAT paulista com outro nome.
Na prática, o XML de entrada do SAT é menor e diferente. O grupo de identificação, que na NF-e tem dezenas de campos, no SAT leva o CNPJ da software house, a assinatura do aplicativo comercial (signAC) e o número do caixa. A versão vem no atributo versaoDadosEnt, não em versao. E grupos equivalentes têm nomes e estrutura diferentes.
O mesmo pagamento nos dois documentos
Uma venda de R$ 59,90 no cartão de crédito. Na NF-e e na NFC-e:
<pag>
<detPag>
<tPag>03</tPag>
<vPag>59.90</vPag>
</detPag>
</pag>
No XML de venda do SAT:
<pgto>
<MP>
<cMP>03</cMP>
<vMP>59.90</vMP>
</MP>
</pgto>
Mesma informação, outra estrutura. Multiplique isso pelo cabeçalho, pelos itens e pelos impostos, e a rotina "adaptada" vira uma colcha de if que gera um documento que não é nenhum dos dois. O guia sobre gerar o XML da nota sem concatenar vale para os dois documentos; o ponto aqui é que cada um tem o seu modelo.
Como separar os fluxos no código
- Modele a venda uma vez, sem nada fiscal: itens, quantidades, valores, pagamentos, cliente opcional. Ela é a entrada comum.
- Crie um emissor por documento, cada um com o próprio modelo de XML, a própria validação e a própria forma de envio: um para NFC-e, outro para CF-e-SAT.
- Escolha o emissor pela configuração da loja e do caixa, não por um
ifespalhado. A loja de Campinas emite SAT; a loja de outro estado emite NFC-e. - Falhe na abertura do caixa se a configuração não tiver emissor válido. É melhor descobrir às 8h do que na primeira venda.
- Mostre na tela do caixa qual documento está ativo. Quem opera a loja precisa saber se está emitindo SAT ou NFC-e.
- Teste cada emissor no ambiente de testes próprio: homologação da Sefaz para a NFC-e, equipamento em modo de teste ou ferramenta de teste oficial para o SAT.
Um emissor por documento, escolhido pela loja
public enum DocumentoDeVenda { Nfce, CfeSat }
public sealed record ResultadoEmissao(bool Autorizado, string? Chave, string? Xml, string Mensagem);
public interface IEmissorDeCupom
{
DocumentoDeVenda Documento { get; }
Task<ResultadoEmissao> EmitirAsync(Venda venda, CancellationToken ct);
}
public sealed class SeletorDeEmissor
{
private readonly IReadOnlyDictionary<DocumentoDeVenda, IEmissorDeCupom> _emissores;
public SeletorDeEmissor(IEnumerable<IEmissorDeCupom> emissores) =>
_emissores = emissores.ToDictionary(e => e.Documento);
public IEmissorDeCupom Para(ConfiguracaoDoCaixa caixa) =>
_emissores.TryGetValue(caixa.Documento, out var emissor)
? emissor
: throw new InvalidOperationException(
"Caixa " + caixa.Numero + " configurado para " + caixa.Documento + ", mas não há emissor registrado.");
}
O EmissorSat e o EmissorNfce implementam a interface cada um à sua maneira. O emissor de SAT monta o XML de venda com signAC e número do caixa, chama a função de envio da biblioteca do fabricante com o número de sessão e o código de ativação, e interpreta o retorno do equipamento. O de NFC-e monta o XML completo, assina com o certificado, gera o QR Code e transmite. Nenhum dos dois conhece o outro. Uma mudança no leiaute do SAT não tem como quebrar a NFC-e.
Na abertura do caixa, chame Para uma vez e guarde o emissor. Se lançar exceção, o caixa não abre e mostra a mensagem. A operadora vê na barra superior "Emitindo: CF-e-SAT" ou "Emitindo: NFC-e".
Contingência e mudança de documento
Contingência é outro ponto em que os documentos não se misturam. A NFC-e tem modalidades de contingência próprias, previstas na documentação. O SAT tem o comportamento do equipamento e as regras da Sefaz-SP para quando ele falha. Não improvise "se o SAT falhar, emite NFC-e" numa sexta à tarde sem saber se a sua empresa pode e como registrar isso. Defina com o contador antes, escreva o procedimento e teste.
A Sefaz-SP vem conduzindo a migração de contribuintes do SAT para a NFC-e. Se a sua loja está nessa transição, o desenho com um emissor por documento é exatamente o que permite trocar a configuração do caixa num dia marcado, sem reescrever a venda. Confira o cronograma na página oficial da Sefaz-SP. Se você atende lojas em mais de um estado, veja também SAT de um estado não se copia para outro.
Erros comuns
- Reaproveitar o gerador da NF-e trocando a raiz. O equipamento recusa, e a recusa aparece no balcão, com cliente esperando.
- Mandar ao SAT campos que ele mesmo preenche, como numeração e data de emissão. O XML de entrada fica fora do leiaute.
- Decidir o documento com
ifespalhado pelo código. Uma tela emite SAT, outra emite NFC-e, e ninguém sabe qual vale em cada caixa. - Testar o SAT só com XML validado no computador do desenvolvedor. A recusa real vem do equipamento ou da ferramenta de teste oficial.
- Esconder da operação qual documento está ativo. Quando dá problema, o suporte pergunta "é SAT ou NFC-e?" e ninguém na loja sabe responder.
- Tratar a biblioteca fiscal como se ela escolhesse o documento. Ela emite o que você pede; a escolha é configuração da loja, validada com o contador.
Checklist
- Existe um emissor separado para cada documento, sem código de XML compartilhado entre eles.
- A venda é modelada uma vez, sem campo fiscal específico de um documento.
- O documento de cada caixa vem da configuração, e o caixa não abre sem emissor válido.
- A tela do caixa mostra qual documento está ativo.
- O emissor de SAT foi testado no equipamento em modo de teste ou na ferramenta oficial.
- O procedimento de contingência de cada documento está escrito e foi validado com o contador.
- Há um plano para trocar o documento de uma loja sem mexer na venda.
Vá até o caixa de uma das suas lojas e tente responder sem abrir o código: o botão de finalizar a venda vai emitir CF-e-SAT ou NFC-e, e onde isso está configurado?