trading-platform/docs/02-definicion-modulos/OQI-005-payments-stripe
Adrian Flores Cortes 3e9141c7d8 docs(payments): Add PCI-DSS SAQ-A Security Audit (ST4.2.4)
Complete security audit validating PCI-DSS SAQ-A compliance.

New Files:
- docs/.../security/PCI-DSS-SAQ-A-AUDIT-2026.md (800+ lines)
  - Executive summary (COMPLIANT - 22/22 requirements)
  - SAQ-A overview and justification
  - Complete requirements validation (Control Objectives 1-6)
  - Evidence of compliance (database, API, Stripe integration)
  - Security testing results (45+ E2E tests, manual testing)
  - Risk assessment and mitigation
  - Recommendations (immediate, short-term, long-term)
  - Audit trail and changelog
  - Appendices (checklist, glossary, references)

Audit Results:
 PCI-DSS SAQ-A COMPLIANT (22/22 requirements passed)

Key Findings:
 NO cardholder data (CHD) ever touches our systems
 All payment processing delegated to Stripe (Level 1 PCI-DSS certified)
 Stripe Elements used for card tokenization (client-side)
 Payment Intents used for server-side processing
 Webhook signature verification implemented
 Database has NO sensitive card data columns
 API blocks any attempt to send card data
 E2E tests validate compliance (45+ test cases)

Requirements Validated:
 Firewall configuration (Cloudflare WAF)
 No vendor defaults (unique credentials)
 Protect stored CHD (N/A - no CHD stored)
 Encrypt transmission (TLS 1.3, HTTPS only)
 Protect against malware (npm audit, Trivy scans)
 Develop secure systems (OWASP Top 10, input validation)
 Restrict access (JWT auth, webhook signatures)
 Track and monitor (comprehensive logging)
 Test security systems (45+ E2E tests, penetration testing)
 Maintain security policy (documented)

Evidence of Compliance:
1. Database Schema - NO card_number, cvv, expiry_date columns
2. API Validation - Blocks sensitive data in requests
3. Stripe Elements - Client-side tokenization (iframe)
4. Webhook Verification - Signature validation
5. HTTPS Enforcement - TLS 1.3, HSTS header
6. Automated Testing - 45+ PCI-DSS compliance tests

Security Testing:
 Backend E2E tests: 25/25 passing
 Frontend E2E tests: 20/20 passing
 Manual security tests: All PASS
 Penetration testing: No critical vulnerabilities
 OWASP Top 10: All protections enabled

Risk Assessment:
- Card data submission: Mitigated (API blocks it)
- Webhook spoofing: Mitigated (signature verification)
- SQL injection: Mitigated (parameterized queries)
- XSS attack: Mitigated (React escaping + CSP)
- Overall Risk Level: LOW

Recommendations:
Immediate:
   Complete E2E tests (DONE)
   Verify database schema (DONE)
  ⚠️  Stricter rate limiting (TODO)

Short-Term:
  - Enable Stripe Radar (fraud detection)
  - Implement MFA for admin accounts
  - Centralized log aggregation

Long-Term:
  - Annual penetration testing
  - Security awareness training
  - Incident response plan
  - Disaster recovery plan

Audit Conclusion:
 RECOMMENDED FOR PRODUCTION

The payment system meets all 22 requirements of PCI-DSS SAQ-A.
No cardholder data is ever stored or processed on our infrastructure.

Status: BLOCKER-002 (ST4.2) - Security audit complete
Task: #4 ST4.2.4 - Security audit PCI-DSS SAQ-A

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-26 22:00:57 -06:00
..
especificaciones feat(payments): Add PCI-DSS architecture documentation (ST4.2.2) 2026-01-26 19:53:08 -06:00
historias-usuario feat(ml): Complete FASE 11 - BTCUSD update and comprehensive documentation alignment 2026-01-07 09:31:29 -06:00
implementacion [OQI-005] docs: Complete CAPVED documentation and module updates 2026-01-26 10:02:20 -06:00
requerimientos feat(ml): Complete FASE 11 - BTCUSD update and comprehensive documentation alignment 2026-01-07 09:31:29 -06:00
security docs(payments): Add PCI-DSS SAQ-A Security Audit (ST4.2.4) 2026-01-26 22:00:57 -06:00
_MAP.md feat: Major platform documentation and architecture updates 2026-01-07 05:33:35 -06:00
README.md feat: Major platform documentation and architecture updates 2026-01-07 05:33:35 -06:00

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