Como funciona o hash do Verifactu
O que diz o documento técnico da AEAT, explicado para quem o tem de programar.
Que campos entram e por que ordem
O hash de um registo de alta calcula-se sobre oito campos do XML, por esta ordem: IDEmisorFactura, NumSerieFactura, FechaExpedicionFactura, TipoFactura, CuotaTotal, ImporteTotal, Huella (a do registo anterior) e FechaHoraHusoGenRegistro.
O registo de anulação usa cinco: IDEmisorFacturaAnulada, NumSerieFacturaAnulada, FechaExpedicionFacturaAnulada, Huella e FechaHoraHusoGenRegistro. O registo de evento, que só existe na modalidade NO VERI*FACTU, usa nove, começando pelos dados do sistema informático.
Como se constrói a cadeia
Cada campo escreve-se como nome=valor e os campos unem-se com &. Aos valores retiram-se os espaços do início e do fim. Se um campo não tiver valor, escreve-se só o nome e o sinal de igual: no primeiro registo do sistema, o hash anterior vai como Huella=. A cadeia é codificada em UTF-8 e aplica-se-lhe SHA-256; o resultado vai em hexadecimal e em maiúsculas, 64 caracteres.
IDEmisorFactura=89890001K&NumSerieFactura=12345678/G33&FechaExpedicionFactura=01-01-2024&TipoFactura=F1&CuotaTotal=12.35&ImporteTotal=123.45&Huella=&FechaHoraHusoGenRegistro=2024-01-01T19:20:30+01:00
→ 3C464DAF61ACB827C65FDA19F352A4E3BDC2C640E9E9FC4CC058073F38F12F60
Porque se encadeia
Cada registo leva o hash do anterior, por isso alterar uma fatura antiga parte todos os hashes posteriores. É por isso que a cadeia é por sistema e instalação, e que dois processos que faturam ao mesmo tempo têm de serializar o cálculo: se dois registos apanharem o mesmo hash anterior, a cadeia bifurca-se.
Na modalidade VERI*FACTU, a AEAT recalcula o hash de cada registo que recebe. Se não coincidir com o teu, o registo fica «Aceptado con errores» (aceite com erros).
E o QR
O QR da fatura contém uma URL do serviço de verificação (cotejo) da AEAT com quatro parâmetros: nif, numserie, fecha (DD-MM-AAAA, com hífenes) e importe (com ponto decimal). Os valores vão com URL encoding em UTF-8: um número de série como 12345678&G33 tem de viajar como 12345678%26G33.
O caminho muda conforme a modalidade: ValidarQR para VERI*FACTU e ValidarQRNoVerifactu para NO VERI*FACTU, em www2.agenciatributaria.gob.es (produção) ou prewww2.aeat.es (testes). O parâmetro opcional formato=json serve para integrações, mas nunca pode ir no QR impresso.
Testámo-lo a 7 de outubro de 2026 contra o serviço de verificação do ambiente de testes da AEAT: a URL que esta ferramenta gera com 12345678&G33 é aceite e a Agência lê bem o número de série, e um montante com vírgula devolve o mesmo erro 2005 que aqui te assinalamos.