Webhook trust
Verify the event before you update the order.
XPayr signs webhook payloads with your webhook secret. Store the raw request body, verify X-XPayr-Signature, then process the event idempotently.
Headers to read
X-XPayr-Signature: HMAC SHA-256 signature prefixed withsha256=.X-XPayr-Event: event type such aspayment.completed.X-XPayr-Delivery: delivery/event identifier where available.
Node.js verification
import crypto from "node:crypto";
export function verifyXPayrWebhook(rawBody, signatureHeader, secret) {
const received = String(signatureHeader || "").replace(/^sha256=/, "");
const expected = crypto
.createHmac("sha256", secret)
.update(rawBody)
.digest("hex");
return crypto.timingSafeEqual(
Buffer.from(received, "hex"),
Buffer.from(expected, "hex")
);
}
PHP verification
function verify_xpayr_webhook(string $rawBody, string $signatureHeader, string $secret): bool
{
$received = preg_replace('/^sha256=/', '', trim($signatureHeader));
$expected = hash_hmac('sha256', $rawBody, $secret);
return is_string($received) && hash_equals($expected, $received);
}
Events to handle
At minimum, handle payment.completed, payment.failed, payment.expired, and test.webhook. Use the session ID and your own metadata order ID to reconcile.