Saltar al contenido
DedicatedPHP Contactar

Estados de suscripción recuperables para un SaaS

Diseñe estados de suscripción recuperables para separar cobro, contrato y acceso, y corregir eventos de pago tardíos o duplicados.

Diagrama editorial de un flujo SaaS que separa contrato, ciclo de pago y capacidades de acceso

Un proveedor de pagos puede confirmar un cargo con retraso, enviar el mismo evento más de una vez o dejar una operación a medio procesar. Por ello, «pagado» y «con acceso» no son equivalentes. Si el permiso de una cuenta depende directamente de la última respuesta recibida desde una API de pagos, un fallo transitorio puede bloquear a un cliente que sí pagó o habilitar a otro cuyo cobro terminó fallando.

En estados de suscripción en SaaS PHP, el objetivo no es almacenar una etiqueta única en una tabla. Es construir un proceso recuperable: cada decisión debe tener una evidencia, un responsable, una transición válida y una forma de reconciliarse cuando llegan datos nuevos.

Definir las reglas de producto antes del modelo técnico

Definir las reglas de producto antes del modelo técnico — guía visual de DedicatedPHP

El modelo de datos no resuelve ambigüedades comerciales. Antes de diseñar entidades o webhooks, producto, finanzas y operaciones deben acordar qué ocurre en cada situación relevante.

  • Alta: ¿se concede acceso antes de que el primer pago quede confirmado, tras una autorización o sólo después de la liquidación?
  • Renovación: ¿cuándo empieza el periodo de gracia y qué capacidades se conservan durante él?
  • Impago: ¿hay reintentos automáticos, avisos, restricciones parciales o suspensión completa?
  • Cancelación: ¿termina el acceso inmediatamente o al final del periodo ya contratado?
  • Devolución o disputa: ¿requiere bloqueo inmediato, revisión manual o revocación al confirmarse un resultado?
  • Reactivación: ¿restaura exactamente el plan previo, crea un nuevo ciclo comercial o exige validación operativa?

También conviene distinguir una cancelación solicitada por el cliente de una cancelación efectiva. La primera expresa intención; la segunda modifica el derecho futuro de acceso. Mezclarlas provoca interfaces confusas y automatizaciones difíciles de corregir.

Separar contrato, cobro y acceso efectivo

Una arquitectura mantenible representa al menos cuatro conceptos. La cuenta identifica al titular y sus miembros. El contrato comercial describe plan, precio acordado, fecha de renovación y decisión de cancelar. El ciclo de cobro representa una obligación concreta para un periodo, su importe y su resultado. Finalmente, las capacidades habilitadas materializan qué puede hacer la cuenta dentro del producto.

Esta separación evita convertir un proveedor de pagos en la fuente única de verdad de todo el SaaS. Un ciclo puede estar pendiente mientras el contrato sigue vigente por gracia. A la vez, una cuenta puede conservar acceso de lectura, pero no poder crear nuevos recursos. Las capacidades permiten expresar esta decisión sin forzar un falso binario entre activo e inactivo.

En PHP, una aplicación puede exponer un servicio de autorización que consulte una proyección local de capacidades, por ejemplo canCreateProject o canExportData. Esa proyección se actualiza cuando cambian los hechos comerciales o de cobro; no necesita invocar al proveedor en cada petición. Así se reduce latencia, dependencia externa y dispersión de condicionales por controladores, colas y tareas programadas.

Modelar transiciones, responsables y evidencia

Evite un único campo status con valores añadidos según aparecen incidencias. Es preferible declarar estados por agregado y transiciones permitidas. Por ejemplo, un ciclo de cobro puede pasar de open a payment_pending, paid, failed, refunded o disputed. No toda transición es reversible ni cualquier actor puede ejecutarla.

Cada cambio debe guardar fecha, origen, identificador externo cuando exista y evidencia. El origen puede ser una orden interna, un webhook validado, una consulta de conciliación o una acción manual autorizada. Una corrección de soporte no debe sobrescribir silenciosamente la historia: debe registrarse como una decisión distinta, con motivo y operador responsable.

Prioridad ante información contradictoria

Defina qué prueba prevalece. Una pantalla de redirección tras el pago no debería confirmar un ciclo: sirve para informar al usuario, no como evidencia final. Un webhook firmado y verificado suele aportar mejor señal, pero puede llegar tarde. Una consulta autenticada al proveedor durante la conciliación puede aclarar eventos ausentes. Si dos fuentes discrepan, el sistema debe pasar a revisión o a un estado pendiente definido, no elegir de forma arbitraria el dato más reciente.

Procesar eventos tardíos, duplicados e incompletos

La recepción de un evento debe ser idempotente. Guarde un identificador estable del evento externo y un hash o referencia de la carga relevante. Si se recibe de nuevo, responda sin repetir el efecto de negocio. Esto es especialmente importante si un evento de pago desencadena la emisión de un documento, la ampliación del periodo o una notificación.

El procesamiento debe separar recepción y aplicación. Primero, valide firma, esquema y procedencia; después, almacene el evento recibido de forma duradera; por último, procese una tarea que intenta aplicar la transición. Si el proceso cae después de persistir el evento, una cola o un proceso de recuperación puede retomarlo. Si falla antes de persistir, la conciliación deberá descubrir la diferencia comparando los ciclos internos con la fuente externa.

evento recibido → validación → registro durable → aplicación idempotente
                                      ↓
                              reintento o conciliación

No asuma orden de entrega. Un reembolso puede llegar antes que una confirmación tardía del pago original. Las reglas deben evaluar el estado actual, las referencias de operación y la secuencia conocida, dejando los casos imposibles o ambiguos en una cola de revisión. Aplicar ciegamente «el último evento recibido» es una causa habitual de permisos erróneos.

Conciliación y permisos como proyección controlada

La conciliación periódica no es un parche; es parte del diseño. Debe localizar ciclos abiertos demasiado tiempo, pagos confirmados fuera del sistema, eventos registrados sin procesar, referencias externas duplicadas y capacidades que no corresponden con el contrato vigente. Al detectar una diferencia, registre el hallazgo y aplique una transición trazable, en vez de actualizar campos directamente.

La proyección de capacidades debe tener reglas explícitas. Por ejemplo, un contrato vigente con un ciclo vencido pero dentro de gracia puede mantener funciones esenciales; al terminar la gracia, puede retirar operaciones de escritura. Cuando se confirma un pago tardío, el sistema reactiva las capacidades previstas para el plan y conserva el historial de la restricción anterior.

Una caché de permisos puede ser útil, pero necesita invalidación al cambiar la proyección y un límite de vigencia. La autorización crítica tampoco debe basarse sólo en datos almacenados en el navegador. El servidor debe decidir con la capacidad vigente y el ámbito correcto de cuenta, usuario y recurso.

Backoffice, auditoría y pruebas de recuperación

El equipo de soporte necesita ver, sin editar registros de base de datos, el contrato, los ciclos, los eventos externos, las transiciones aplicadas, las capacidades actuales y las acciones manuales. Debe poder solicitar una conciliación, reintentar un evento seguro y abrir una revisión. Las correcciones que alteren acceso o saldo requieren permisos diferenciados, motivo obligatorio y registro de auditoría.

Pruebe el flujo como una secuencia de fallos, no sólo como un pago correcto. Incluya renovación confirmada, pago incierto, duplicados, eventos fuera de orden, devolución, cancelación al final de periodo y reactivación. Verifique tanto el resultado final como que ningún reintento crea dos periodos, dos documentos o una ampliación doble de permisos.

Un caso hipotético: un ciclo vence, el cobro queda pendiente y la cuenta entra en gracia con capacidades limitadas. El webhook de confirmación no se procesa por una interrupción temporal, pero el evento permanece registrado. Un reintento idempotente confirma el ciclo, extiende el contrato y recompone las capacidades. Si el evento no hubiera llegado, la conciliación encontraría la operación externa confirmada y generaría la misma transición con su propia evidencia.

Señales de alerta y lista de comprobación

Señales de alerta y lista de comprobación — guía visual de DedicatedPHP

Mida cuentas con contrato y capacidades incoherentes, ciclos vencidos sin decisión, eventos sin procesar, reintentos agotados, diferencias detectadas por conciliación y frecuencia de cambios manuales. Un aumento de correcciones manuales suele indicar reglas insuficientes, no sólo un problema operativo.

  • ¿Contrato, ciclo de cobro y capacidades son entidades separadas?
  • ¿Cada transición tiene actor, evidencia, fecha y motivo?
  • ¿Los eventos externos son idempotentes y se guardan antes de aplicarse?
  • ¿Existe una conciliación capaz de recuperar operaciones incompletas?
  • ¿Los permisos se calculan desde una proyección local y no desde una respuesta de pago en tiempo real?
  • ¿Soporte puede investigar y corregir con auditoría, sin cambios directos en producción?
  • ¿Las pruebas cubren retrasos, duplicados, desorden y contradicciones?

Un modelo recuperable no elimina los fallos externos. Hace que sean detectables, acotados y corregibles sin convertir un incidente de cobro en una pérdida de control sobre el acceso al producto.

¿Quieres aplicar estas ideas a tu proyecto?Hablemos de tu plataforma PHP.
Ver servicio relacionado