Plataforma de trading profesional para inversión en S&P 500 con autenticación JWT, suscripciones Stripe, y gráficos en tiempo real.
- Arquitectura
- Estructura del Proyecto
- Tecnologías y Herramientas
- Requisitos Previos
- Instalación Rápida
- Comandos
- Configuración
- Proceso Completo de Stripe
- Flujo de la Aplicación
- API Endpoints
- Desarrollo Local
- Testing
- CI/CD Pipeline
- Troubleshooting
- Documentación
┌─────────────────────────────────────────────────────────────────────────────┐
│ PLANO DE CONTROL │
│ API REST + Event-Driven │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ API GATEWAY (nginx) │ │
│ │ http://localhost:8080 │ │
│ │ - Rate Limiting (brute force protection) │ │
│ │ - CORS Headers │ │
│ │ - Load Balancing │ │
│ │ - Security Headers (OWASP) │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ┌─────────────────────┼─────────────────────┐ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌───────────────────┐ ┌──────────────────────┐ ┌──────────────┐ │
│ │ Auth Service │ │ Subscription Service │ │ Frontend │ │
│ │ FastAPI + JWT │ │ FastAPI + Stripe │ │ Next.js 15 │ │
│ │ Puerto: 5000 │ │ Puerto: 5000 │ │ Puerto: 3000 │ │
│ │ Puerto ext: 5001 │ │ Puerto ext: 5002 │ │ │ │
│ └───────────────────┘ └──────────────────────┘ └──────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────────┐
│ PLANO DE DATOS │
│ PostgreSQL + MinIO (S3) │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌───────────────────┐ ┌───────────────────┐ ┌───────────────────────┐ │
│ │ PostgreSQL 15 │ │ MinIO │ │ Redis (Futuro) │ │
│ │ Puerto: 5432 │ │ Puerto: 9000 │ │ Puerto: 6379 │ │
│ │ │ │ Console: 9001 │ │ │ │
│ │ - auth.users │ │ │ │ - Session Cache │ │
│ │ - subscriptions │ │ - Archivos S3 │ │ - Rate Limiting │ │
│ │ - market_data │ │ - Backups │ │ │ │
│ └───────────────────┘ └───────────────────┘ └───────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────────┐
│ EVENT-DRIVEN (Futuro) │
│ WebSocket + Stripe Webhooks │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌───────────────────┐ ┌───────────────────┐ ┌───────────────────────┐ │
│ │ WS Gateway │ │ Stripe Webhooks │ │ Kafka/RabbitMQ │ │
│ │ Puerto: 8080/ws │ │ /webhooks/* │ │ (Message Broker) │ │
│ └───────────────────┘ └───────────────────┘ └───────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
fintech-platform/
│
├── 📁 apps/ # Microservicios (Plano de Control)
│ │
│ ├── 📁 auth-service/ # Servicio de Autenticación
│ │ ├── 📁 app/
│ │ │ ├── 📁 core/ # Configuración, DB, Security
│ │ │ ├── 📁 models/ # Modelos SQLAlchemy
│ │ │ ├── 📁 routers/ # Endpoints API
│ │ │ └── 📁 schemas/ # Pydantic schemas
│ │ ├── 📁 tests/ # Tests unitarios
│ │ ├── Dockerfile
│ │ ├── pyproject.toml
│ │ └── .env.example
│ │
│ └── 📁 subscription-service/ # Servicio de Suscripciones + Stripe
│ ├── 📁 app/
│ │ ├── 📁 core/ # Configuración, DB
│ │ ├── 📁 models/ # Modelos SQLAlchemy
│ │ ├── 📁 routers/ # Endpoints API
│ │ │ ├── subscriptions.py # Planes, checkout, suscripciones
│ │ │ └── market.py # Proxy Yahoo Finance
│ │ ├── 📁 schemas/ # Pydantic schemas
│ │ └── 📁 services/ # Lógica de Stripe
│ ├── 📁 tests/ # Tests unitarios
│ ├── Dockerfile
│ ├── pyproject.toml
│ └── .env.example
│
├── 📁 frontend/ # Aplicación Frontend
│ └── 📁 web-app/ # Next.js 15 (App Router)
│ ├── 📁 app/ # Páginas y layouts
│ │ ├── 📁 auth/
│ │ │ ├── login/
│ │ │ └── register/
│ │ ├── 📁 dashboard/ # Dashboard principal + gráficos
│ │ └── 📁 subscription/
│ │ ├── page.tsx # Página de planes
│ │ ├── success/ # Página de éxito
│ │ └── cancel/ # Página de cancelación
│ ├── 📁 lib/ # Utilidades, contextos
│ ├── 📁 public/ # Assets estáticos
│ ├── Dockerfile
│ ├── package.json
│ └── .env.example
│
├── 📁 infra/ # Infraestructura
│ ├── 📁 nginx/
│ │ ├── conf.d/
│ │ │ └── api-gateway.conf # Routing, CORS, Rate Limiting
│ │ ├── nginx.conf
│ │ └── Dockerfile
│ │
│ ├── 📁 postgres/
│ │ └── init.sql # Schema inicial
│ │
│ └── 📁 minio/
│ └── .gitkeep
│
├── 📁 contracts/
│ └── openapi/
│ └── fintech-api.yaml
│
├── 📁 packages/
│
├── 📁 .github/
│ └── 📁 workflows/
│ └── ci.yml
│
├── 📄 docker-compose.yml
├── 📄 turbo.json
├── 📄 .env
├── 📄 .env.example
├── 📄 .gitignore
├── 📄 .dockerignore
├── 📄 README.md
└── 📄 ruff.toml
| Tecnología | Versión | Propósito |
|---|---|---|
| Python | 3.12+ | Lenguaje de programación |
| FastAPI | 0.115+ | Framework API REST |
| SQLAlchemy | 2.0+ | ORM Asíncrono |
| asyncpg | 0.30+ | Driver PostgreSQL async |
| Pydantic | 2.0+ | Validación de datos |
| python-jose | 3.3+ | Manejo de JWT |
| passlib | 1.7+ | Hashing de contraseñas (bcrypt) |
| uv | Latest | Gestor de paquetes/venv rápido |
| Stripe | 7.0+ | Procesamiento de pagos |
| Tecnología | Versión | Propósito |
|---|---|---|
| Next.js | 15.0+ | Framework React con SSR/SSG |
| React | 19.0+ | Librería UI |
| TypeScript | 5.0+ | Tipado estático |
| Tailwind CSS | 3.4+ | Framework CSS |
| Recharts | 3.8+ | Gráficos y charts |
| pnpm | 8+ | Gestor de paquetes rápido |
| Turborepo | Latest | Monorepo build system |
| Tecnología | Propósito |
|---|---|
| Docker | Containerización |
| Docker Compose | Orquestación de servicios |
| PostgreSQL | Base de datos relacional |
| MinIO | Storage S3-compatible |
| nginx | API Gateway, Load Balancer |
| GitHub Actions | CI/CD Pipeline |
- Docker 24.0+
- Docker Compose 2.20+
- Git 2.40+
- Python 3.12+ (para desarrollo local)
- Node.js 22+ (para desarrollo local)
- Cuenta de Stripe (https://dashboard.stripe.com)
git clone <tu-repositorio>
cd fintech-platform# Copiar el template
cp .env.example .env
# Editar con tus valores
nano .env- Ir a https://dashboard.stripe.com/test/apikeys
- Copiar las claves
STRIPE_SECRET_KEYySTRIPE_PUBLISHABLE_KEY - Actualizar el archivo
.env
# Construir e iniciar todos los servicios
docker compose up --build
# Iniciar en segundo plano
docker compose up -d --buildVer instrucciones completas en Proceso Completo de Stripe
# Health check del API Gateway
curl http://localhost:8080/nginx-health
# Health check del Auth Service
curl http://localhost:8080/health
# Frontend
open http://localhost:3000# Levantar todos los servicios
docker compose up --build
# Levantar en segundo plano
docker compose up -d --build
# Ver logs
docker compose logs -f
# Ver logs de un servicio específico
docker compose logs -f auth_service
docker compose logs -f subscription_service
docker compose logs -f nginx
docker compose logs -f frontend
# Detener servicios
docker compose down
# Detener y eliminar volúmenes (⚠️ PIERDE DATOS)
docker compose down -v
# Reconstruir un servicio específico
docker compose up --build auth_service
docker compose up --build subscription_service
docker compose up --build frontend
# Ver estado de servicios
docker compose ps# ─── Auth Service ───
cd apps/auth-service
uv sync
uv run uvicorn app.main:app --reload --port 5000
# ─── Subscription Service ───
cd apps/subscription-service
uv sync
uv run uvicorn app.main:app --reload --port 5001
# ─── Frontend ───
cd frontend/web-app
pnpm install
pnpm dev
pnpm build
pnpm lint
pnpm exec tsc --noEmit# ─── Backend Tests ───
cd apps/auth-service
uv run pytest tests/ -v
cd apps/subscription-service
uv run pytest tests/ -v
# ─── Frontend ───
cd frontend/web-app
pnpm test
pnpm test:coverage# Conectar a PostgreSQL (Docker)
docker exec -it fintech_postgres psql -U core -d core_db
# Ver tablas
\dt
# Ver datos de planes
SELECT id, name, price, stripe_price_id FROM plans;
# Ver usuarios
SELECT id, email, created_at FROM auth.users;# Acceder a MinIO Console
open http://localhost:9001
# Credenciales (del .env)
# MINIO_ROOT_USER: admin
# MINIO_ROOT_PASSWORD: minio_dev_password# ════════════════════════════════════════════════════════════════
# POSTGRESQL
# ════════════════════════════════════════════════════════════════
POSTGRES_USER=core
POSTGRES_PASSWORD=your_secure_password
POSTGRES_DB=core_db
# ════════════════════════════════════════════════════════════════
# DATABASE URL
# ════════════════════════════════════════════════════════════════
DATABASE_URL=postgresql+asyncpg://core:your_secure_password@postgres:5432/core_db
# ════════════════════════════════════════════════════════════════
# MINIO (S3-compatible Storage)
# ════════════════════════════════════════════════════════════════
MINIO_ROOT_USER=admin
MINIO_ROOT_PASSWORD=your_secure_password
MINIO_BUCKET=core-storage
S3_ENDPOINT=http://minio:9000
S3_ACCESS_KEY=admin
S3_SECRET_KEY=your_secure_password
# ════════════════════════════════════════════════════════════════
# AUTH SERVICE
# ════════════════════════════════════════════════════════════════
AUTH_SECRET_KEY=generate_a_very_long_random_string
# ════════════════════════════════════════════════════════════════
# STRIPE (Test Mode)
# ════════════════════════════════════════════════════════════════
STRIPE_SECRET_KEY=sk_test_...
STRIPE_PUBLISHABLE_KEY=pk_test_...
STRIPE_WEBHOOK_SECRET=whsec_...
# ════════════════════════════════════════════════════════════════
# FRONTEND
# ════════════════════════════════════════════════════════════════
FRONTEND_URL=http://localhost:3000
NEXT_PUBLIC_API_URL=http://localhost:8080- Ir a https://dashboard.stripe.com/test/apikeys
- Copiar las claves de Test Mode:
STRIPE_SECRET_KEY(sk_test_...)STRIPE_PUBLISHABLE_KEY(pk_test_...)
- Actualizar el archivo
.env
- Ir a https://dashboard.stripe.com/test/products
- Asegurarse de estar en Test Mode (toggle esquina superior derecha)
- Click en "+ Add product"
- Crear 3 productos:
| # | Nombre | Precio | Intervalo |
|---|---|---|---|
| 1 | Basic Plan | $9.99 USD | Monthly |
| 2 | Pro Plan | $29.99 USD | Monthly |
| 3 | Enterprise Plan | $99.99 USD | Monthly |
- Por cada producto, copiar el Price ID (empieza con
price_)
Opción A: Con DataGrip
-- Ejecutar en DataGrip
UPDATE plans SET stripe_price_id = 'price_ID_DEL_BASIC' WHERE id = 1;
UPDATE plans SET stripe_price_id = 'price_ID_DEL_PRO' WHERE id = 2;
UPDATE plans SET stripe_price_id = 'price_ID_DEL_ENTERPRISE' WHERE id = 3;Opción B: Con Docker
docker exec -it fintech_postgres psql -U core -d core_db -c \
"UPDATE plans SET stripe_price_id = 'price_xxx' WHERE id = 1;"Opción C: Con psql directamente
docker exec -it fintech_postgres psql -U core -d core_dbSELECT id, name, price, stripe_price_id FROM plans;Debería mostrar:
id | name | price | stripe_price_id
----+------------------+--------+----------------------------------------
1 | Basic | 9.99 | price_1TMKyDBm0MtoBY37dVIsDJ4Q
2 | Pro | 29.99 | price_1TMKyHBm0MtoBY37CqZy5MVp
3 | Enterprise | 99.99 | price_1TMKyNBm0MtoBY37VxJN1ONY
Para recibir eventos de Stripe cuando un pago se complete:
- Ir a https://dashboard.stripe.com/test/webhooks
- Click en "Add endpoint"
- Configurar:
- URL:
http://localhost:8080/api/subscriptions/webhook - Events:
checkout.session.completed,customer.subscription.deleted
- URL:
- Copiar el Signing secret (
whsec_...) - Actualizar
STRIPE_WEBHOOK_SECRETen.env - Reconstruir el servicio:
docker compose up --build subscription_service
| Tarjeta | Uso |
|---|---|
4242 4242 4242 4242 |
Pago exitoso |
4000 0000 0000 0002 |
Pago declinado |
4000 0025 0000 3155 |
Requiere 3D Secure |
- Fecha expiración: Cualquier fecha futura
- CVC:
123 - Código postal: Cualquier código válido
┌──────────┐ ┌──────────┐ ┌──────────┐
│ Register │ ──▶ │ Login │ ──▶ │Dashboard │
└──────────┘ └──────────┘ └──────────┘
│ │ │
▼ ▼ ▼
/api/auth/register /api/auth/login /api/auth/me
┌────────────┐ ┌────────────┐ ┌────────────┐ ┌────────────┐
│ Subscription│───▶│ Checkout │───▶│ Stripe │───▶│ Success │
│ Page │ │ Session │ │ Form │ │ Page │
└────────────┘ └────────────┘ └────────────┘ └────────────┘
│ │ │
▼ ▼ ▼
/api/subscriptions POST /subscribe /subscription/success
┌──────────┐ ┌────────────────┐ ┌──────────┐
│Dashboard │───▶│ Subscription │───▶│ Frontend │
│ │ │ Service Proxy │ │ Chart │
└──────────┘ └────────────────┘ └──────────┘
│
▼
┌─────────────────┐
│ Yahoo Finance │
│ API │
└─────────────────┘
Base URL: http://localhost:8080/api/auth
| Method | Endpoint | Descripción | Auth |
|---|---|---|---|
| POST | /register |
Registrar nuevo usuario | No |
| POST | /login |
Iniciar sesión | No |
| POST | /refresh |
Refrescar access token | No |
| GET | /me |
Obtener perfil usuario | JWT |
| POST | /logout |
Cerrar sesión | JWT |
| GET | /health |
Health check | No |
Base URL: http://localhost:8080/api/subscriptions
| Method | Endpoint | Descripción | Auth |
|---|---|---|---|
| GET | /plans |
Listar planes disponibles | No |
| GET | /plans/{id} |
Obtener plan específico | No |
| POST | /subscribe |
Crear sesión de checkout | JWT |
| GET | /me |
Mi suscripción activa | JWT |
| POST | /cancel/{id} |
Cancelar suscripción | JWT |
| POST | /webhook |
Webhook de Stripe | No |
| GET | /health |
Health check | No |
Base URL: http://localhost:8080/api/market
| Method | Endpoint | Descripción | Auth |
|---|---|---|---|
| GET | /chart/{symbol} |
Datos de acciones | No |
Parámetros:
symbol: Símbolo de la acción (ej: SPY, AAPL, GOOGL)interval: Intervalo de tiempo (1m, 5m, 15m, 1h, 1d)range: Rango de datos (1d, 5d, 1mo, 3mo, 6mo, 1y)
Ejemplo:
curl "http://localhost:8080/api/market/chart/SPY?interval=1d&range=30d"Símbolos disponibles: SPY, AAPL, GOOGL, MSFT, AMZN, TSLA, META, NVDA
Base URL: http://localhost:8080
| Endpoint | Descripción |
|---|---|
/nginx-health |
Health check de nginx |
/health |
Health check del Auth Service |
- Swagger UI: http://localhost:8080/api/auth/docs
- ReDoc: http://localhost:8080/api/auth/redoc
# 1. Backend (dos terminales)
cd apps/auth-service
uv sync
uv run uvicorn app.main:app --reload --port 5000
cd apps/subscription-service
uv sync
uv run uvicorn app.main:app --reload --port 5001
# 2. Frontend
cd frontend/web-app
pnpm install
pnpm dev-
Crear rama desde
develop:git checkout -b feature/mi-nueva-funcion
-
Hacer cambios y commit:
git add . git commit -m "feat: descripción del cambio"
-
Push y crear PR:
git push origin feature/mi-nueva-funcion
apps/
├── auth-service/
│ └── tests/
│ ├── __init__.py
│ ├── conftest.py
│ └── test_auth.py
│
└── subscription-service/
└── tests/
├── __init__.py
├── conftest.py
└── test_subscriptions.py
# Auth Service
cd apps/auth-service
uv run pytest tests/ -v --cov=app --cov-report=html
# Subscription Service
cd apps/subscription-service
uv run pytest tests/ -v --cov=app
# Frontend
cd frontend/web-app
pnpm test
pnpm test:coverageEl proyecto usa GitHub Actions para CI/CD:
- Lint - Verificación de código (ruff, pnpm lint)
- Test Backend - Tests unitarios con PostgreSQL
- Test Frontend - Type check y build
- Docker Build - Construcción de imágenes
- Security Scan - Escaneo de vulnerabilidades (Trivy)
- E2E Tests - Tests de extremo a extremo
- Deploy Staging - Despliegue a staging (branch develop)
- Deploy Production - Despliegue a producción (branch main)
Configurar en GitHub Secrets:
STRIPE_SECRET_KEYSTRIPE_WEBHOOK_SECRETAWS_ACCESS_KEY_ID(para producción)AWS_SECRET_ACCESS_KEY(para producción)
# Ver logs
docker compose logs postgres
# Verificar puertos
lsof -i :5432# Verificar que postgres está healthy
docker compose ps postgres
# Ver logs
docker compose logs auth_service# Verificar que nginx está corriendo
docker compose ps nginx
# Ver logs
docker compose logs nginx- Verificar que los Price IDs en la base de datos son correctos
- Ejecutar:
SELECT id, name, stripe_price_id FROM plans;
- Comparar con los Price IDs en Stripe Dashboard
Es normal. Yahoo Finance limita las solicitudes. Esperar unos minutos e intentar de nuevo.
docker compose down -v
docker compose up --build -dLos contratos OpenAPI están en:
contracts/openapi/
└── fintech-api.yaml
Los diagramas de arquitectura están basados en:
/mnt/c/Users/Chris/Documents/image_full_hd/arquitectura_finance_plus.png/mnt/c/Users/Chris/Documents/image_full_hd/fintech_mapa_maestro.png/mnt/c/Users/Chris/Documents/image_full_hd/finance_db_storage.png
MIT License - Ver archivo LICENSE para más detalles.