Desenvolvedores
Webhooks
Quando uma fatura muda de estado, a CryBit envia uma requisição POST assinada, com corpo JSON, para a URL de webhook do seu merchant.
Configuração
Defina a URL do webhook e marque os eventos nas configurações do merchant, na aba de integração: paid, expired, refunded, cancelled. A URL deve ser um endereço HTTP ou HTTPS público na porta 80, 443, 8080 ou 8443; redirecionamentos não são seguidos. Ela é definida no merchant, não na requisição da fatura.
Cabeçalhos
| Cabeçalho | Valor |
|---|---|
X-CryBit-Event | O nome do evento, por exemplo payment.paid. |
X-CryBit-Signature | t=<unix time>,v1=<hex>: HMAC-SHA256 de "<t>.<raw body>" com o seu segredo de assinatura. |
Verifique a assinatura
O segredo de assinatura aparece nas configurações do merchant, ao lado da URL do webhook. Calcule a assinatura sobre o corpo bruto, compare em tempo constante e rejeite requisições com mais de cinco minutos.
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 e novas tentativas
- Responda rapidamente com um status 2xx: a CryBit espera cerca de doze segundos.
- Se você não responder, a CryBit tenta de novo após 15 segundos, 1 minuto, 5, 15 e 30 minutos, depois 2, 6 e 24 horas.
- Uma resposta 4xx, exceto 429, interrompe as novas tentativas.
- O mesmo evento pode chegar mais de uma vez: trate-o de forma idempotente, usando order_id ou o uuid da fatura como chave.
- Se você perdeu um webhook, consulte o status com GET /api/v1/payments/{uuid}: ele é sempre a fonte da verdade.
FAQ
Posso ver o que foi entregue?
Sim. A página de logs da API na conta do lojista lista as requisições e as entregas de webhook com o código de status e o corpo.
