Ir al contenido

Webhook — test vectors

Use este vector para validar su función de verificación antes de conectar a producción. Si su implementación produce la firma esperada, puede confiar en su algoritmo.

Confirmado por el equipo de backend. Aplicando hex(HMAC_SHA256(bytes.fromhex(secret), nonce + body)) sobre estos valores obtendrá exactamente la firma indicada.

secret_key (hex):
02d4b921007cad413e79731dd02b3267cd43a14d150a0ae6a1c651942122bb62
nonce:
1645634942
body (UTF-8 compacto, exactamente así — sin espacios envolventes):
{"fiat_amount": 100.0, "fiat_currency": "USD", "status": "AC", "crypto_amount": 1.21461894, "unconfirmed_amount": 8.0, "confirmed_amount": 0.0, "currency": "DASH", "identifier": "1040095a-737d-41a2-a2e1-d031d19ec8cd"}
X-SIGNATURE:
395a6c0294f0896fcc0e5827e926e12308f4fdca5c18da69d3af6879e5c80e2d
import crypto from 'node:crypto';
const secretHex = '02d4b921007cad413e79731dd02b3267cd43a14d150a0ae6a1c651942122bb62';
const nonce = '1645634942';
const body = '{"fiat_amount": 100.0, "fiat_currency": "USD", "status": "AC", "crypto_amount": 1.21461894, "unconfirmed_amount": 8.0, "confirmed_amount": 0.0, "currency": "DASH", "identifier": "1040095a-737d-41a2-a2e1-d031d19ec8cd"}';
const expected = '395a6c0294f0896fcc0e5827e926e12308f4fdca5c18da69d3af6879e5c80e2d';
const got = crypto
.createHmac('sha256', Buffer.from(secretHex, 'hex'))
.update(nonce + body, 'utf8')
.digest('hex');
console.log(got === expected ? '✓ OK' : `✗ mismatch: ${got}`);

Si su resultado no coincide con 395a6c02…, revise en este orden:

  1. Secret decoding — ¿convirtió el hex a bytes? (Buffer.from(hex, 'hex') en Node, bytes.fromhex(hex) en Python, hex2bin($hex) en PHP).
  2. Body exact match — ¿usa el body crudo, byte a byte? Reserializar JSON cambia el whitespace y rompe la firma. El body debe leerse del stream HTTP como string/Buffer sin pasar por JSON.parse y luego JSON.stringify.
  3. Formato del body — sin espacios envolventes entre { y el primer campo, con , y : entre pares.
  4. Concatenaciónnonce + body en ese orden, sin separadores ni trailing newline.
  5. Charset — UTF-8.
  6. Output encoding — hex lowercase.
  • Con Claude / Cursor: instale el MCP server @b4bit/b4bit-pay-mcp (npx @b4bit/b4bit-pay-mcp). Su tool verify_webhook reproduce este algoritmo con diagnósticos detallados cuando la firma no coincide (secret mal decodificado, concatenación inversa, whitespace envolvente).
  • En producción: capture un webhook real (usando ngrok o cloudflared) y verifique contra ese body concreto byte-exact. Es la validación definitiva antes de ir live.