Skip to content

borjamrd/verifactu-conformance

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Kit de conformidad Verifactu

Los vectores de prueba oficiales de la AEAT, listos para meter en el CI de tu librería.

Si estás implementando Verifactu —en Node, PHP, Python, .NET, Java, Go o lo que sea— tienes un problema: ¿cómo sabes que tu huella es la que calcula Hacienda? La especificación trae ejemplos, pero están dentro de un PDF. Aquí los tienes en JSON, con su procedencia y su referencia al documento oficial.

No es una librería más. Es el banco de pruebas que cualquier librería puede usar.

Qué hay dentro

fixtures/huella.json   Los 3 vectores oficiales de la huella (SHA-256), con su cadena canónica.
fixtures/qr.json       URLs de QR válidas e inválidas, con los códigos de error esperados.
src/                   Implementación de referencia en TypeScript (opcional: los fixtures son
                       agnósticos del lenguaje).

Los fixtures son JSON plano. No necesitas JavaScript para usarlos: cárgalos desde tu suite en el lenguaje que sea.

Úsalos en cualquier lenguaje

Descarga fixtures/huella.json y recorre sus casos. Cada uno trae los campos en orden, la cadena canónica que se debe construir con ellos, y la huella que debe salir:

{
  "id": "alta-primer-registro",
  "procedencia": "oficial",
  "referencia": "apartado 6.1",
  "tipo": "alta",
  "campos": [
    { "nombre": "IDEmisorFactura", "valor": "89890001K" },
    { "nombre": "NumSerieFactura", "valor": "12345678/G33" },
    ""
  ],
  "cadena": "IDEmisorFactura=89890001K&NumSerieFactura=12345678/G33&…&Huella=&FechaHoraHusoGenRegistro=2024-01-01T19:20:30+01:00",
  "huella": "3C464DAF61ACB827C65FDA19F352A4E3BDC2C640E9E9FC4CC058073F38F12F60"
}

Ejemplo en Python:

import hashlib, json

casos = json.load(open("fixtures/huella.json"))["casos"]

for caso in casos:
    cadena = "&".join(f'{c["nombre"]}={c["valor"]}' for c in caso["campos"])
    assert cadena == caso["cadena"], caso["id"]

    huella = hashlib.sha256(cadena.encode("utf-8")).hexdigest().upper()
    assert huella == caso["huella"], caso["id"]

print(f"{len(casos)} casos conformes")

Ejemplo en TypeScript, con la implementación de referencia:

import { CASOS_HUELLA, calcularHuella } from "verifactu-conformance";

for (const caso of CASOS_HUELLA) {
  const huella = await calcularHuella(caso.campos);
  if (huella !== caso.huella) throw new Error(`No conforme: ${caso.id}`);
}

Las tres trampas que este kit te ahorra

El campo NIF aparece dos veces en los registros de evento (posiciones 1 y 6): una para el sistema informático y otra para el obligado a emitir. Si modelas los campos como un mapa nombre → valor, el segundo pisa al primero y la huella sale mal. Los campos son una lista ordenada, no un objeto. Por eso los fixtures los publican como array.

123.1 y 123.10 son ambos válidos. La norma dice que en los campos numéricos los ceros a la derecha no son relevantes. Producen hashes distintos, y la AEAT acepta los dos. Un verificador que solo pruebe el literal del XML dará falsos negativos.

Un & sin codificar en el número de serie parte la URL del QR y crea un parámetro que no existe: la factura deja de poder cotejarse. Debe ir como %26. Es el error que la propia AEAT publica como ejemplo de URL incorrecta, y está en los fixtures con su URL corregida al lado.

De dónde sale cada caso

Cada caso declara su procedencia:

  • oficial — es un ejemplo literal de un documento de la AEAT, con su referencia al apartado. Los tres casos de la huella son oficiales.
  • derivado — no es un ejemplo literal: es un caso construido a partir de una regla de la norma (por ejemplo, que el importe use punto decimal). Sigue siendo correcto, pero lo decimos claramente en vez de dártelo como si viniera del BOE.

Esa distinción está ahí a propósito. Un kit de conformidad que confunde lo que dice la norma con lo que interpreta su autor no vale para nada.

Fuentes

Marco legal: Real Decreto 1007/2023 y Orden HAC/1177/2024. Fechas de exigibilidad: 1 de enero de 2027 (Impuesto sobre Sociedades) y 1 de julio de 2027 (autónomos y resto), tras el aplazamiento del Real Decreto-ley 15/2025.

Alcance

Este kit solo valida. No emite facturas, no envía nada a la AEAT y no es un Sistema Informático de Facturación. Sirve para comprobar que tu implementación calcula bien la huella y construye bien el QR: la responsabilidad de cumplir la norma sigue siendo de tu software y de su fabricante.

Contribuir

Si encuentras un caso que la norma cubre y aquí falta, abre un issue o un PR. Dos condiciones: que venga con su referencia al documento oficial, y que declare su procedencia.

Si crees que un fixture está mal, dilo cuanto antes: es lo peor que le puede pasar a este repositorio, y se arregla el mismo día.

Herramientas

Los mismos fixtures alimentan Cotejo, donde puedes verificar tu cadena de hash y validar tu QR desde el navegador, sin subir nada a ningún servidor.


MIT. Úsalo como quieras.

About

Kit de conformidad Verifactu: los vectores de prueba oficiales de la AEAT, listos para el CI de cualquier librería.

Topics

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages