---
id: "PMC-009-PAYMENTS"
title: "PMC-009: Modulo de Payments"
type: "Module Definition"
epic: "PMC-009"
status: "Draft"
project: "platform_marketing_content"
version: "1.0.0"
created_date: "2026-01-04"
updated_date: "2026-01-04"
---
# PMC-009: Modulo de Payments

**Version:** 1.0.0
**Fecha:** 2026-01-04
**Estado:** Definicion
**Prioridad:** Alta

---

## Descripcion General

El modulo de Payments proporciona la integracion completa con Stripe para gestionar suscripciones, pagos y facturacion del sistema SaaS. Incluye checkout flow con Stripe Elements, gestion de planes de suscripcion, facturacion automatica y sistema de creditos de generacion.

### Objetivos

1. Integrar Stripe como pasarela de pagos principal
2. Gestionar planes de suscripcion (Free, Pro, Enterprise, Internal)
3. Implementar checkout flow con Stripe Elements
4. Automatizar facturacion y cobros recurrentes
5. Gestionar creditos de generacion por tenant
6. Procesar webhooks de Stripe para sincronizar estados

---

## Planes de Suscripcion

```yaml
Planes Disponibles:
  free:
    nombre: "Free"
    precio: $0/mes
    limites:
      generaciones_mes: 50
      storage_gb: 1
      usuarios_max: 1
      modelos_custom: 0
    features:
      - Generacion basica de imagenes
      - 1 proyecto activo
      - Soporte por email

  pro:
    nombre: "Pro"
    precio: $79/mes
    stripe_price_id: pmc_pro
    limites:
      generaciones_mes: 500
      storage_gb: 25
      usuarios_max: 5
      modelos_custom: 3
    features:
      - Todo de Free
      - Modelos personalizados
      - API access
      - Integraciones n8n
      - Soporte prioritario

  enterprise:
    nombre: "Enterprise"
    precio: $249/mes
    stripe_price_id: pmc_enterprise
    limites:
      generaciones_mes: unlimited
      storage_gb: 100
      usuarios_max: unlimited
      modelos_custom: unlimited
    features:
      - Todo de Pro
      - Generaciones ilimitadas
      - Usuarios ilimitados
      - SSO/SAML
      - SLA garantizado
      - Soporte dedicado

  internal:
    nombre: "Internal"
    precio: $0/mes
    limites:
      generaciones_mes: unlimited
      storage_gb: unlimited
      usuarios_max: unlimited
      modelos_custom: unlimited
    features:
      - Acceso completo sin restricciones
      - Solo para uso interno de la organizacion
```

---

## Productos Stripe Propuestos

```yaml
Productos Stripe:
  pmc_pro:
    type: subscription
    nombre: "PMC Pro Plan"
    precio: $79/mes
    billing_interval: monthly
    descripcion: "500 generaciones, 25GB storage, 5 usuarios"
    metadata:
      plan_code: pro
      generations: 500
      storage_gb: 25
      users_max: 5

  pmc_enterprise:
    type: subscription
    nombre: "PMC Enterprise Plan"
    precio: $249/mes
    billing_interval: monthly
    descripcion: "Generaciones ilimitadas, recursos ilimitados"
    metadata:
      plan_code: enterprise
      generations: unlimited
      storage_gb: 100
      users_max: unlimited

  pmc_generations_100:
    type: one_time
    nombre: "Pack 100 Generaciones Extra"
    precio: $19
    descripcion: "100 creditos de generacion adicionales"
    metadata:
      product_type: credits
      credits_amount: 100
```

---

## Entidades del Dominio

### Subscription

```yaml
Entidad: Subscription
Descripcion: Suscripcion activa de un tenant a un plan
Atributos:
  - id: UUID (PK)
  - tenant_id: UUID (FK a Tenant)
  - user_id: UUID (FK a User, quien suscribio)
  - plan_id: UUID (FK a Plan)
  - stripe_subscription_id: string (sub_xxx)
  - stripe_customer_id: string (cus_xxx)
  - status: enum [active, past_due, canceled, incomplete, trialing, paused]
  - current_period_start: timestamp
  - current_period_end: timestamp
  - cancel_at_period_end: boolean
  - canceled_at: timestamp
  - trial_start: timestamp
  - trial_end: timestamp
  - metadata: JSONB
  - created_at: timestamp
  - updated_at: timestamp

Relaciones:
  - N:1 con Tenant
  - N:1 con User
  - N:1 con Plan
  - 1:N con Invoice
```

### Invoice

```yaml
Entidad: Invoice
Descripcion: Factura generada por Stripe
Atributos:
  - id: UUID (PK)
  - tenant_id: UUID (FK)
  - subscription_id: UUID (FK a Subscription)
  - stripe_invoice_id: string (in_xxx)
  - stripe_invoice_number: string
  - amount_due: decimal
  - amount_paid: decimal
  - currency: string (usd, eur)
  - status: enum [draft, open, paid, void, uncollectible]
  - invoice_pdf_url: string
  - hosted_invoice_url: string
  - paid_at: timestamp
  - due_date: timestamp
  - period_start: timestamp
  - period_end: timestamp
  - created_at: timestamp
  - updated_at: timestamp

Relaciones:
  - N:1 con Tenant
  - N:1 con Subscription
```

### PaymentMethod

```yaml
Entidad: PaymentMethod
Descripcion: Metodo de pago registrado del cliente
Atributos:
  - id: UUID (PK)
  - tenant_id: UUID (FK)
  - user_id: UUID (FK)
  - stripe_payment_method_id: string (pm_xxx)
  - type: enum [card, sepa_debit, us_bank_account]
  - card_brand: string (visa, mastercard, amex)
  - card_last4: string
  - card_exp_month: integer
  - card_exp_year: integer
  - is_default: boolean
  - billing_details: JSONB (name, email, address)
  - created_at: timestamp
  - updated_at: timestamp

Relaciones:
  - N:1 con Tenant
  - N:1 con User
```

### GenerationCredit

```yaml
Entidad: GenerationCredit
Descripcion: Balance de creditos de generacion por tenant
Atributos:
  - id: UUID (PK)
  - tenant_id: UUID (FK, unico)
  - credits_included: integer (del plan)
  - credits_remaining: integer (del periodo actual)
  - credits_used: integer (del periodo actual)
  - credits_extra: integer (comprados, no expiran)
  - resets_at: timestamp (inicio proximo periodo)
  - last_reset_at: timestamp
  - created_at: timestamp
  - updated_at: timestamp

Relaciones:
  - 1:1 con Tenant

Notas:
  - credits_remaining se resetea cada periodo de facturacion
  - credits_extra no se resetean, son acumulables
  - Al consumir, primero se usan credits_remaining, luego credits_extra
```

### CreditTransaction

```yaml
Entidad: CreditTransaction
Descripcion: Historial de movimientos de creditos
Atributos:
  - id: UUID (PK)
  - tenant_id: UUID (FK)
  - type: enum [subscription_reset, purchase, usage, adjustment, refund]
  - amount: integer (positivo o negativo)
  - balance_after: integer
  - description: string
  - reference_type: string (generation_job, invoice, manual)
  - reference_id: UUID
  - created_at: timestamp

Relaciones:
  - N:1 con Tenant
```

---

## Funcionalidades

### F-009.1: Seleccionar Plan y Suscribirse

| ID | Funcionalidad | Descripcion | Prioridad |
|----|---------------|-------------|-----------|
| F-009.1.1 | Ver planes disponibles | Mostrar comparativa de planes | Alta |
| F-009.1.2 | Seleccionar plan | Elegir plan deseado | Alta |
| F-009.1.3 | Crear customer Stripe | Registrar cliente en Stripe | Alta |
| F-009.1.4 | Iniciar trial | Periodo de prueba de 14 dias | Media |

### F-009.2: Checkout con Stripe Elements

| ID | Funcionalidad | Descripcion | Prioridad |
|----|---------------|-------------|-----------|
| F-009.2.1 | Crear checkout session | Generar sesion de pago Stripe | Alta |
| F-009.2.2 | Stripe Elements UI | Formulario de pago embebido | Alta |
| F-009.2.3 | Confirmar pago | Procesar transaccion | Alta |
| F-009.2.4 | Manejar errores | Reintentos y mensajes claros | Alta |

### F-009.3: Gestionar Suscripcion

| ID | Funcionalidad | Descripcion | Prioridad |
|----|---------------|-------------|-----------|
| F-009.3.1 | Ver suscripcion actual | Detalles del plan activo | Alta |
| F-009.3.2 | Upgrade de plan | Cambiar a plan superior | Alta |
| F-009.3.3 | Downgrade de plan | Cambiar a plan inferior | Media |
| F-009.3.4 | Cancelar suscripcion | Finalizar al terminar periodo | Media |
| F-009.3.5 | Reactivar suscripcion | Revertir cancelacion pendiente | Media |

### F-009.4: Ver Facturas e Historial

| ID | Funcionalidad | Descripcion | Prioridad |
|----|---------------|-------------|-----------|
| F-009.4.1 | Listar facturas | Historial de pagos | Alta |
| F-009.4.2 | Descargar factura PDF | Obtener comprobante | Alta |
| F-009.4.3 | Ver detalle de factura | Items, impuestos, totales | Media |

### F-009.5: Comprar Creditos Adicionales

| ID | Funcionalidad | Descripcion | Prioridad |
|----|---------------|-------------|-----------|
| F-009.5.1 | Ver packs disponibles | Mostrar opciones de creditos | Media |
| F-009.5.2 | Comprar pack | Checkout one-time | Media |
| F-009.5.3 | Acreditar creditos | Sumar a credits_extra | Media |

### F-009.6: Webhooks de Stripe

| ID | Funcionalidad | Descripcion | Prioridad |
|----|---------------|-------------|-----------|
| F-009.6.1 | invoice.paid | Actualizar estado de factura | Alta |
| F-009.6.2 | invoice.payment_failed | Notificar y manejar fallo | Alta |
| F-009.6.3 | customer.subscription.updated | Sincronizar cambios de suscripcion | Alta |
| F-009.6.4 | customer.subscription.deleted | Manejar cancelacion | Alta |
| F-009.6.5 | checkout.session.completed | Confirmar compra one-time | Alta |

---

## API Endpoints

```yaml
Base: /api/v1/billing

# Checkout y Suscripcion
POST   /billing/checkout:
  Descripcion: Crear sesion de checkout Stripe
  Body: { plan_code: "pro", success_url: string, cancel_url: string }
  Response: { checkout_url: string, session_id: string }
  Permisos: tenant_admin

GET    /billing/subscription:
  Descripcion: Ver suscripcion actual del tenant
  Response: { subscription, plan, usage }
  Permisos: authenticated

POST   /billing/subscription/upgrade:
  Descripcion: Upgrade inmediato a plan superior
  Body: { new_plan_code: string }
  Response: { subscription, proration_amount }
  Permisos: tenant_admin

POST   /billing/subscription/downgrade:
  Descripcion: Downgrade al final del periodo
  Body: { new_plan_code: string }
  Response: { subscription, effective_date }
  Permisos: tenant_admin

POST   /billing/subscription/cancel:
  Descripcion: Cancelar suscripcion al final del periodo
  Body: { reason?: string, feedback?: string }
  Response: { subscription, cancel_at }
  Permisos: tenant_admin

POST   /billing/subscription/reactivate:
  Descripcion: Revertir cancelacion pendiente
  Response: { subscription }
  Permisos: tenant_admin

# Metodos de Pago
GET    /billing/payment-methods:
  Descripcion: Listar metodos de pago
  Response: { payment_methods: [] }
  Permisos: tenant_admin

POST   /billing/payment-methods:
  Descripcion: Agregar metodo de pago
  Body: { payment_method_id: string }
  Response: { payment_method }
  Permisos: tenant_admin

DELETE /billing/payment-methods/:id:
  Descripcion: Eliminar metodo de pago
  Response: 204 No Content
  Permisos: tenant_admin

PATCH  /billing/payment-methods/:id/default:
  Descripcion: Establecer como metodo predeterminado
  Response: { payment_method }
  Permisos: tenant_admin

# Facturas
GET    /billing/invoices:
  Descripcion: Listar facturas del tenant
  Query: ?status=paid&page=1&limit=20
  Response: { invoices: [], pagination }
  Permisos: tenant_admin

GET    /billing/invoices/:id:
  Descripcion: Detalle de factura
  Response: { invoice }
  Permisos: tenant_admin

GET    /billing/invoices/:id/pdf:
  Descripcion: Descargar PDF de factura
  Response: Redirect a URL de Stripe
  Permisos: tenant_admin

# Creditos
GET    /billing/credits:
  Descripcion: Ver balance de creditos
  Response: { credits_remaining, credits_extra, credits_used, resets_at }
  Permisos: authenticated

POST   /billing/credits/purchase:
  Descripcion: Comprar pack de creditos
  Body: { pack_code: "pmc_generations_100" }
  Response: { checkout_url, session_id }
  Permisos: tenant_admin

GET    /billing/credits/transactions:
  Descripcion: Historial de movimientos de creditos
  Query: ?type=usage&page=1&limit=50
  Response: { transactions: [], pagination }
  Permisos: tenant_admin

# Webhooks (endpoint publico)
POST   /billing/webhooks:
  Descripcion: Endpoint para webhooks de Stripe
  Headers: Stripe-Signature
  Response: 200 OK
  Notas: Verificar firma con STRIPE_WEBHOOK_SECRET
```

---

## Reglas de Negocio

```yaml
RN-009.1:
  Descripcion: Solo tenant_admin puede cambiar plan
  Validacion: Verificar rol del usuario
  Accion: 403 Forbidden si no es admin

RN-009.2:
  Descripcion: Downgrade aplica al final del periodo
  Validacion: No cambio inmediato, schedule para renewal
  Accion: Stripe schedule subscription update

RN-009.3:
  Descripcion: Creditos del plan no usados no se transfieren
  Validacion: credits_remaining se resetea cada periodo
  Excepcion: credits_extra (comprados) son permanentes

RN-009.4:
  Descripcion: Cancelacion permite usar hasta fin del periodo
  Validacion: cancel_at_period_end = true
  Accion: Acceso continua hasta current_period_end

RN-009.5:
  Descripcion: Plan Free no requiere metodo de pago
  Validacion: Permitir suscripcion sin checkout
  Accion: Crear subscription con trial infinito o sin cobro

RN-009.6:
  Descripcion: Upgrade es inmediato con prorrateo
  Validacion: Cobrar diferencia proporcional
  Accion: Stripe proration automatico

RN-009.7:
  Descripcion: Pago fallido da 3 reintentos
  Validacion: Stripe Smart Retries habilitado
  Accion: Notificar usuario, suspender tras fallos

RN-009.8:
  Descripcion: Creditos se consumen en orden
  Validacion: Primero credits_remaining, luego credits_extra
  Accion: Logica en GenerationService

RN-009.9:
  Descripcion: Plan Internal solo asignable por super_admin
  Validacion: Verificar rol super_admin
  Accion: No disponible en checkout publico
```

---

## Dependencias

```yaml
Dependencias de Modulos:
  - PMC-001 Tenants:
      uso: Asociacion tenant-plan, limites por tenant
      datos: tenant_id, plan_id, limits JSONB

  - PMC-007 Admin:
      uso: Permisos de billing, gestion de planes
      datos: admin.billing permission

  - PMC-004 Generation:
      uso: Consumo de creditos por generacion
      integracion: Decrementar credits al generar

Dependencias del Catalogo:
  - @CATALOG_PAYMENTS:
      path: shared/catalog/payments/
      uso: Patron base de integracion Stripe
      incluye:
        - Stripe SDK wrapper
        - Webhook handling
        - Customer management
        - Subscription lifecycle
      adaptar:
        - Crear productos/precios PMC en Stripe
        - Implementar sistema de creditos
        - Integrar con planes de PMC-001
      docs: shared/catalog/payments/README.md

  - @CATALOG_NOTIFY:
      path: shared/catalog/notifications/
      uso: Notificaciones de pago
      incluye:
        - Email de confirmacion de pago
        - Alerta de pago fallido
        - Recordatorio de vencimiento
      docs: shared/catalog/notifications/README.md

Servicios Externos:
  - Stripe:
      tipo: Payment Gateway
      productos:
        - Subscriptions API
        - Checkout Sessions
        - Payment Intents
        - Webhooks
        - Customer Portal
      sdk: stripe (npm)
      version: "^14.0.0"

Referencia de Implementacion:
  - Payment service: projects/gamilit/apps/backend/src/modules/payments/
  - Stripe integration: projects/gamilit/apps/backend/src/modules/payments/services/stripe.service.ts
  - Webhook handler: projects/gamilit/apps/backend/src/modules/payments/controllers/webhooks.controller.ts
```

---

## Configuracion

```yaml
Variables de Entorno:
  STRIPE_SECRET_KEY:
    descripcion: API key secreta de Stripe
    formato: sk_live_xxx o sk_test_xxx
    requerido: true

  STRIPE_PUBLISHABLE_KEY:
    descripcion: API key publica para frontend
    formato: pk_live_xxx o pk_test_xxx
    requerido: true

  STRIPE_WEBHOOK_SECRET:
    descripcion: Secret para verificar webhooks
    formato: whsec_xxx
    requerido: true

  STRIPE_PRICE_PRO:
    descripcion: Price ID del plan Pro
    formato: price_xxx
    requerido: true

  STRIPE_PRICE_ENTERPRISE:
    descripcion: Price ID del plan Enterprise
    formato: price_xxx
    requerido: true

  STRIPE_PRICE_CREDITS_100:
    descripcion: Price ID del pack de 100 creditos
    formato: price_xxx
    requerido: true

  STRIPE_TRIAL_DAYS:
    descripcion: Dias de prueba para nuevas suscripciones
    default: 14
    requerido: false

  BILLING_CURRENCY:
    descripcion: Moneda por defecto
    default: "usd"
    requerido: false
```

---

## Flujos de Usuario

### Suscribirse a Plan Pro

```
1. Usuario navega a Settings → Billing → Plans
2. Ve comparativa de planes (Free, Pro, Enterprise)
3. Selecciona "Upgrade to Pro"
4. Sistema crea Checkout Session en Stripe
5. Redirect a Stripe Checkout
6. Usuario ingresa datos de pago (Stripe Elements)
7. Stripe procesa pago
8. Webhook invoice.paid recibido
9. Sistema actualiza subscription y credits
10. Redirect a success_url con confirmacion
```

### Cancelar Suscripcion

```
1. Admin navega a Settings → Billing → Subscription
2. Click en "Cancel Subscription"
3. Modal de confirmacion con fecha de fin
4. Opcionalmente ingresa razon/feedback
5. Sistema llama Stripe cancel at period end
6. Suscripcion marcada cancel_at_period_end = true
7. Usuario puede seguir usando hasta current_period_end
8. Al vencer, subscription status = canceled
```

### Comprar Creditos Extra

```
1. Usuario ve que credits_remaining esta bajo
2. Navega a Settings → Billing → Credits
3. Ve packs disponibles (100 creditos por $19)
4. Click en "Buy Credits"
5. Checkout Session para one-time payment
6. Stripe procesa pago
7. Webhook checkout.session.completed
8. Sistema suma credits_extra += 100
9. Redirect con confirmacion
```

---

## Webhooks de Stripe

```yaml
Eventos a Procesar:
  invoice.paid:
    accion:
      - Actualizar Invoice status = paid
      - Si es primera factura, activar subscription
      - Reset credits_remaining del periodo

  invoice.payment_failed:
    accion:
      - Actualizar Invoice status segun attempt
      - Notificar usuario por email
      - Tras 3 fallos, marcar subscription past_due

  customer.subscription.created:
    accion:
      - Crear registro Subscription local
      - Crear GenerationCredit para tenant
      - Actualizar tenant.plan_id

  customer.subscription.updated:
    accion:
      - Sincronizar status, period dates
      - Si cambio de plan, actualizar limits
      - Recalcular credits si aplica

  customer.subscription.deleted:
    accion:
      - Marcar subscription status = canceled
      - Cambiar tenant a plan Free
      - Notificar admin del tenant

  checkout.session.completed:
    accion:
      - Si mode = subscription, ya manejado por invoice.paid
      - Si mode = payment (creditos), acreditar credits_extra
      - Crear CreditTransaction

  customer.created:
    accion:
      - Actualizar tenant con stripe_customer_id

  payment_method.attached:
    accion:
      - Crear/actualizar PaymentMethod local
```

---

## Criterios de Aceptacion

- [ ] Checkout con Stripe Elements funciona end-to-end
- [ ] Suscripcion se crea correctamente tras pago
- [ ] Upgrade inmediato con prorrateo funciona
- [ ] Downgrade se programa para fin de periodo
- [ ] Cancelacion permite uso hasta vencimiento
- [ ] Facturas se sincronizan via webhooks
- [ ] PDFs de facturas descargables
- [ ] Sistema de creditos funciona correctamente
- [ ] Compra de creditos extra funciona
- [ ] Webhooks procesan todos los eventos clave
- [ ] Notificaciones de pago se envian
- [ ] Solo tenant_admin puede gestionar billing

---

## Consideraciones de Seguridad

```yaml
Seguridad:
  - API keys de Stripe solo en backend (nunca en frontend)
  - Webhook signature verification obligatorio
  - PCI compliance delegado a Stripe (no almacenar tarjetas)
  - Audit log de todas las transacciones
  - Rate limiting en endpoints de billing
  - Validar que usuario pertenece al tenant
```

---

## Referencias

- [ARQUITECTURA-TECNICA.md](../00-vision-general/ARQUITECTURA-TECNICA.md)
- [@CATALOG_PAYMENTS](../../../shared/catalog/payments/)
- [PMC-001-TENANTS.md](./PMC-001-TENANTS.md)
- [PMC-007-ADMIN.md](./PMC-007-ADMIN.md)
- [Stripe Docs](https://stripe.com/docs)

---

**Documento generado por:** Requirements-Analyst
**Fecha:** 2026-01-04
