BEZ-Coin token logoBEZHAS
webhookIntegraciónIntermedio3 min de lectura

Webhooks de pagos

Los webhooks avisan a tu sistema cuando un pago de BeZhas Pay cambia de estado, sin que tengas que consultar la API cada pocos segundos. BeZhas firma cada entrega para que puedas comprobar que viene de BeZhas y que nadie la ha modificado por el camino.

Los webhooks se gestionan con la api-key de tu organización (X-API-Key). No se pueden registrar con un token OAuth de un conector de IA: registrar un destino que recibe tus pagos es una decisión de tu equipo técnico, no de un agente.

Eventos

EventoCuándo se envía
payment.settledEl pago está liquidado. Es el valor por defecto si no indicas eventos.
payment.failedEl pago no se pudo completar.
payment.expiredLa orden de pago caducó sin completarse.
payment.refundedSe ha devuelto el importe al pagador.

Registrar un webhook

bash
curl -X POST https://api.bezhas.com/api/gateway/v1/webhooks/register \
  -H "X-API-Key: $BEZHAS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url":"https://tu-empresa.com/webhooks/bezhas","events":["payment.settled","payment.refunded"]}'

La respuesta incluye el campo secret. Solo se muestra esta vez: guárdalo en tu gestor de secretos. Si lo pierdes, vuelve a registrar la misma URL y se generará uno nuevo (el anterior deja de valer).

Registrar de nuevo una URL que ya existe actualiza sus eventos y rota el secreto; no crea un duplicado.

Qué recibe tu servidor

Cada entrega es un POST con el evento en el cuerpo y estas cabeceras:

CabeceraContenido
X-BeZhas-Signaturesha256=<hex(HMAC-SHA256(secret, cuerpo_en_bruto))>
X-BeZhas-EventNombre del evento, p. ej. payment.settled
X-BeZhas-DeliveryIdentificador de la entrega. Úsalo para ignorar duplicados.

Responde con un código 2xx en menos de 10 segundos. Cualquier otra respuesta, o no responder, cuenta como fallo y se reintenta.

Verificar la firma

Calcula el HMAC sobre el cuerpo en bruto, tal como llega, antes de parsear el JSON. Si lo parseas y lo vuelves a serializar, el orden o los espacios pueden cambiar y la firma no coincidirá.

js
const crypto = require('crypto');

function firmaValida(secret, rawBody, cabecera) {
    const esperada = 'sha256=' + crypto.createHmac('sha256', secret).update(rawBody).digest('hex');
    const a = Buffer.from(esperada);
    const b = Buffer.from(String(cabecera || ''));
    return a.length === b.length && crypto.timingSafeEqual(a, b);
}

Usa siempre una comparación en tiempo constante (timingSafeEqual). Una comparación normal de cadenas permite adivinar la firma midiendo el tiempo de respuesta.

Reintentos

Si una entrega falla, se reintenta con espera exponencial: 1 minuto, luego 2, 4, 8… con un máximo de una hora entre intentos, hasta 8 intentos en total. Agotados los intentos, la entrega queda como dead y puedes reenviarla a mano.

bash
# Entregas recientes (filtra con ?status=pending|delivered|dead)
curl https://api.bezhas.com/api/gateway/v1/webhooks/deliveries?status=dead \
  -H "X-API-Key: $BEZHAS_API_KEY"

# Reenviar una entrega fallida
curl -X POST https://api.bezhas.com/api/gateway/v1/webhooks/deliveries/123/retry \
  -H "X-API-Key: $BEZHAS_API_KEY"

Como un evento puede llegar más de una vez, tu manejador debe ser idempotente: guarda el X-BeZhas-Delivery procesado y, si vuelve a llegar, responde 200 sin repetir la acción.

Gestionar tus webhooks

AcciónEndpoint
ListarGET /api/gateway/v1/webhooks (nunca devuelve el secreto)
DesactivarDELETE /api/gateway/v1/webhooks/:id
Ver entregasGET /api/gateway/v1/webhooks/deliveries
ReenviarPOST /api/gateway/v1/webhooks/deliveries/:id/retry

Buenas prácticas

  • Usa HTTPS en tu URL de destino.
  • Verifica la firma antes de hacer nada con el contenido.
  • No confíes solo en el webhook para entregar valor: ante la duda, consulta el estado del pago en la API.
  • Guarda el secreto en un gestor de secretos, nunca en el repositorio.

Ver también