Intentos de Pago (Payment Retry)
El sistema de retry procesa automáticamente intentos de cobro para facturas en atraso.
Estados del Intento
| Status | Descripción |
|---|---|
pending | Esperando procesamiento |
processing | Siendo procesado (reclamado por el worker) |
succeeded | Pago exitoso |
failed | Pago rechazado, más intentos disponibles |
exhausted | Máximo de intentos alcanzado |
Campos del Intento
| Campo | Descripción |
|---|---|
| Factura | Factura asociada |
| Pago | Registro de pago creado |
| Número del intento | Secuencial (1, 2, 3...) |
| Método de pago | Método utilizado en el intento |
| Valor (centavos) | Valor a ser cobrado |
| Código de fallo | Motivo del rechazo |
| Mensaje de fallo | Descripción detallada del error |
| Programado para | Fecha/hora del intento |
| Procesado en | Fecha/hora del procesamiento |
| Próximo retry en | Cuándo el próximo intento será realizado |
Worker de Retry
El worker se ejecuta cada 6 horas y:
- Busca intentos con
status=pendingyscheduledFor ≤ ahora - Reclama atómicamente cada intento (
pending → processing) para evitar duplicación - Para cada intento:
- Verifica si la factura ya fue pagada (omite)
- Crea registro de pago
- Procesa el pago vía gateway
- En caso de éxito:
- Marca la factura como pagada
- Crea registro de recuperación
- Elimina la cuenta de la lista de morosos
- En caso de fallo:
- Si hay intentos restantes: programa el próximo
- Si agotó los intentos: marca como
exhaustedy suspende la cuenta (si está configurado)
Prevención de Condiciones de Carrera
El sistema usa updateMany atómico con verificación de status para garantizar que solo un worker procese cada intento:
WHERE id = X AND status = 'pending'
SET status = 'processing'
Si count = 0, otro worker ya reclamó el intento.
Retry para Cuotas
Los intentos también pueden ser dirigidos a cuotas específicas:
- El
metadata.installmentIdidentifica la cuota - El valor del intento es el de la cuota, no el de la factura completa