trading-platform/docs/02-definicion-modulos/OQI-005-payments-stripe/README.md
rckrdmrd a7cca885f0 feat: Major platform documentation and architecture updates
Changes include:
- Updated architecture documentation
- Enhanced module definitions (OQI-001 to OQI-008)
- ML integration documentation updates
- Trading strategies documentation
- Orchestration and inventory updates
- Docker configuration updates

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-07 05:33:35 -06:00

6.4 KiB

id title type project version updated_date
README Sistema de Pagos con Stripe Documentation trading-platform 1.0.0 2026-01-04

OQI-005: Sistema de Pagos con Stripe

Estado: Implementado Fecha: 2025-12-05 Modulo: apps/backend/src/modules/payments


Descripcion

Sistema completo de pagos integrado con Stripe para:

  • Pagos unicos (compra de cursos)
  • Suscripciones mensuales (planes Basic, Pro, Premium)
  • Webhooks para eventos de pago
  • Historial de transacciones

Arquitectura

┌─────────────────┐     ┌─────────────────┐     ┌─────────────────┐
│    Frontend     │────▶│  NestJS API     │────▶│     Stripe      │
│   (React)       │     │  /payments/*    │     │     API         │
└─────────────────┘     └─────────────────┘     └─────────────────┘
                               │
                               ▼
                        ┌─────────────────┐
                        │   PostgreSQL    │
                        │  billing schema │
                        └─────────────────┘

Endpoints

Metodo Ruta Descripcion Auth
POST /payments/create-payment-intent Crear pago directo JWT
POST /payments/create-checkout-session Checkout hosted JWT
POST /payments/subscriptions Crear suscripcion JWT
GET /payments/subscriptions/current Suscripcion actual JWT
DELETE /payments/subscriptions/:id Cancelar suscripcion JWT
GET /payments/history Historial de pagos JWT
POST /payments/webhook Webhook Stripe -

Entidades

Payment

@Entity({ name: 'payments', schema: 'billing' })
class Payment {
  id: string;              // UUID
  userId: string;          // FK a users
  type: PaymentType;       // course_purchase | subscription | one_time
  status: PaymentStatus;   // pending | processing | succeeded | failed | cancelled | refunded
  amount: number;          // Monto en USD
  currency: string;        // USD
  stripePaymentIntentId: string;
  stripeCustomerId: string;
  courseId?: string;       // Si es compra de curso
  subscriptionId?: string; // Si es pago de suscripcion
  description?: string;
  metadata?: object;
  failureReason?: string;
  refundedAt?: Date;
  createdAt: Date;
  updatedAt: Date;
}

Subscription

@Entity({ name: 'subscriptions', schema: 'billing' })
class Subscription {
  id: string;              // UUID
  userId: string;          // FK a users
  plan: SubscriptionPlan;  // basic | pro | premium
  status: SubscriptionStatus; // active | past_due | cancelled | incomplete | trialing | unpaid
  stripeSubscriptionId: string;
  stripeCustomerId: string;
  stripePriceId: string;
  price: number;           // Precio mensual
  currency: string;        // USD
  billingInterval: string; // month | year
  currentPeriodStart: Date;
  currentPeriodEnd: Date;
  trialEnd?: Date;
  cancelledAt?: Date;
  cancelAtPeriodEnd: boolean;
  metadata?: object;
  createdAt: Date;
  updatedAt: Date;
}

Planes de Suscripcion

Plan Precio Price ID Caracteristicas
Basic $19/mes price_1Sb3k64dPtEGmLmpeAdxvmIu Predicciones basicas, cursos intro
Pro $49/mes price_1Sb3k64dPtEGmLmpm5n5bbJH Predicciones avanzadas, todos los cursos
Premium $99/mes price_1Sb3k74dPtEGmLmpHfLpUkvQ Todo + soporte prioritario

Flujo de Pago

Pago Unico (Payment Intent)

1. Frontend solicita crear payment intent
2. Backend crea PaymentIntent en Stripe
3. Backend guarda registro en BD (status: pending)
4. Frontend recibe clientSecret
5. Frontend muestra formulario de tarjeta (Stripe Elements)
6. Usuario completa pago
7. Stripe envia webhook (payment_intent.succeeded)
8. Backend actualiza status a succeeded
9. Backend otorga acceso al recurso

Suscripcion

1. Frontend solicita crear suscripcion
2. Backend obtiene/crea Customer en Stripe
3. Backend adjunta metodo de pago
4. Backend crea Subscription en Stripe
5. Backend guarda registro en BD
6. Stripe cobra automaticamente cada mes
7. Webhooks actualizan estado

Configuracion

Variables de Entorno

STRIPE_SECRET_KEY=sk_test_xxx
STRIPE_WEBHOOK_SECRET=whsec_xxx
FRONTEND_URL=http://localhost:5173

Webhook Events

Evento Accion
payment_intent.succeeded Actualizar pago a succeeded, otorgar acceso
payment_intent.payment_failed Actualizar pago a failed
customer.subscription.updated Sincronizar estado de suscripcion
customer.subscription.deleted Marcar suscripcion como cancelled

Ejemplo de Uso

Crear Payment Intent

curl -X POST http://localhost:3000/payments/create-payment-intent \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 2900,
    "currency": "usd",
    "type": "course_purchase",
    "courseId": "uuid-del-curso",
    "description": "Curso de Trading Basico"
  }'

Respuesta:

{
  "clientSecret": "pi_xxx_secret_xxx",
  "paymentIntentId": "pi_xxx",
  "amount": 2900,
  "currency": "usd"
}

Crear Suscripcion

curl -X POST http://localhost:3000/payments/subscriptions \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "plan": "pro",
    "paymentMethodId": "pm_xxx"
  }'

Modo Mock

Cuando STRIPE_SECRET_KEY no esta configurado, el sistema funciona en modo mock:

  • Retorna payment intents simulados
  • Las suscripciones se crean localmente
  • Util para desarrollo sin cuenta Stripe

Archivos

apps/backend/src/modules/payments/
├── dto/
│   ├── payment.dto.ts
│   └── subscription.dto.ts
├── entities/
│   ├── payment.entity.ts
│   └── subscription.entity.ts
├── payments.controller.ts
├── payments.service.ts
└── payments.module.ts

Seguridad

  • Todos los endpoints requieren JWT (excepto webhook)
  • Webhook valida firma de Stripe
  • Claves secretas en variables de entorno
  • Nunca exponer sk_test_* en frontend

Documentacion generada: 2025-12-05