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>
6.4 KiB
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