Flujo de Webhooks
Procesamiento
flowchart TD
MP["MercadoPago envía webhook"] --> SIG{"Firma HMAC<br/>válida?"}
SIG -->|No| REJECT["401 Unauthorized"]
SIG -->|Sí| PARSE{"Payload<br/>válido (Zod)?"}
PARSE -->|No| INVALID["422 Validation Error"]
PARSE -->|Sí| LOG["Guardar webhook_log"]
LOG --> FIND{"¿Existe orden<br/>en DB?"}
FIND -->|Sí| UPDATE["Actualizar estado<br/>de la orden"]
FIND -->|No| SKIP["Solo log"]
UPDATE --> OK["200 OK"]
SKIP --> OK
Eventos y transiciones
graph LR
subgraph Webhooks["Webhooks recibidos"]
W1["order.processed"]
W2["order.canceled"]
W3["order.expired"]
W4["order.failed"]
W5["order.action_required"]
W6["order.refunded"]
W7["order.partially_refunded"]
end
subgraph Estados["Estado en DB"]
S1["completed"]
S2["canceled"]
S3["updated"]
end
W1 --> S1
W2 --> S2
W3 --> S2
W4 --> S3
W5 --> S3
W6 --> S3
W7 --> S3
Timing
| Evento | Latencia típica |
|---|---|
Orden creada → at_terminal |
1-3 segundos |
Pago en terminal → order.processed |
2-5 segundos |
Cancelación → order.canceled |
1-2 segundos |
Expiración → order.expired |
Al cumplirse el timeout |
Reembolso → order.refunded |
2-10 segundos |
Retry de MercadoPago
MercadoPago reintenta webhooks si no recibe 200:
| Intento | Delay |
|---|---|
| 1 | Inmediato |
| 2 | 5 minutos |
| 3 | 45 minutos |
| 4 | 6 horas |
| 5 | 2 días |
| 6 | 4 días |
Siempre devolver 200
La API siempre devuelve 200 después de procesar el webhook, incluso si la orden no existe en la DB. Esto evita retries innecesarios de MP.