Portal da NF-e não é arquivo: guarde e confira o XML autorizado do seu lado
Por que a consulta no portal não substitui o XML com protocolo que você guarda, como organizar esse arquivo e um script que confere se cada nota está completa e autorizada.
Uma distribuidora recebe uma intimação pedindo os XMLs das notas de um trimestre de três anos atrás. A equipe responde que "está tudo no portal". Na prática, as notas aparecem na consulta, mas a empresa não tem os arquivos: o emissor antigo foi trocado, a pasta ficava no servidor que foi desligado e o único lugar com XML era a caixa de e-mail de uma pessoa que já saiu. O portal é um serviço de consulta. O dever de guardar o XML autorizado é de quem emite.
A resposta curta: para cada nota, guarde o XML de distribuição (a nota assinada junto com o protocolo de autorização) e os eventos dela, como cancelamento e carta de correção, numa cópia que não seja só o e-mail e que sobreviva à troca de sistema. Confira periodicamente se cada nota emitida tem arquivo, se o arquivo está íntegro e autorizado, e anote no código a versão do leiaute.
Por que a consulta no portal não é o seu arquivo
A NF-e é um documento eletrônico assinado digitalmente pelo emissor e autorizado pela Secretaria da Fazenda. O valor jurídico está no arquivo XML assinado, acompanhado do protocolo de autorização. Uma tela de consulta mostra que a nota existe e qual a situação dela, mas não é o documento. Ela também não está sob o seu controle: pode mudar de formato, exigir outra forma de acesso ou ficar fora do ar no dia em que você precisar.
Há outro motivo, mais prático. O XML que o seu sistema montou e enviou é o único que prova exatamente o que foi emitido: valores, impostos, destinatário. Quando surge uma divergência com o cliente ou com o fisco, é esse arquivo que responde. O guia API de nota fiscal emite, quem guarda é você trata do mesmo dever quando a emissão é terceirizada; aqui o foco é organizar e conferir o arquivo.
O prazo de guarda é definido pela legislação tributária e pode variar conforme o caso. Confirme com o contador da empresa e use esse prazo como mínimo. Este guia é técnico e não substitui a orientação de um contador ou advogado tributarista.
O que guardar de cada nota
- O XML de distribuição, cujo elemento raiz é
nfeProc: contém a nota assinada (NFe) e o protocolo de autorização (protNFe). Só a nota, sem o protocolo, não prova a autorização. - Os eventos, cada um com seu protocolo: cancelamento, carta de correção e outros que a nota tiver.
- A chave de acesso de 44 dígitos como identificador, de preferência no nome do arquivo.
- A versão do leiaute com que a nota foi gerada, que já vem no atributo
versaodo XML e deve estar também no seu código.
Uma estrutura de pastas simples resolve a maioria dos casos: nfe/CNPJ/ANO/MES/CHAVE-procNFe.xml, com os eventos na mesma pasta, com sufixo próprio. Guarde em dois lugares, um deles fora do servidor do emissor (armazenamento de objetos com versionamento, por exemplo), e teste a restauração como qualquer backup, no espírito de backup que restaura de verdade.
Como montar a rotina, passo a passo
- No momento da autorização, o sistema grava o XML de distribuição no armazenamento definitivo antes de considerar a venda concluída. Se a gravação falhar, a nota fica marcada como pendente de arquivo.
- Grave os eventos do mesmo jeito, assim que forem homologados.
- Uma vez por mês, compare a lista de notas emitidas segundo o sistema com os arquivos existentes. Nota sem arquivo é incidente.
- Confira cada arquivo: abre como XML, tem protocolo, o código de situação é de autorização e a chave do protocolo bate com o nome do arquivo.
- Registre um hash de cada arquivo num manifesto. Na próxima conferência, um hash diferente indica arquivo alterado ou corrompido.
- Em caso de dúvida sobre a situação de uma nota, use o serviço oficial de consulta de protocolo pelo seu emissor, não a raspagem de tela do portal.
Script de conferência do arquivo
Este script em Python, só com biblioteca padrão, percorre uma pasta, confere cada XML de distribuição e grava um manifesto em CSV. O namespace e os nomes de elemento são os do leiaute da NF-e:
import csv
import hashlib
import sys
from pathlib import Path
import xml.etree.ElementTree as ET
NS = {'nfe': 'http://www.portalfiscal.inf.br/nfe'}
AUTORIZADA = {'100', '150'}
def conferir(caminho):
dados = caminho.read_bytes()
sha = hashlib.sha256(dados).hexdigest()
try:
raiz = ET.fromstring(dados)
except ET.ParseError as e:
return {'arquivo': caminho.name, 'sha256': sha, 'problema': 'XML inválido: ' + str(e)}
if raiz.tag != '{http://www.portalfiscal.inf.br/nfe}nfeProc':
return {'arquivo': caminho.name, 'sha256': sha, 'problema': 'sem protocolo (raiz não é nfeProc)'}
prot = raiz.find('nfe:protNFe/nfe:infProt', NS)
if prot is None:
return {'arquivo': caminho.name, 'sha256': sha, 'problema': 'protNFe ausente'}
chave = prot.findtext('nfe:chNFe', default='', namespaces=NS)
cstat = prot.findtext('nfe:cStat', default='', namespaces=NS)
problema = ''
if cstat not in AUTORIZADA:
problema = 'situação ' + cstat + ' não é autorização'
elif not caminho.name.startswith(chave):
problema = 'chave do protocolo não bate com o nome do arquivo'
return {
'arquivo': caminho.name,
'chave': chave,
'cstat': cstat,
'protocolo': prot.findtext('nfe:nProt', default='', namespaces=NS),
'sha256': sha,
'problema': problema,
}
pasta = Path(sys.argv[1])
linhas = [conferir(p) for p in sorted(pasta.rglob('*-procNFe.xml'))]
campos = ['arquivo', 'chave', 'cstat', 'protocolo', 'sha256', 'problema']
with open('manifesto.csv', 'w', newline='', encoding='utf-8') as f:
escritor = csv.DictWriter(f, fieldnames=campos)
escritor.writeheader()
escritor.writerows(linhas)
com_problema = [l for l in linhas if l.get('problema')]
print(len(linhas), 'arquivos conferidos,', len(com_problema), 'com problema')
for l in com_problema:
print(l['arquivo'], '-', l['problema'])
sys.exit(1 if com_problema else 0)
O código de situação 100 indica uso autorizado e o 150, autorização fora de prazo; a tabela completa de códigos está no Manual de Orientação do Contribuinte, publicado no portal da NF-e. Uma nota cancelada continua com o protocolo de autorização no XML de distribuição: o cancelamento é um evento à parte, e por isso o arquivo do evento precisa existir ao lado da nota. O script não confere a assinatura digital; para isso, use a validação do seu emissor ou uma biblioteca de assinatura XML.
Na distribuidora do exemplo, a primeira execução no arquivo recuperado mostrou 2.314 arquivos e 41 problemas: 37 notas salvas sem protocolo (só o XML enviado) e 4 com nome trocado. As 37 tiveram o XML de distribuição recuperado pelo emissor novo, a partir da chave. O manifesto passou a rodar todo dia 5.
Erros comuns
- Guardar só a nota, sem o protocolo. O arquivo não prova que a nota foi autorizada, e você descobre isso na hora de apresentá-lo.
- O e-mail como arquivo. A caixa da pessoa é apagada quando ela sai, e os XMLs vão junto.
- Raspar a tela do portal para montar a base. O formato muda sem aviso e o que você coleta não é o documento assinado.
- Esquecer os eventos. Uma nota cancelada parece válida no seu arquivo, porque o cancelamento não foi guardado.
- Arquivo só no servidor do emissor. A troca de sistema ou de fornecedor leva anos de notas embora.
- Versão do leiaute fora do código. Uma atualização obrigatória passa despercebida e as notas começam a ser rejeitadas, como lembra dica de nota fiscal tem data.
Checklist
- Cada nota autorizada tem o XML de distribuição com
nfeProce protocolo. - Eventos de cancelamento e correção estão guardados ao lado da nota.
- Os arquivos ficam em dois lugares, um fora do servidor do emissor.
- Existe conferência mensal entre notas emitidas e arquivos guardados.
- Um manifesto com hash de cada arquivo é gerado e comparado.
- O prazo de guarda foi confirmado com o contador.
- A restauração do arquivo de notas já foi testada.
Escolha uma nota emitida há dois anos e tente achá-la agora, sem abrir o portal: em quanto tempo você chega ao XML com o protocolo de autorização?
Referência: http://www.nfe.fazenda.gov.br/portal/principal.aspx