How It Works

  1. Extract Headers: Read the incoming webhook signature (X-OneKhusa-Webhook-Signature) and webhook event code (OneKhusa-Webhook-Event) from the request headers. Webhook signature supports HMAC-SHA512 for payload hashing.
  2. Read Raw Payload: Read the exact, unparsed request body string/bytes.
  3. Compute Local Hash: Generate an HMAC-SHA512 hash using your OneKhusa webhook secret and the raw payload body.
  4. Timing-Safe Comparison: Compare your computed signature against the header signature using a fixed-time equality check to protect against timing attacks.
  5. Payload Check: When the request payload is validated and verified to be originating from OneKhusa, proceed to finalise the transaction in your system.

Implementation Details

This section provides sample code for C#, PHP and JavaScript on how to programmatically verify webhook notifications locally.

1. C# (.NET Core)

Use HMACSHA512 alongside CryptographicOperations.FixedTimeEquals for constant-time comparison.

2. PHP

Use hash_hmac() to compute the hash and hash_equals() for timing-safe comparison.

3. JavaScript (Node.js / Express)

Use crypto.createHmac() and crypto.timingSafeEqual() with Buffer instances.

Crucial Rules for Local Verification

⚠️ Always read the raw request body string prior to JSON parsing. Re-serializing parsed JSON alters whitespace or field order, causing signature checks to fail.
⚠️ Always use constant-time string equality functions (FixedTimeEquals, hash_equals, or timingSafeEqual) to prevent timing attacks.