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 processingpayment.succeeded— customer paid; funds settled to your ledgerpayment.failed— customer failed to paypayment.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')
);
}