Comprehensive developer guidelines for payment system development. New Files: - docs/.../OQI-005-payments-stripe/DEVELOPER-GUIDELINES.md (900+ lines) - Complete reference for payment development - PCI-DSS compliance rules (DO's and DON'Ts) - Backend development guidelines - Frontend development guidelines - Testing guidelines (unit + E2E) - Common pitfalls and how to avoid them - Code review checklist - Deployment checklist - Troubleshooting guide - Examples and templates Sections: 1. Overview - Architecture summary, tech stack, compliance level 2. PCI-DSS Compliance Rules - What's allowed vs prohibited 3. Backend Development - File structure, endpoints, webhooks, database 4. Frontend Development - Stripe Elements, checkout flow, error handling 5. Testing Guidelines - Unit tests, E2E tests, component tests 6. Common Pitfalls - 5 common mistakes and how to avoid them 7. Code Review Checklist - Security, quality, Stripe integration 8. Deployment Checklist - Environment, security, testing, monitoring 9. Troubleshooting - Common issues and solutions 10. Examples & Templates - Complete flow examples Key Guidelines: ✅ DO's: - Use Payment Intents (server-side processing) - Use Stripe Elements (client-side tokenization) - Verify webhook signatures - Store only tokens/IDs (pm_xxx, pi_xxx) - Use HTTPS everywhere - Log payment events (without sensitive data) - Write E2E tests for PCI-DSS compliance ❌ DON'Ts: - Accept card data in backend - Store PAN, CVV, or expiry in database - Create native card inputs - Store card data in React state - Skip webhook signature verification - Use HTTP (only HTTPS) - Log sensitive data PCI-DSS Compliance: ✅ ALLOWED: - Store last 4 digits - Store card brand - Store Stripe tokens (pm_xxx, pi_xxx, cus_xxx) - Store customer name ❌ PROHIBITED: - Store full PAN (card number) - Store CVV/CVC - Store expiry date - Store PIN Common Pitfalls: 1. Accepting card data in backend → Block sensitive fields 2. Storing full PAN in database → Use tokens only 3. Native card inputs → Use Stripe CardElement 4. Not verifying webhook signatures → Use constructEvent 5. Logging sensitive data → Filter sensitive fields Code Examples: - Wallet deposit flow (complete end-to-end) - Subscription checkout (Stripe hosted) - Payment Intent creation (backend) - Stripe Elements integration (frontend) - Webhook signature verification - Database schema (safe vs prohibited) Testing Examples: - Unit tests (Stripe service mocked) - E2E tests (PCI-DSS compliance) - Component tests (CardElement rendering) - Integration tests (webhook handling) Deployment Checklist: - Environment variables configured - Stripe webhooks set up - SSL/TLS enabled - Security headers configured - Rate limiting enabled - All tests passing (45+ PCI-DSS tests) - Monitoring and alerts configured Target Audience: - Backend developers (Express.js, TypeScript) - Frontend developers (React, Stripe.js) - DevOps engineers (deployment, monitoring) - Code reviewers (security validation) - New team members (onboarding) Status: BLOCKER-002 (ST4.2) - Developer guidelines complete Task: #5 ST4.2.5 - Actualizar developer guidelines pagos Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> |
||
|---|---|---|
| .. | ||
| especificaciones | ||
| historias-usuario | ||
| implementacion | ||
| requerimientos | ||
| security | ||
| _MAP.md | ||
| DEVELOPER-GUIDELINES.md | ||
| README.md | ||
| 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