Skip to main content

El problema de los duplicados

Cuando tu sistema emite una factura y la conexión se cae antes de recibir la respuesta, ¿debes reintentar? Si lo haces sin precauciones, podrías generar dos facturas idénticas ante el SAT. La idempotencia es la propiedad que garantiza que enviar la misma solicitud más de una vez produce el mismo resultado: una sola factura, no varias.

La base técnica: cadena original y sello

Cadena Original

El SAT define un formato de concatenación (mediante un XSLT) que convierte todos los campos del CFDI en una sola cadena de texto plano. Esa cadena es la Cadena Original. Incluye, entre otros campos:
  • Versión
  • Fecha
  • Sello
  • FormaPago
  • NoCertificado
  • Certificado
  • Subtotal
  • Moneda
  • Total
  • Tipo de Comprobante
  • Exportación
  • Método de Pago
  • LugarExpedición
  • Datos del Emisor
  • Datos del Receptor
  • Conceptos y sus detalles (descripción, cantidad, valor unitario, importe, etc.)
  • Impuestos (transferidos y retenidos).
Ejemplo de un fragmento de la cadena original podría tener este aspecto:

Sello Digital del Emisor

La Cadena Original se procesa con SHA-256 y el resultado se firma con la llave privada del CSD del emisor usando RSA:
Este sello garantiza tres propiedades:

Validación del PAC

Antes de certificar el CFDI, el PAC verifica:
  1. La estructura XML es válida (esquemas XSD del SAT)
  2. El SelloDigital corresponde al CSD del emisor
  3. El CFDI no fue timbrado previamente (unicidad)
Si el mismo XML llega dos veces al PAC, el segundo intento es rechazado porque el sello ya fue registrado.

El UUID como identificador único

El PAC genera un UUID (Folio Fiscal) al timbrar. Este UUID es único a nivel nacional y queda registrado en el SAT:
Es el dato definitivo para identificar un CFDI. No puede repetirse, no puede ser reutilizado y permanece en los registros del SAT aunque el CFDI sea cancelado.

Cómo funciona la idempotencia en la API Web

La API Web de Facturama (un RFC emisor) tiene tres campos que si no se especifican, son generados automáticamente en cada llamada: Si omites estos campos y haces dos llamadas con el mismo JSON, Facturama genera dos CFDIs distintos porque Date y Folio cambian. Esto rompe la idempotencia.

Cómo implementar idempotencia en API Web

Especifica explícitamente los tres campos antes de enviar: Folio, Date y para Carta Porte IdCCP
Con Date y Folio fijos, el XML resultante es idéntico en todos los reintentos. El PAC detectará el duplicado y rechazará el segundo intento y la API mostrará la factura que ya había sido timbrada previamente con los mismos datos.
Puedes usar el Folio como clave de idempotencia en tu base de datos. Si ya existe un CFDI con ese folio, no vuelvas a enviarlo.

El campo IdCCP

Para CFDIs con complemento Carta Porte, existe un campo adicional IdCCP que identifica la carta porte:
Si no lo especificas, se genera uno nuevo en cada llamada. Especifícalo para garantizar que el complemento de Carta Porte sea idéntico en los reintentos.

Cuándo usar la idempotencia

Aplica la estrategia de idempotencia cuando el error es recuperable por reintento:
Ante un error 5xx o un timeout, no asumir que la factura no se creó. Primero consulta si existe un CFDI con ese folio antes de reintentar. Si ya existe, usa el UUID existente.

Flujo recomendado

Para API multiemisor se utiliza type = issedLite