Webhooks
Los webhooks permiten que tu servidor reciba notificaciones en tiempo real cuando se completa un pago. Esta es la forma recomendada de confirmar pagos en producción, ya que proporciona una comunicación confiable de servidor a servidor.
Cómo Funcionan los Webhooks
Cuando un cliente completa un pago a través del botón SmartPay:
- ApoloPay envía una petición HTTP
POSTa la URL de tu webhook configurada - Tu servidor recibe la petición con los detalles del pago
- Tu servidor verifica la autenticidad del webhook usando el secreto de webhook (webhook secret)
- Tu servidor procesa la confirmación del pago (ej., actualiza el estado del pedido)
Configurar Webhooks
- Ve al Panel de ApoloPay
- Navega a la configuración de tu botón de pago
- En la sección Webhook, ingresa la URL de tu endpoint
- Guarda — Se generará un Secreto de Webhook para ti
tip
El endpoint de tu webhook debe ser públicamente accesible mediante HTTPS. Durante el desarrollo, puedes usar herramientas como ngrok para exponer tu servidor local.
Payload del Webhook
Cuando se completa un pago, ApoloPay envía una petición POST a la URL de tu webhook con la siguiente estructura:
{
"event": "payment.completed",
"processId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"amount": 25.50,
"metadata": {
"orderId": "ORD-9821",
"customerEmail": "[email protected]"
},
"timestamp": "2026-03-19T12:00:00Z"
}
Manejo de Webhooks
Node.js (Express)
const express = require('express');
const crypto = require('crypto');
const app = express();
const WEBHOOK_SECRET = process.env.APOLOPAY_WEBHOOK_SECRET;
// Usa el raw body para verificar la firma
app.post(
'/api/webhooks/apolopay',
express.raw({ type: 'application/json' }),
(req, res) => {
const signature = req.headers['x-apolopay-signature'];
const payload = req.body.toString();
// Verifica la firma del webhook
const expectedSignature = crypto
.createHmac('sha256', WEBHOOK_SECRET)
.update(payload)
.digest('hex');
if (signature !== expectedSignature) {
console.error('Firma de webhook inválida');
return res.status(401).json({ error: 'Firma inválida' });
}
// Procesa el webhook
const event = JSON.parse(payload);
console.log('Pago completado:', event.processId);
// Actualiza el estado de tu pedido en la base de datos
// ...
// Responde con 200 para confirmar la recepción
res.status(200).json({ received: true });
}
);
Python (FastAPI)
import hmac
import hashlib
from fastapi import FastAPI, Request, HTTPException
import os
app = FastAPI()
WEBHOOK_SECRET = os.getenv("APOLOPAY_WEBHOOK_SECRET")
@app.post("/api/webhooks/apolopay")
async def handle_webhook(request: Request):
payload = await request.body()
signature = request.headers.get("x-apolopay-signature")
# Verifica la firma del webhook
expected_signature = hmac.new(
WEBHOOK_SECRET.encode(),
payload,
hashlib.sha256,
).hexdigest()
if signature != expected_signature:
raise HTTPException(status_code=401, detail="Firma inválida")
# Procesa el webhook
event = await request.json()
print(f"Pago completado: {event['processId']}")
# Actualiza el estado de tu pedido en la base de datos
# ...
return {"received": True}
Mejores Prácticas
| Práctica | Descripción |
|---|---|
| Siempre verifica las firmas | Usa el secreto del webhook para validar que las peticiones provienen de ApoloPay |
| Responde rápidamente | Devuelve un código 200 lo antes posible. Procesa tareas pesadas asincrónicamente |
| Maneja duplicados | Tu endpoint debe ser idempotente — el mismo evento puede ser enviado múltiples veces |
| Usa HTTPS | Siempre usa HTTPS para el endpoint de tu webhook en producción |
| Registra (log) eventos | Mantén un registro de los eventos webhook recibidos para depuración |
Política de Reintentos
Si tu servidor no responde con un estado 2xx, ApoloPay reintentará procesar la entrega del webhook con retroceso exponencial (exponential backoff).
Siguientes Pasos
- Integración Backend → — Crea procesos de pago desde tu backend
- Descripción de SmartPay → — Revisa el flujo de pago completo