6. Cryptographic Webhook HMAC Signatures
When invoice state changes occur, Nijipe triggers an automated callback post request to your store's configured webhook URL.
Event Triggered
Invoice status updates (e.g. pending to paid)
Payload Signed
HMAC-SHA256 signature generated with your secret
POST Dispatched
Payload and X-Nijipe-Signature sent to URL
Verification
Merchant verifies signature matches locally
To verify that the webhook request actually originated from Nijipe, compute the HMAC-SHA256 signature using the raw body payload string and your store's dedicated Webhook Secret as the cryptographic secret, and match it against the header: X-Nijipe-Signature.
Code Examples
Node.js / TypeScript
const crypto = require('crypto');
function verifyWebhook(requestBody: string | Buffer, signatureHeader: string, webhookSecret: string) {
const computedSignature = crypto
.createHmac('sha256', webhookSecret)
.update(requestBody)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signatureHeader, 'hex'),
Buffer.from(computedSignature, 'hex')
);
}Python
import hmac
import hashlib
def verify_webhook(request_body: bytes, signature_header: str, webhook_secret: str) -> bool:
computed_signature = hmac.new(
key=webhook_secret.encode('utf-8'),
msg=request_body,
digestmod=hashlib.sha256
).hexdigest()
return hmac.compare_digest(signature_header, computed_signature)Go
import (
"crypto/hmac"
"crypto/sha256"
"crypto/subtle"
"encoding/hex"
)
func VerifyWebhook(requestBody []byte, signatureHeader string, webhookSecret string) bool {
mac := hmac.New(sha256.New, []byte(webhookSecret))
mac.Write(requestBody)
computedSignature := hex.EncodeToString(mac.Sum(nil))
// Use ConstantTimeCompare to prevent timing attacks
return subtle.ConstantTimeCompare(
[]byte(signatureHeader),
[]byte(computedSignature)
) == 1
}PHP
function verify_webhook($request_body, $signature_header, $webhook_secret) {
$computed_signature = hash_hmac('sha256', $request_body, $webhook_secret);
// Use hash_equals to prevent timing attacks
return hash_equals($signature_header, $computed_signature);
}