Saltar al contenido

VeriFactu en un ERP real: cómo enviamos facturas a la AEAT

Cómo integramos el envío de registros de facturación a la AEAT en un ERP en producción: arquitectura, huella encadenada, colas y errores reales.

TécnicoPublicado 2 min de lectura

Borrador. Este texto es solo un esqueleto con la estructura propuesta. Los apartados marcados con [Completar] deben escribirse con la experiencia real del proyecto antes de publicar.

Contexto y alcance

[Completar] Qué ERP es, qué volumen de facturas mueve al mes, qué módulos emiten facturas y qué obligaba al cambio. Conviene enlazar a la normativa vigente y comprobar los plazos de aplicación antes de publicar, porque han cambiado.

Qué exige el sistema de verdad

Antes de escribir código, lo que hay que tener claro:

  • Cada factura genera un registro de facturación (alta, y anulación si procede) que el sistema conserva y remite.
  • Los registros se encadenan mediante una huella que depende del registro anterior, de modo que no se puede alterar el histórico sin que se note.
  • La factura impresa o en PDF lleva un código QR que permite al cliente cotejarla.
  • El envío se hace a un servicio web de la AEAT autenticado con certificado electrónico.

[Completar] Contrastar cada punto con la especificación técnica vigente y citar el documento y la versión.

Arquitectura de la integración

[Completar] Diagrama de componentes: ERP, generador de registros, cola de envío, cliente del servicio web, almacén de respuestas.

La decisión de diseño más importante fue desacoplar la emisión de la factura del envío: la factura se emite y se registra siempre, y el envío se reintenta de forma asíncrona.

Generación del registro y huella encadenada

Ejemplo simplificado de cómo se encadena un registro con el anterior. No es la especificación oficial: los campos y el formato exactos están en la documentación técnica de la AEAT.

import { createHash } from "node:crypto";

interface Registro {
  idFactura: string;
  importeTotal: string;
  huellaAnterior: string; // vacía en el primer registro
}

export function huella(r: Registro): string {
  const cadena = `${r.idFactura}|${r.importeTotal}|${r.huellaAnterior}`;
  return createHash("sha256").update(cadena, "utf8").digest("hex").toUpperCase();
}

[Completar] Qué hacemos para que dos procesos concurrentes no rompan la cadena (bloqueo, secuencia por serie, transacción).

Cola de envío y reintentos

[Completar] Estados de un registro (pendiente, enviado, aceptado, rechazado), política de reintentos con espera creciente y qué hacemos cuando la AEAT no responde.

Errores reales y cómo los resolvimos

[Completar] Tabla o lista de los rechazos más habituales, su causa y la corrección. Es la sección que más valor aporta a otros desarrolladores.

Pruebas y puesta en producción

[Completar] Uso del entorno de pruebas de la AEAT, datos de prueba, ensayo con facturas reales, plan de vuelta atrás.

Qué haríamos distinto

[Completar] Tres aprendizajes concretos.

Conclusiones

[Completar] Resumen en tres líneas y llamada a la acción: si necesitas adaptar tu ERP, hablamos.

Artículos relacionados