Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Request Headers

Code Block
languagejson
{
  "user-agent": "ReactorNetty/1.1.9",
  "content-length": "631",
  "accept": "application/json",
  "accept-encoding": "gzip",
  "content-type": "application/json",
  "moniepoint-webhook-id": "b15ec58f-fa1f-4abb-8329-efaef8aa2bef",
  "moniepoint-webhook-signature": "WMfZqwVUKvjo6eY/W4qh5FT2M6Wb/2nSuC3aVMbpSNA=",
  "moniepoint-webhook-timestamp": "1728651860073",
  "x-forwarded-for": "141.147.77.31",
  "x-forwarded-host": "wenhookdemo.free.beeceptor.com",
  "x-forwarded-proto": "https"
}

...

The body of the webhook POST request contains a JSON object with details about the transaction. Below is an example payload:

Code Block
languagejson
{
  "data": {
    "amount": 25300,
    "businessId": 150,
    "customFields": {
      "Invoice ID": "82674382"
    },
    "responseCode": "09",
    "terminalSerial": "P260300326393",
    "businessOwnerId": 100,
    "responseMessage": "Airtime Purchase Pending",
    "transactionTime": "2024-10-10T09:32:57.916+0100",
    "transactionType": "AIRTIME",
    "merchantReference": "",
    "transactionStatus": "PENDING",
    "transactionReference": "ATP|2MPT0073|1838496858930533333120",
    "retrievalReferenceNumber": ""
  },
  "eventId": "59630e16-34f0-40ee-b5c3-a3d66e71ca41",
  "subject": {
    "domain": "CHANNELS",
    "resource": "business",
    "resourceId": "150"
  },
  "createdAt": "2024-10-11T14:04:20.051330639",
  "eventType": "V1_POS_AIRTIME_TRANSACTION"
}

...

Code Sample for Signature Verification

Code Block
languagejs
const crypto = require('crypto');
/**
 * Validates the webhook payload signature against the expected signature.
 *
 * @param {string} webhookId - The unique identifier for the webhook.
 * @param {string} timestamp - The timestamp of the webhook event.
 * @param {string} requestBody - The body of the request as a JSON string.
 * @param {string} signature - The signature received in the webhook request.
 * @param {string} secretKey - The secret key used to generate the signature.
 * @returns {boolean} - Returns true if the signature is valid, false otherwise.
 *
 * @example
 * const webhookId = "your_webhook_id";
 * const timestamp = "timestamp_value";
 * const requestBody = '{"key": "value"}';
 * const expectedSignature = "HvzIH3TaI0jFiMPbcuH4NblQ9Mmz+WKzodD1dpFlMHM=";
 * const secretKey = "your_secret_key";
 *
 * const isValid = isPayloadSignatureValid(webhookId, timestamp, requestBody, expectedSignature, secretKey);
 * console.log(`Signature is valid: ${isValid}`);
 */
const isPayloadSignatureValid = (webhookId, timestamp, requestBody, signature, secretKey) => {
  const data = `${webhookId}__${timestamp}__${requestBody}`;
  const expectedSignature = crypto.createHmac('sha256', secretKey).update(data).digest('base64');
  return signature === expectedSignature;
};

...