Gestionar pagos de suscripción fallidos
Cuando un pago recurrente de una suscripción falla, MONEI reintenta automáticamente el cobro según un calendario de reintentos. Este proceso — conocido como dunning — ayuda a recuperar los pagos fallidos antes de cancelar la suscripción.
Cómo funcionan los reintentos
- Un pago recurrente falla (p. ej., fondos insuficientes, tarjeta caducada).
- La suscripción pasa al estado
PAST_DUEy se envía un webhookSUBSCRIPTION_PAST_DUE. - MONEI reintenta el pago según el calendario de reintentos.
- Si un reintento tiene éxito, la suscripción vuelve a
ACTIVEy la facturación continúa con normalidad. - Si se agotan todos los reintentos, la suscripción se
CANCELEDy se envía un webhookSUBSCRIPTION_CANCELED.
Calendario de reintentos predeterminado
MONEI utiliza calendarios de reintentos diferentes según el intervalo de facturación:
| Intervalo de facturación | Reintento 1 | Reintento 2 | Reintento 3 |
|---|---|---|---|
| Día | +1 hora | +2 horas | +3 horas |
| Semana, Mes, Año | +1 día | +5 días | +9 días |
Cada intervalo de reintento se cuenta desde el intento anterior, no desde el fallo inicial. Por ejemplo, si falla un pago de una suscripción mensual:
- Reintento 1 — 1 día después del fallo inicial
- Reintento 2 — 5 días después del reintento 1 (6 días en total)
- Reintento 3 — 9 días después del reintento 2 (15 días en total)
- Si los 3 reintentos fallan, la suscripción se cancela
En modo de prueba, los intervalos minute y hour usan calendarios de reintentos más cortos (minutos en lugar de horas/días) para pruebas más rápidas.
Calendario de reintentos personalizado
Puedes sobrescribir el calendario de reintentos predeterminado al crear o actualizar una suscripción usando el parámetro retrySchedule.
Cada entrada del array define un intervalo de reintento:
- cURL
- Node.js
- PHP
- Python
curl --request POST 'https://api.monei.com/v1/subscriptions' \
--header 'Authorization: YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data-raw '{
"amount": 1500,
"currency": "EUR",
"interval": "month",
"intervalCount": 1,
"callbackUrl": "https://example.com/subscriptions/callback",
"paymentCallbackUrl": "https://example.com/payments/callback",
"retrySchedule": [
{"interval": "day", "intervalCount": 1},
{"interval": "day", "intervalCount": 3},
{"interval": "day", "intervalCount": 7},
{"interval": "day", "intervalCount": 14}
]
}'
const subscription = await monei.subscriptions.create({
amount: 1500,
currency: 'EUR',
interval: 'month',
intervalCount: 1,
callbackUrl: 'https://example.com/subscriptions/callback',
paymentCallbackUrl: 'https://example.com/payments/callback',
retrySchedule: [
{interval: 'day', intervalCount: 1},
{interval: 'day', intervalCount: 3},
{interval: 'day', intervalCount: 7},
{interval: 'day', intervalCount: 14}
]
});
<?php
$subscription = $monei->subscriptions->create(
new CreateSubscriptionRequest([
'amount' => 1500,
'currency' => 'EUR',
'interval' => 'month',
'interval_count' => 1,
'callback_url' => 'https://example.com/subscriptions/callback',
'payment_callback_url' => 'https://example.com/payments/callback',
'retry_schedule' => [
['interval' => 'day', 'interval_count' => 1],
['interval' => 'day', 'interval_count' => 3],
['interval' => 'day', 'interval_count' => 7],
['interval' => 'day', 'interval_count' => 14]
]
])
);
?>
subscription = monei.subscriptions.create(
CreateSubscriptionRequest(
amount=1500,
currency="EUR",
interval="month",
interval_count=1,
callback_url="https://example.com/subscriptions/callback",
payment_callback_url="https://example.com/payments/callback",
retry_schedule=[
{"interval": "day", "interval_count": 1},
{"interval": "day", "interval_count": 3},
{"interval": "day", "interval_count": 7},
{"interval": "day", "interval_count": 14}
]
)
)
Este ejemplo reintenta tras 1 día, 3 días, 7 días y 14 días — dando al cliente más tiempo para resolver el problema con su pago.
En los calendarios de reintentos personalizados, la duración total no puede superar el intervalo de facturación de la suscripción. Por ejemplo, una suscripción diaria no puede tener reintentos que abarquen más de 1 día.
Eventos de webhook
MONEI envía notificaciones de webhook en cada etapa del proceso de reintentos:
| Evento | Cuándo | Enviado a |
|---|---|---|
| Callback de pago | Cada intento de reintento (éxito o fallo) | paymentCallbackUrl |
SUBSCRIPTION_PAST_DUE | Primer fallo de pago | callbackUrl |
SUBSCRIPTION_ACTIVATED | El reintento tiene éxito, la suscripción se recupera | callbackUrl |
SUBSCRIPTION_CANCELED | Se agotan todos los reintentos | callbackUrl |
Usa estos webhooks para:
- Notificar a los clientes sobre pagos fallidos e invitarles a actualizar su método de pago
- Actualizar tu sistema cuando una suscripción se recupera o se cancela
- Registrar los intentos de reintento para análisis
Recuperar una suscripción vencida
Si una suscripción está en estado PAST_DUE, puedes recuperarla estableciendo skipIntervalCount a través del endpoint actualizar suscripción. Esto indica al sistema que omita el ciclo de facturación fallido y pase al siguiente — la suscripción vuelve a ACTIVE y el contador de reintentos se resetea.
- cURL
- Node.js
- PHP
- Python
curl --request PUT 'https://api.monei.com/v1/subscriptions/YOUR_SUBSCRIPTION_ID' \
--header 'Authorization: YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data-raw '{
"skipIntervalCount": 1
}'
const subscription = await monei.subscriptions.update('YOUR_SUBSCRIPTION_ID', {
skipIntervalCount: 1
});
<?php
use Monei\Model\UpdateSubscriptionRequest;
$subscription = $monei->subscriptions->update(
'YOUR_SUBSCRIPTION_ID',
new UpdateSubscriptionRequest([
'skip_interval_count' => 1
])
);
?>
from Monei import UpdateSubscriptionRequest
subscription = monei.subscriptions.update(
"YOUR_SUBSCRIPTION_ID",
UpdateSubscriptionRequest(
skip_interval_count=1
)
)
Esto es útil cuando un cliente ha actualizado su método de pago (mediante reactivación) y quieres omitir el ciclo fallido en lugar de esperar al siguiente reintento.
Notificaciones por correo electrónico
MONEI puede enviar automáticamente notificaciones por correo electrónico a los clientes y administradores de la cuenta cuando se producen eventos de suscripción:
- Correos al cliente — notifican al cliente cuando cambia el estado de su suscripción (p. ej., pago fallido, suscripción pausada)
- Correos al administrador — notifican a los administradores de la cuenta sobre los eventos de suscripción
Estos se configuran en los ajustes de notificaciones del MONEI Dashboard. No se requieren cambios de código.
MONEI también envía alertas automáticas al correo de la cuenta cuando la entrega de webhooks a tu callbackUrl falla repetidamente en modo producción.
Probar pagos fallidos
Usa el número de tarjeta de prueba que termina en 5565 para simular pagos recurrentes fallidos:
- Crea y activa una suscripción en modo de prueba usando la tarjeta de prueba
4242 4242 4242 5565. - El pago inicial tiene éxito — la suscripción pasa a
ACTIVE. - El primer pago recurrente falla — la suscripción pasa a
PAST_DUE. - MONEI reintenta según el calendario de reintentos. Todos los reintentos fallarán con esta tarjeta de prueba.
- Después de 3 reintentos fallidos, la suscripción se cancela automáticamente.
Esto te permite verificar la gestión de webhooks para los eventos SUBSCRIPTION_PAST_DUE y SUBSCRIPTION_CANCELED, y probar cualquier flujo de notificación al cliente que hayas implementado.
Usa intervalos de facturación minute u hour en modo de prueba para acelerar el ciclo de reintentos en lugar de esperar días.