La huella VeriFactu no coincide: 9 errores típicos y cómo detectarlos
SHA-256 no perdona: basta un carácter distinto en la cadena para obtener una huella completamente diferente. Si tu resultado no cuadra, el problema casi nunca es el algoritmo, sino el texto que le pasas.
Calcula el caso 1 de la AEAT. Debe darte 3C464DAF61ACB827C65FDA19F352A4E3BDC2C640E9E9FC4CC058073F38F12F60. Si no te da eso, el fallo está en cómo construyes la cadena o en cómo aplicas SHA-256. Tienes la cadena exacta en la guía de la huella.
Todos los ejemplos de esta página parten del caso 1 y cambian un solo detalle, para que veas que cualquier diferencia cambia la huella entera.
1. Importes con otro formato
Es el error más común. La huella usa el texto del importe, no su valor numérico:
ImporteTotal | Huella resultante |
|---|---|
123.45 | 3C464DAF…F12F60 (la correcta) |
123.40 | A6E02E87…830372 |
123.4 | 435A16D5…13F1AE |
123,40 | 3B1369D7…61D00C |
Solución: formatea siempre con punto y dos decimales (number_format($x, 2, '.', '') en PHP, x.toFixed(2) en JavaScript) y usa ese mismo texto en el XML. Revisa también CuotaTotal: si hay varios tipos de IVA, es la suma de todas las cuotas.
2. Fecha de expedición en otro formato
FechaExpedicionFactura va como DD-MM-AAAA (01-01-2024). Muchos sistemas guardan las fechas como 2024-01-01 o con barras (01/01/2024). Conviértela antes de montar la cadena.
3. Marca temporal en UTC o sin huso horario
FechaHoraHusoGenRegistro lleva el huso dentro del texto: 2024-01-01T19:20:30+01:00. El mismo instante escrito en UTC (2024-01-01T18:20:30+00:00) da otra huella: 84389B4E…F1C5D3.
Causas típicas:
- El servidor trabaja en UTC y el código usa la hora del sistema en lugar de la de España.
- En WordPress, la zona horaria del sitio sigue en UTC, que es el valor por defecto de una instalación nueva. Ve a Ajustes › Generales y elige Madrid (o Canarias).
- Se usa un desfase fijo como
UTC+1, que no cambia al horario de verano. - La hora se escribe con
Zal final o con milisegundos. Usa el formato con segundos y el huso con dos puntos.
4. Espacios al principio o al final
Un espacio pegado al NIF o a la serie ("89890001K ") cambia la huella. Recorta cada valor antes de concatenarlo. Los espacios que estén dentro del valor, en cambio, se mantienen.
5. Codificación distinta de UTF-8
Si la serie o el NIF tienen caracteres fuera del ASCII básico, como la ñ o letras acentuadas, la cadena debe pasarse a bytes en UTF-8. Si tu entorno usa Latin-1 o Windows-1252, esos caracteres producen otros bytes y otra huella.
6. Codificar la cadena como URL
La cadena de la huella no se codifica como URL. La serie 12345678/G33 va con su barra, no como 12345678%2FG33. La codificación solo se aplica a la URL del código QR.
7. Resultado en minúsculas
La mayoría de librerías devuelven el hexadecimal en minúsculas (3c464daf…). La huella se expresa en mayúsculas. Si comparas cadenas, conviértela antes. Si la vas a encadenar, recuerda que el siguiente registro incluirá este texto tal cual.
8. Campos en otro orden o que faltan
El orden es fijo, y el campo Huella se incluye siempre, aunque vaya vacío (…&Huella=&FechaHoraHusoGenRegistro=…). Un error frecuente es omitirlo en el primer registro, u olvidar que la anulación tiene su propio conjunto de cinco campos (IDEmisorFacturaAnulada, NumSerieFacturaAnulada, FechaExpedicionFacturaAnulada, Huella y FechaHoraHusoGenRegistro).
9. Encadenar con el registro equivocado
El campo Huella lleva la huella del último registro generado por el sistema, sea de alta o de anulación. Errores habituales:
- Encadenar por serie. No hay una cadena por cada serie de facturas.
- Saltarse las anulaciones. Tras anular una factura, la siguiente alta encadena con la huella de la anulación.
- Condiciones de carrera. Dos facturas emitidas a la vez leen la misma “última huella” y la cadena se bifurca. Hace falta un bloqueo mientras se lee la última huella y se guarda la nueva.
- Leer la huella de una caché. La última huella debe leerse de la base de datos en el momento de generar el registro.
Imprime la cadena exacta antes de aplicar SHA-256, entre comillas para ver los espacios, y compárala carácter a carácter con la que genera el validador para los mismos datos. La primera diferencia te dice cuál de estos errores tienes.
Compara tu cadena con la correcta
El validador te muestra la cadena canónica, la huella y la URL del QR de cualquier registro, y avisa de los errores de formato (importes, fechas, marca temporal, NIF). Funciona en tu navegador.