Ir al contenido

Facturación, pagos y sincronización de acceso

Billing mantiene el catálogo comercial y sincroniza suscripciones hacia el modelo efectivo de acceso utilizado por Summit Auth.

Entidad Responsabilidad
BillingProduct Producto facturable, aplicaciones asociadas y restricción opcional a organizaciones.
BillingProductGroup Agrupador de autorización dentro de un producto, expuesto como claim groups a las aplicaciones vinculadas.
BillingPlan Nivel comercial, precio, moneda, intervalo y duración.
BillingFeature Funcionalidad reutilizable del catálogo global.
BillingPlanFeature Inclusión de una funcionalidad en un plan, con Value y Unit opcionales.
BillingSubscription Suscripción personal u organizacional y su periodo vigente.
ProductAccessAssignment Procedencia concreta de un acceso y, para organizaciones, ocupación de un puesto.
ProductAccess Vista efectiva y aplanada de acceso por usuario y producto.

Una funcionalidad binaria usa Value = null y Unit = null. Una cuota puede usar, por ejemplo, Value = 50 y Unit = "GB".

Una suscripción personal tiene UserId y no tiene OrganizationId. Una suscripción organizacional tiene OrganizationId y no tiene UserId.

Las suscripciones organizacionales no conceden automáticamente todos los puestos disponibles. ProductAccessAssignment registra qué miembros ocupan un puesto. La reconciliación conserva asignaciones de miembros activos hasta SeatLimit y elimina las que dejan de ser válidas.

BillingSubscriptionAccessSyncService.SyncProductAccessAsync exige que el caller cargue Product y Plan. El servicio:

  1. valida si la suscripción es personal u organizacional;
  2. traduce el estado comercial a un estado de acceso;
  3. actualiza las asignaciones de procedencia;
  4. reconcilia el ProductAccess efectivo;
  5. persiste y audita solo cuando el estado cambia.
BillingSubscription.Status ProductAccess.Status
active, trialing active
past_due, suspended suspended
cancelled, expired expired

Un estado desconocido produce un error en lugar de otorgar acceso de forma optimista.

Cuando existen varias asignaciones para el mismo usuario y producto, la reconciliación prioriza una asignación activa y después la de expiración más lejana. ProductAccess conserva el resultado efectivo; la procedencia sigue en ProductAccessAssignment.

BillingProduct.RequiresOrganization impide que un acceso personal satisfaga el requisito del producto. El registro personal puede continuar en la base de datos, pero:

  • no supera el guard de producto durante /connect/authorize;
  • no aparece como acceso personal efectivo en los claims;
  • el endpoint de funcionalidades exige una asignación organizacional activa.

El flujo de compra usa PaymentOrderService y IPaymentGatewayProvider:

  1. Payments/Index presenta planes activos que el usuario puede adquirir.
  2. Payments/Checkout crea o reutiliza una PaymentOrder pendiente.
  3. El usuario acepta la versión vigente de los términos.
  4. RecordTermsAcceptanceAsync registra fecha y versión antes de mostrar el widget del proveedor.
  5. El callback confirma la orden mediante el proveedor configurado.
  6. Una confirmación aprobada crea o renueva la suscripción y sincroniza ProductAccess.
  7. Una cancelación no crea acceso.

La implementación actual de proveedor es PayPhonePaymentGatewayProvider. El servicio rechaza la confirmación de una orden que no tenga aceptación de términos registrada.

La sincronización puede repetirse. Si plan, estado, fechas y acceso efectivo ya coinciden, no crea otra fila ni otro evento de auditoría.

Los eventos pueden incluir identificadores internos, producto, plan y estado, pero nunca tokens, credenciales del proveedor ni payloads que contengan información sensible.

Hay dos lecturas relacionadas:

  • GET /api/internal/product-access/{userId}/{productKey}/features resuelve las funcionalidades del plan efectivo de un usuario.
  • GET /api/organizations/{id}/products incluye las funcionalidades del plan de cada suscripción organizacional.

Ambas devuelven key, name, value y unit, ordenados por nombre. Consulta APIs internas para ejemplos completos.