JCPay· Webhooks

Webhooks

JCPay POSTs JSON event payloads to your registered endpoints with an HMAC-SHA256 signature for verification. Events are queued and retried with exponential backoff on failure.

Signature verification

X-NexusPay-Signature: t=1714010000,v1=a3f8d2b1...

// To verify:
//   signedPayload = timestamp + '.' + rawBody
//   expected      = HMAC_SHA256(signingSecret, signedPayload)
//   expected === v1 (constant-time compare)
// Reject if |now - timestamp| > 300 seconds.

Events

  • payment.processing — provider has started processing
  • payment.succeeded — customer paid; funds settled to your ledger
  • payment.failed — customer failed to pay
  • payment.expired — checkout window elapsed without payment

Retry schedule

On non-2xx, JCPay retries at: 1m, 5m, 30m, 2h, 6h, 24h. After 6 failures the delivery is marked failed; you can replay it manually from the dashboard.

Node.js verification example

import crypto from 'node:crypto';

function verify(secret, rawBody, header) {
  const [tPart, vPart] = header.split(',');
  const t = Number(tPart.split('=')[1]);
  const v1 = vPart.split('=')[1];
  if (Math.abs(Date.now() / 1000 - t) > 300) return false;
  const expected = crypto
    .createHmac('sha256', secret)
    .update(t + '.' + rawBody)
    .digest('hex');
  return crypto.timingSafeEqual(
    Buffer.from(expected, 'hex'),
    Buffer.from(v1, 'hex')
  );
}