Problema observado
En producción, al seleccionar Continue with Mercado Pago la interfaz mostró:
Membership is not available for purchase right now.
La evidencia operativa indicó un conflicto de checkout pendiente, no indisponibilidad general de Mercado Pago. El mensaje actual colapsa estados distintos —sesión vencida, checkout existente, membresía vigente, idempotencia, proveedor caído o configuración deshabilitada— en un mismo error genérico y no ofrece una acción para continuar.
Esto impide que la persona sepa si puede:
- retomar el checkout ya creado;
- cambiar de PayPal a Mercado Pago o viceversa;
- descartar un intento pendiente;
- volver a autenticarse;
- esperar y reintentar por una falla real del proveedor.
Objetivo
Presentar el estado correcto y acciones server-authoritative sin generar checkouts duplicados, suscripciones huérfanas ni cobros inesperados.
Estados y UX requeridos
Checkout pendiente del mismo proveedor
Mostrar que ya existe un proceso pendiente y ofrecer:
- Continuar con el checkout existente.
- Cancelar por ahora.
Reutilizar la approval URL persistida sólo después de validarla y nunca crear otra operación.
Checkout pendiente de otro proveedor
Mostrar qué medio está pendiente y ofrecer:
- Continuar con el medio existente.
- Cambiar a PayPal/Mercado Pago.
- Cancelar por ahora.
Cambiar de medio debe retirar/cancelar de forma segura el intento anterior tanto en la autoridad como en el proveedor cuando corresponda, antes de habilitar uno nuevo.
Membresía vigente o paid-through
No mostrar compra indisponible. Explicar que la cuenta ya tiene acceso y enlazar a Account para ver o administrar la membresía.
Sesión vencida
Pedir autenticación y volver una sola vez al estado de membresía, sin loop ni perder la intención.
Proveedor realmente indisponible
Sólo en este caso usar un mensaje de indisponibilidad temporal, identificando PayPal o Mercado Pago y permitiendo reintento acotado.
Configuración comercial deshabilitada
No renderizar un botón que el servidor sabe que no puede funcionar.
Contrato backend
- Respuestas tipadas y estables, por ejemplo: pending_checkout_same_provider, pending_checkout_other_provider, membership_already_active, sign_in_required, provider_unavailable, checkout_disabled e idempotency_conflict.
- No exponer payer email, account ID, external subscription ID, approval URL en errores ni detalles del proveedor.
- Una sola autoridad decide si el checkout se puede continuar, retirar o reemplazar.
- Continuar y cambiar son idempotentes ante doble clic, refresh y reconexión.
- Registrar métricas por provider/outcome sin PII y con correlación operativa acotada.
Criterios de aceptación
- El caso observado muestra checkout pendiente y las opciones correspondientes, nunca la falsa indisponibilidad general.
- PayPal pendiente → Mercado Pago y Mercado Pago pendiente → PayPal funcionan sin bindings o preapprovals huérfanos.
- Múltiples clics, Back, refresh, dos pestañas y timeout no crean operaciones duplicadas.
- Una approval URL vencida no se reutiliza; la autoridad ofrece recuperación o reemplazo seguro.
- Membresía activa/cancelled-pending-end/expired presenta acciones coherentes con su estado.
- Errores 401, 409, 422, 503 y timeout tienen copy ES/EN específico y accesible.
- Pruebas unitarias, PostgreSQL, contrato, integración y navegador cubren ambos proveedores y staging/live.
- No se modifica el precio Founder, pagos reales existentes, paid-through, cuotas ni acceso durante la corrección.
- El deploy conserva rollback verificable y smoke de ambos proveedores sin completar un cobro real.
Problema observado
En producción, al seleccionar Continue with Mercado Pago la interfaz mostró:
La evidencia operativa indicó un conflicto de checkout pendiente, no indisponibilidad general de Mercado Pago. El mensaje actual colapsa estados distintos —sesión vencida, checkout existente, membresía vigente, idempotencia, proveedor caído o configuración deshabilitada— en un mismo error genérico y no ofrece una acción para continuar.
Esto impide que la persona sepa si puede:
Objetivo
Presentar el estado correcto y acciones server-authoritative sin generar checkouts duplicados, suscripciones huérfanas ni cobros inesperados.
Estados y UX requeridos
Checkout pendiente del mismo proveedor
Mostrar que ya existe un proceso pendiente y ofrecer:
Reutilizar la approval URL persistida sólo después de validarla y nunca crear otra operación.
Checkout pendiente de otro proveedor
Mostrar qué medio está pendiente y ofrecer:
Cambiar de medio debe retirar/cancelar de forma segura el intento anterior tanto en la autoridad como en el proveedor cuando corresponda, antes de habilitar uno nuevo.
Membresía vigente o paid-through
No mostrar compra indisponible. Explicar que la cuenta ya tiene acceso y enlazar a Account para ver o administrar la membresía.
Sesión vencida
Pedir autenticación y volver una sola vez al estado de membresía, sin loop ni perder la intención.
Proveedor realmente indisponible
Sólo en este caso usar un mensaje de indisponibilidad temporal, identificando PayPal o Mercado Pago y permitiendo reintento acotado.
Configuración comercial deshabilitada
No renderizar un botón que el servidor sabe que no puede funcionar.
Contrato backend
Criterios de aceptación