Header format: PayProof-Signature: t=<unix>,v1=<hex>
Verify
Compute HMAC-SHA256(secret, "${t}.${raw_body}") and compare to v1 (lowercase hex).
Node
import crypto from "crypto";
export function verifyPayProofSignature(secret, rawBody, header) {
const parts = Object.fromEntries(
header.split(",").map((p) => p.trim().split("="))
);
const expected = crypto
.createHmac("sha256", secret)
.update(`${parts.t}.${rawBody}`)
.digest("hex");
return crypto.timingSafeEqual(
Buffer.from(expected),
Buffer.from(parts.v1 || "")
);
}