integraciones
5 min de lectura · 15 oct 2026

Reintentos de pago sin cobrar dos veces

Un pago que falla por un error de red no siempre falló. Esta guía explica cómo reintentar cobros con claves de idempotencia y una máquina de estados, para que el cliente pague una sola vez.

Mateo Pizaialabs.app · publicado 15 oct 2026
Tarjeta de pago rodeada por una flecha circular cian de reintento junto a un único punto confirmado, sobre fondo oscuro.

El problema

Tu sistema envía un cobro a la pasarela. La respuesta no llega. Puede haber pasado cualquiera de estas cosas:

  1. La solicitud nunca llegó.
  2. Llegó y falló.
  3. Llegó, se cobró y la respuesta se perdió.

Si reintentas a ciegas en el caso 3, cobras dos veces. Si no reintentas en el caso 1, pierdes la venta. La idempotencia resuelve este dilema.

Qué es una clave de idempotencia

Es un identificador único que acompaña a una operación. Si el servidor recibe dos solicitudes con la misma clave, ejecuta la operación una vez y devuelve el mismo resultado en ambas.

Muchas pasarelas aceptan una clave de idempotencia o un identificador único de orden. Revisa la documentación de la tuya. Si no lo soporta, necesitas compensarlo con consulta de estado antes de reintentar.

Regla 1: la clave nace con la intención de pago

Genera la clave cuando creas la intención de cobro, antes de llamar a la pasarela. Guárdala en tu base de datos en la misma transacción.

with db.transaction():
    intento = Pago(orden_id=orden.id, valor=orden.total,
                   clave=uuid4(), estado="PENDIENTE")
    db.save(intento)
respuesta = pasarela.cobrar(valor=intento.valor, clave=intento.clave)

Cada reintento técnico usa la misma clave. Una clave nueva equivale a un cobro nuevo.

Regla 2: una máquina de estados explícita

solicitud enviadarespuesta o webhookrespuesta o webhooktimeoutconsulta de estadoconsulta de estadoreintento con misma clave

PENDIENTE

EN_PROCESO

APROBADO

RECHAZADO

DESCONOCIDO

diagrama · regla 2: una máquina de estados explícita

El estado DESCONOCIDO es el más importante. Nunca se trata como rechazo.

Regla 3: consulta antes de reintentar

Ante un timeout:

  1. Marca el pago como DESCONOCIDO.
  2. Consulta el estado en la pasarela por tu referencia o clave.
  3. Si está aprobado, actualiza y termina.
  4. Si no existe, reintenta con la misma clave.
  5. Si sigue sin respuesta, espera con backoff exponencial y vuelve al paso 2.

Ejemplo de backoff (supuesto): 2, 4, 8, 16 y 32 segundos, con variación aleatoria. Después del último, el pago pasa a revisión.

Regla 4: webhooks idempotentes

La pasarela puede enviar el mismo webhook varias veces. Tu receptor debe aguantarlo.

  • Guarda el id del evento con una restricción de unicidad.
  • Si el id ya existe, responde éxito y no proceses de nuevo.
  • Valida la firma del webhook antes de confiar en él.
  • Aplica la transición solo si es válida desde el estado actual.
def webhook(evento):
    verificar_firma(evento)
    if not db.insert_unique("eventos", evento.id):
        return 200
    pago = db.get_pago(evento.referencia, for_update=True)
    if transicion_valida(pago.estado, evento.estado):
        pago.estado = evento.estado; db.save(pago)
    return 200

Reintentos de negocio

Hay otro tipo de reintento. El pago fue rechazado de verdad, por ejemplo por fondos insuficientes, y quieres volver a intentar días después.

Ese es un intento nuevo, con clave nueva. Antes de crearlo:

  • Verifica que no haya un intento APROBADO para la misma orden.
  • Verifica que no haya un intento EN_PROCESO o DESCONOCIDO.
  • Respeta un número máximo de intentos y avisa al cliente.

Una restricción en base de datos ayuda: solo un intento APROBADO por orden.

Dónde entra un agente

Un agente de IA no debe decidir si se cobra. Esa lógica es determinista. Sí puede aportar en:

  • Redactar el aviso al cliente cuando un cobro falla.
  • Clasificar respuestas del cliente ("ya pagué por transferencia").
  • Revisar la cola de pagos DESCONOCIDOS antiguos y armar el resumen para finanzas.

El agente no tiene permisos para crear cobros. Llama a un servicio que aplica todas las reglas anteriores.

Pruebas que debes correr antes del deploy

Simula las fallas en un ambiente de pruebas de la pasarela:

  1. Corta la conexión justo después de enviar el cobro. El pago debe quedar en DESCONOCIDO y resolverse por consulta.
  2. Envía el mismo webhook tres veces. Solo una transición debe aplicarse.
  3. Envía un webhook de aprobado antes que la respuesta síncrona. El estado final debe ser APROBADO una sola vez.
  4. Lanza dos reintentos de negocio en paralelo para la misma orden. Uno debe fallar por la restricción de unicidad.
  5. Envía un webhook con firma inválida. Debe rechazarse y registrarse.

Si alguna prueba falla, el flujo no sale a producción.

Conciliación como red de seguridad

Aun con todo esto, concilia a diario. Busca:

  • Dos pagos aprobados para la misma orden.
  • Pagos aprobados en la pasarela sin registro en tu sistema.
  • Pagos marcados aprobados en tu sistema sin liquidación.

Cada hallazgo genera un caso. Un doble cobro detectado el mismo día se devuelve antes de que el cliente lo note.

Métricas

MétricaFórmula
Dobles cobrosórdenes con dos aprobados / órdenes
Pagos en DESCONOCIDOcantidad y antigüedad
Recuperación por reintento técnicoaprobados tras timeout / timeouts
Recuperación por reintento de negocioaprobados tras rechazo / reintentos
Webhooks duplicados descartadoseventos repetidos / eventos

La meta de dobles cobros es cero. Cualquier valor distinto abre una revisión.

Errores comunes

  • Generar una clave nueva en cada reintento.
  • Tratar el timeout como rechazo.
  • Procesar webhooks sin control de duplicados.
  • Confiar en webhooks sin firma.
  • Dejar al agente crear cobros directamente.

Checklist

Preguntas frecuentes

¿Y si mi pasarela no soporta idempotencia?

Usa tu propia referencia única por intento y consulta el estado antes de cada reintento. Es más lento, pero evita el doble cobro.

¿Cuánto tiempo guardo las claves?

Al menos el tiempo en que la pasarela puede enviar webhooks o aceptar consultas de ese pago. Revisa ese plazo en su documentación.

¿Aplica a pagos recurrentes?

Sí. Cada cobro de cada periodo tiene su clave, derivada de la suscripción y el periodo.

Fuentes

¿Quieres esto funcionando en tu empresa?
Si tu integración de pagos tiene reintentos manuales o dobles cobros ocasionales, revisamos el flujo y lo dejamos con estados e idempotencia.