NF-e em homologação e produção: como impedir que um ambiente vaze no outro
Amarre URL, tpAmb, série e numeração a uma única chave de ambiente, confira tudo antes de transmitir e deixe o ambiente visível para quem emite.
Segunda, 9h. A Casa Ferragem Silva emitiu doze notas no sábado, os clientes levaram a mercadoria e ninguém percebeu que o sistema ainda apontava para homologação. As doze notas foram autorizadas, só que sem valor fiscal. No mesmo dia, o caso inverso: um desenvolvedor testou um ajuste no XML e consumiu a numeração de produção, deixando buracos na sequência da série 1.
A resposta curta: ambiente de NF-e não é "o mesmo sistema com outro endereço". É um conjunto amarrado — URL do web service, campo tpAmb, série, contador de numeração e o aviso na tela — e tudo isso precisa derivar de uma única configuração, conferida antes de cada transmissão. Se cada peça é configurada à parte, um dia uma delas fica para trás.
Por que os dois ambientes se misturam
A SEFAZ mantém dois ambientes separados. Homologação aceita nota para teste, devolve protocolo de autorização de verdade e não gera obrigação fiscal. Produção é o mundo real: a nota vale, entra no cruzamento do fisco e só sai de lá por cancelamento ou evento. O XML diz em qual ambiente quer estar pelo campo tpAmb (1 para produção, 2 para homologação), e o endereço do web service diz para qual servidor você está mandando.
O problema começa quando essas informações moram em lugares diferentes. A URL fica num arquivo de configuração, o tpAmb fica fixo no código que monta o XML, a série fica numa tabela e o contador é o mesmo para os dois. Basta alguém trocar só a URL para o sistema mandar XML de produção para homologação (que rejeita pelo ambiente divergente) ou, pior, achar que trocou tudo e continuar emitindo nota de teste para cliente real.
O certificado digital não ajuda a diferenciar: o mesmo certificado A1 da empresa funciona nos dois ambientes. Por isso ele não pode ser o "sinal" de que você está em produção. Sobre a etapa anterior ao XML, há um panorama em o que acontece antes do XML da nota; e sobre por que o ambiente de teste existe, em homologação existe para errar sem valer. Aqui o foco é a engenharia que impede a mistura.
Como amarrar o ambiente a uma única chave
- Escolha o ambiente em um só lugar. Uma variável de configuração, por exemplo
NFE_AMBIENTE=homologacao. Nada mais no sistema decide ambiente por conta própria. - Derive tudo dessa chave. URL do autorizador,
tpAmbdo XML, série padrão e contador de numeração saem da mesma escolha. Ninguém digita a URL à mão. - Separe a numeração por ambiente. O contador tem chave composta (ambiente, série). Teste nunca consome número de produção.
- Confira antes de transmitir. Leia o
tpAmbdo XML já assinado e compare com o ambiente configurado. Divergiu, não envia. - Confira o retorno. O protocolo devolvido também traz
tpAmb. Grave-o junto com a URL usada e o número do protocolo. - Mostre o ambiente na tela. Uma faixa fixa "HOMOLOGAÇÃO — SEM VALOR FISCAL" na tela de emissão e o mesmo aviso impresso no DANFE de teste.
Exemplo em C#: configuração que não deixa peça solta
No sistema da Casa Ferragem Silva, a configuração só aceita o ambiente. A URL vem de uma tabela no código, indexada pelo próprio ambiente. Os endereços abaixo são fictícios; os reais dependem do autorizador da sua UF e estão publicados no Portal da NF-e.
public enum AmbienteNfe { Producao = 1, Homologacao = 2 }
public sealed class ConfigNfe
{
private static readonly Dictionary<AmbienteNfe, string> UrlAutorizacao = new()
{
[AmbienteNfe.Producao] = "https://nfe.exemplo-uf.gov.br/ws/NFeAutorizacao4.asmx",
[AmbienteNfe.Homologacao] = "https://homologacao.nfe.exemplo-uf.gov.br/ws/NFeAutorizacao4.asmx"
};
public AmbienteNfe Ambiente { get; }
public string Url => UrlAutorizacao[Ambiente];
public int TpAmb => (int)Ambiente;
public ConfigNfe(string valorDaVariavel)
{
Ambiente = valorDaVariavel switch
{
"producao" => AmbienteNfe.Producao,
"homologacao" => AmbienteNfe.Homologacao,
_ => throw new InvalidOperationException(
"NFE_AMBIENTE deve ser 'producao' ou 'homologacao'. Valor recebido: " + valorDaVariavel)
};
}
}
Repare que não existe valor padrão. Se a variável estiver ausente ou com erro de digitação, o sistema não sobe. É melhor a emissão parar às 8h com uma mensagem clara do que funcionar o dia inteiro no ambiente errado.
A conferência antes do envio
using System.Xml.Linq;
static void ConferirAmbiente(string xmlAssinado, ConfigNfe config)
{
XNamespace ns = "http://www.portalfiscal.inf.br/nfe";
var doc = XDocument.Parse(xmlAssinado);
var tpAmb = doc.Descendants(ns + "tpAmb").FirstOrDefault()?.Value;
if (tpAmb != config.TpAmb.ToString())
throw new InvalidOperationException(
"XML com tpAmb=" + tpAmb + " mas o sistema está em " + config.Ambiente + ". Envio bloqueado.");
}
A checagem custa microssegundos e pega exatamente o caso do XML gerado num ambiente e transmitido em outro, que acontece quando há fila de reenvio, XML montado num servidor e enviado por outro, ou um script de contingência esquecido.
Numeração separada no banco
CREATE TABLE numeracao_nfe (
ambiente TINYINT NOT NULL,
serie INT NOT NULL,
proximo_numero INT NOT NULL,
PRIMARY KEY (ambiente, serie)
);
INSERT INTO numeracao_nfe VALUES (1, 1, 1532); -- produção, série 1
INSERT INTO numeracao_nfe VALUES (2, 1, 1); -- homologação, série 1
Com a chave composta, o teste da segunda-feira usa o contador da linha de homologação e a série 1 de produção continua em 1532. Se o teste tivesse consumido números de produção, os buracos na sequência precisariam ser tratados com inutilização de numeração, que é um evento formal e não uma limpeza de banco. Para quem prefere isolar ainda mais, uma série exclusiva para testes também funciona, desde que o contador continue separado por ambiente.
O que homologação exige de diferente
Homologação tem regras próprias. A mais conhecida é o texto padrão exigido no nome do destinatário, "NF-E EMITIDA EM AMBIENTE DE HOMOLOGACAO - SEM VALOR FISCAL". Se o seu código monta o destinatário igual nos dois ambientes, a nota de teste é rejeitada. A redação exata e as demais regras estão no Manual de Orientação do Contribuinte (MOC) e nas notas técnicas vigentes; confira a versão que você implementou, porque dica de nota fiscal antiga pode rejeitar a nota de hoje.
Essa diferença é mais um motivo para a regra sair da mesma chave: o montador de XML pergunta à configuração se está em homologação e aplica o texto, em vez de alguém lembrar de trocar.
Deixar o ambiente visível para quem emite
O operador do caixa não abre XML. Ele vê a tela e o papel. Se em homologação a tela é idêntica à de produção, o erro de sábado vai se repetir. Coloque uma faixa colorida fixa no topo da emissão, o nome do ambiente no rodapé de cada tela e a marca "SEM VALOR FISCAL" no DANFE gerado em homologação. Muitas bibliotecas de DANFE já fazem isso quando leem tpAmb=2; confira se a sua faz.
No log de cada autorização, grave ambiente, URL, série, número, chave de acesso e protocolo. Quando o contador pedir explicação sobre uma nota, você responde em minutos.
Erros comuns
- Trocar só a URL no arquivo de configuração. O
tpAmbcontinua fixo no código e a SEFAZ rejeita, ou a troca parcial passa despercebida até alguém conferir uma nota real. - Usar o mesmo contador de numeração para os dois ambientes. O teste consome números de produção e abre buracos que exigem inutilização.
- Ter um valor padrão de ambiente no código. Se a variável some num deploy, o sistema sobe silenciosamente no ambiente padrão, seja ele qual for.
- Usar o certificado como sinal de ambiente. O mesmo certificado vale nos dois; ele não diferencia nada.
- Imprimir DANFE de teste igual ao de produção. O papel vai junto com a mercadoria e o cliente acha que tem nota válida.
- Copiar o banco de produção para homologação sem zerar a numeração. O ambiente de teste herda contadores e dados reais de clientes, o que também é um problema de privacidade.
Checklist
- O ambiente é escolhido em uma única variável, sem valor padrão.
- URL,
tpAmbe regras específicas de homologação derivam dessa variável. - A tabela de numeração tem chave (ambiente, série).
- O
tpAmbdo XML assinado é conferido antes do envio. - O
tpAmbdo protocolo de retorno é conferido e gravado. - A tela de emissão mostra o ambiente sem precisar abrir o XML.
- O DANFE de homologação traz "SEM VALOR FISCAL".
- O log de autorização guarda ambiente, URL, série, número e protocolo.
Abra agora a tela de emissão do seu sistema, sem olhar configuração nem XML: você consegue dizer em qual ambiente está e qual será o número da próxima nota de produção?
Referência: https://pt.stackoverflow.com/questions/35235/como-emitir-o-xml-da-nfe-ao-ws-da-sefaz-usando-c