Programação Por Equipe DevBras

Capa do artigo: NF-e rejeitada com XML que parece perfeito: schema, assinatura e o editor que reformata

NF-e rejeitada com XML que parece perfeito: schema, assinatura e o editor que reformata

Valide o XML da nota contra o XSD da versão declarada, assine sem tocar depois, confira a assinatura localmente e só considere pronta a nota com protocolo.

Quinta, 17h40, a nota 1532 da Ferragens Lima volta rejeitada. O desenvolvedor abre o XML assinado no editor, o arquivo está lindo, indentado, cada tag no lugar. Ele aperta "formatar documento" para ler melhor, transmite de novo e a rejeição muda: agora é a assinatura que não confere. O XML ficou mais bonito e menos válido.

A resposta curta: quem decide se a nota é válida é o schema da versão que você declarou e a assinatura calculada sobre os bytes exatos do XML, não a aparência no editor. Valide contra o XSD antes de transmitir, assine e não toque mais no arquivo, confira a assinatura localmente e só chame de pronta a nota que voltou com protocolo de autorização, primeiro em homologação.

Por que o XML que parece certo é rejeitado

A nota fiscal eletrônica passa por três etapas diferentes: gerar o XML, assinar com o certificado digital e transmitir para o webservice da Secretaria da Fazenda. Cada etapa tem um jeito próprio de falhar, e nenhum deles aparece a olho nu.

O schema confere estrutura, não aparência

O leiaute da NF-e é publicado como um pacote de arquivos XSD. Eles definem a ordem dos elementos, quais são obrigatórios, o tamanho de cada campo, os padrões aceitos e os valores possíveis. Um CEP escrito como 01310-100 em vez de oito dígitos, um valor com vírgula em vez de ponto decimal ou um elemento fora da sequência esperada derrubam a nota. No editor, tudo isso parece normal.

O schema que vale é o da versão declarada no próprio XML, no atributo versao do grupo infNFe. Se você declara uma versão e monta o conteúdo seguindo um exemplo antigo de outra, a rejeição vem mesmo que "o XML esteja certo". Por isso dica de fórum com dez anos de idade é perigosa, como mostra o post sobre dica de nota fiscal que tem data.

A assinatura confere bytes, não significado

A assinatura digital da NF-e segue o padrão XML Signature: o conteúdo do grupo infNFe é canonicalizado, vira um resumo criptográfico e esse resumo é assinado com a chave do certificado. A referência da assinatura aponta para o atributo Id desse grupo, que começa com "NFe" seguido da chave de acesso.

A canonicalização padroniza detalhes como a ordem dos atributos, mas não remove espaços e quebras de linha entre as tags. Esses espaços são nós de texto e entram no cálculo. Indentar o arquivo depois de assinar, trocar o fim de linha, corrigir "só um acento" ou regravar com outro encoding muda o resumo. O fisco recalcula, compara e rejeita.

Como gerar, validar, assinar e transmitir sem surpresa

O fluxo abaixo usa a nota 1532 da Ferragens Lima como exemplo. Os passos valem para qualquer linguagem; os exemplos usam xmllint e C#.

  1. Gere o XML com serialização, não com concatenação de texto. Objetos ou um gerador de XML cuidam de escape e de ordem. O post sobre montar o XML da nota sem concatenar string detalha os riscos.
  2. Baixe o pacote de schemas da versão que você declara, no Portal da NF-e, e guarde junto do código, com o nome da versão.
  3. Assine o grupo infNFe com o certificado, carregado de um cofre de segredos ou variável de ambiente, nunca com a senha escrita no código.
  4. Valide o arquivo assinado contra o XSD. O schema da nota inclui o bloco da assinatura, então a validação faz mais sentido logo antes de transmitir.
  5. Confira a assinatura localmente, lendo o arquivo exatamente como ele será enviado.
  6. Transmita em homologação, com o ambiente marcado como homologação no XML, e leia os campos cStat e xMotivo do retorno.
  7. Guarde o XML autorizado com o protocolo, o retorno bruto e a versão do schema usada.

Validar contra o XSD antes de transmitir

Com o pacote de schemas extraído numa pasta, o xmllint, que vem com a libxml2, valida o arquivo em segundos. O nome exato do XSD principal depende do pacote que você baixou; confira na pasta.

xmllint --noout --schema schemas/nfe_v4.00.xsd nota-1532-assinada.xml

Quando passa, a saída diz que o arquivo valida. Quando falha, ela aponta o elemento, a regra e o valor. Na Ferragens Lima, o primeiro erro foi exatamente o CEP com hífen: a mensagem citava o elemento CEP, a faceta de padrão e o valor recusado. Corrigido no gerador, não no arquivo, o problema não voltou nas notas seguintes.

Coloque essa validação no pipeline de testes com algumas notas de exemplo de cada tipo de operação. Uma mudança no gerador que quebra o schema aparece no pull request, não na rejeição de sexta à noite.

Conferir a assinatura do jeito que ela será enviada

Em .NET, a mesma API que assina também confere. O detalhe que importa é PreserveWhitespace = true: sem ele, o carregamento descarta espaços e você confere um documento diferente do que vai transmitir.

using System;
using System.Security.Cryptography.Xml;
using System.Xml;

var doc = new XmlDocument { PreserveWhitespace = true };
doc.Load("nota-1532-assinada.xml");

var no = (XmlElement)doc.GetElementsByTagName("Signature", SignedXml.XmlDsigNamespaceUrl)[0];
var assinatura = new SignedXml(doc);
assinatura.LoadXml(no);

Console.WriteLine(assinatura.CheckSignature() ? "assinatura confere" : "assinatura NÃO confere");

Use a mesma regra ao gravar: depois de assinar, salve o documento sem formatação extra e sem passar por nenhuma etapa que "limpe" o XML. Se alguém precisa ler a nota indentada, gere uma cópia para leitura com outro nome e nunca a transmita.

Ler o retorno e guardar a prova

O webservice responde com um código de status em cStat e uma descrição em xMotivo. Grave os dois, junto com o XML enviado, antes de qualquer outra ação. Quando a nota é autorizada, o retorno traz o protocolo; o arquivo que vale como documento é o XML da nota unido ao protocolo de autorização, normalmente num envelope nfeProc. Esse é o arquivo que você guarda e entrega ao cliente.

Homologação existe para errar sem valor fiscal. Teste nela cada tipo de operação que o sistema emite, inclusive cancelamento e rejeições esperadas. O post sobre homologação que não é produção com outro endereço explica o que muda entre os ambientes.

Erros comuns

  • Formatar o XML depois de assinar: a indentação muda os nós de texto, o resumo recalculado não bate e a nota é rejeitada por assinatura.
  • Validar só "no olho" ou só no retorno do fisco: cada erro de schema custa uma ida e volta, e em produção cada ida e volta é uma venda parada.
  • Seguir exemplo de outra versão do leiaute: o XML parece certo, mas o schema que confere é o da versão declarada.
  • Senha do certificado A1 no código ou no repositório: quem tem o arquivo e a senha assina documentos fiscais em nome da empresa.
  • Copiar uma nota de produção para "ver como fica" em homologação, ou o contrário: ambiente errado gera rejeição no melhor caso e documento com valor fiscal indesejado no pior.
  • Não guardar o retorno bruto: sem cStat, xMotivo e protocolo, você não prova o que foi autorizado nem diagnostica o que falhou.

Checklist

  • O XML é gerado por serialização, não por concatenação de texto.
  • O pacote de schemas da versão declarada está versionado junto do código.
  • O arquivo assinado passa no xmllint antes de toda transmissão.
  • Nenhuma etapa depois da assinatura reformata, reindenta ou recodifica o XML.
  • A assinatura é conferida localmente com espaços preservados.
  • Certificado e senha vêm de cofre ou variável de ambiente, fora do código.
  • Cada tipo de operação foi autorizado em homologação, com protocolo.
  • XML autorizado, protocolo e retorno bruto ficam guardados juntos.

Isto descreve a parte técnica. Qual documento emitir, com quais dados fiscais, é decisão de quem responde pela contabilidade da empresa, e este texto não substitui um contador.

Pegue a última nota que o seu sistema chamou de pronta: existe um protocolo de autorização guardado ao lado dela, ou só um XML bonito numa pasta?

Avalie este artigo

Referência: http://www.linhadecodigo.com.br/artigo/1814/nota-fiscal-eletronica-geracao-assinatura-e-transmissao.aspx