Desarrolladores
Webhooks
Cuando una factura cambia de estado, CryBit envía una solicitud POST firmada con cuerpo JSON a la URL de webhook de su comercio.
Configuración
Defina la URL del webhook y marque los eventos en la configuración del comercio, en la pestaña de integración: paid, expired, refunded, cancelled. La URL debe ser una dirección HTTP o HTTPS pública en el puerto 80, 443, 8080 u 8443; no se siguen las redirecciones. Se define en el comercio, no en la solicitud de la factura.
Encabezados
| Encabezado | Valor |
|---|---|
X-CryBit-Event | El nombre del evento, por ejemplo payment.paid. |
X-CryBit-Signature | t=<unix time>,v1=<hex>: HMAC-SHA256 de "<t>.<raw body>" con su secreto de firma. |
Verificar la firma
El secreto de firma se muestra en la configuración del comercio junto a la URL del webhook. Calcule la firma sobre el cuerpo sin procesar, compare en tiempo constante y rechace las solicitudes con más de cinco minutos de antigüedad.
PHP
$secret = getenv('CRYBIT_WEBHOOK_SECRET');
$body = file_get_contents('php://input');
$header = $_SERVER['HTTP_X_CRYBIT_SIGNATURE'] ?? '';
parse_str(str_replace(',', '&', $header), $p); // t=…&v1=…
$t = (int) ($p['t'] ?? 0);
$expected = hash_hmac('sha256', $t . '.' . $body, $secret);
if (abs(time() - $t) > 300 || !hash_equals($expected, $p['v1'] ?? '')) {
http_response_code(400);
exit;
}
// the request is genuine: store the event, answer 200, do the rest later
http_response_code(200);Node.js
import crypto from 'node:crypto'
export function verify(rawBody, header, secret) {
const parts = Object.fromEntries(header.split(',').map((kv) => kv.split('=')))
const t = Number(parts.t)
const expected = crypto.createHmac('sha256', secret).update(t + '.' + rawBody).digest('hex')
const ok = parts.v1 && parts.v1.length === expected.length
&& crypto.timingSafeEqual(Buffer.from(parts.v1), Buffer.from(expected))
return ok && Math.abs(Date.now() / 1000 - t) <= 300
}Entrega y reintentos
- Responda rápido con un estado 2xx: CryBit espera unos doce segundos.
- Si no responde, CryBit reintenta tras 15 segundos, 1 minuto, 5, 15 y 30 minutos, y luego tras 2, 6 y 24 horas.
- Una respuesta 4xx, salvo 429, detiene los reintentos.
- El mismo evento puede llegar más de una vez: procéselo de forma idempotente, usando como clave order_id o el uuid de la factura.
- Si se perdió un webhook, consulte el estado con GET /api/v1/payments/{uuid}: siempre es la fuente de verdad.
FAQ
¿Puedo ver lo que se entregó?
Sí. La página de registros de la API en la cuenta de comercio lista las solicitudes y las entregas de webhooks con el código de estado y el cuerpo.
