Nijipe DevelopersREST API SPECIFICATION
Access Merchant Hub

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);
}