Visión General
Arquitectura de alto nivel
graph TB
subgraph Clientes["Clientes"]
ERP1["ERP Cliente A"]
ERP2["ERP Cliente B"]
DASH["Dashboard Admin"]
end
subgraph CF["Cloudflare"]
WORKER["⚡ Worker<br/>Hono + OpenAPI"]
D1["🗄️ D1 Database<br/>SQLite"]
CRON["⏰ Cron Trigger<br/> Token Refresh"]
end
subgraph MP["MercadoPago"]
MPAPI["API v1"]
MPOAUTH["OAuth Server"]
MPWEBHOOK["Webhook Sender"]
end
ERP1 -->|"x-api-token: mk_..."| WORKER
ERP2 -->|"x-api-token: mk_..."| WORKER
DASH -->|"x-api-token"| WORKER
WORKER <-->|"Bearer token"| MPAPI
WORKER <-->|"PKCE Flow"| MPOAUTH
MPWEBHOOK -->|"HMAC-SHA256"| WORKER
WORKER <--> D1
CRON --> WORKER
Flujo de una orden de pago
sequenceDiagram
participant ERP
participant API as Integration API
participant DB as D1 Database
participant MP as MercadoPago
ERP->>API: POST /orders (caja_id, amount)
API->>DB: Buscar POS → obtener terminal
API->>MP: POST /v1/orders (terminal_id, amount)
MP-->>API: order_id, status: "created"
API->>DB: Guardar orden
API-->>ERP: 201 { order_id, status }
Note over MP: El cliente paga en la terminal
MP->>API: Webhook order.processed
API->>DB: Actualizar estado orden
API-->>MP: 200 OK
ERP->>API: GET /orders/:orderId
API->>DB: Buscar orden local
API->>MP: GET /v1/orders/:id (estado real)
MP-->>API: status: "processed", payments: [...]
API->>DB: Actualizar si cambió
API-->>ERP: 200 { status, payments, refunds }
Capas del sistema
graph TD
subgraph Request["Request Layer"]
MW1["Security Middleware<br/>adminToken() / clientToken()"]
MW2["Activity Log Middleware"]
MW3["Webhook Signature Middleware"]
end
subgraph Routes["Route Layer"]
R1["OAuth Routes"]
R2["Store Routes"]
R3["Terminal Routes"]
R4["Order Routes"]
R5["Webhook Routes"]
R6["API Key Routes"]
R7["Admin Routes"]
R8["Health Routes"]
end
subgraph Business["Business Layer"]
DB["lib/database.ts<br/>Queries & mutations"]
MPLIB["lib/mercadopago.ts<br/>mpRequest() centralizado"]
KEYS["lib/api-key.ts"]
PKCE["lib/pkce.ts"]
end
subgraph Data["Data Layer"]
D1DB["Cloudflare D1"]
MPAPI["MercadoPago API"]
end
MW1 --> Routes
MW2 --> Routes
MW3 --> R5
Routes --> Business
DB --> D1DB
MPLIB --> MPAPI
Multi-tenancy
Cada cliente es completamente aislado:
graph LR
subgraph ClienteA["Cliente A"]
KEY_A["API Key: mk_abc..."]
OAUTH_A["OAuth Token MP"]
STORES_A["Stores + POS"]
ORDERS_A["Orders"]
end
subgraph ClienteB["Cliente B"]
KEY_B["API Key: mk_xyz..."]
OAUTH_B["OAuth Token MP"]
STORES_B["Stores + POS"]
ORDERS_B["Orders"]
end
API["Integration API"]
API --> ClienteA
API --> ClienteB
- Cada cliente tiene su propia cuenta de MercadoPago (OAuth independiente)
- Las API keys identifican al cliente automáticamente
- Todas las queries filtran por
client_name - Un cliente nunca puede ver datos de otro