Skip to main content

Webhook Authentication

MunoPay signs all webhook requests, allowing you to verify their authenticity. While optional, this provides an additional layer of security for applications handling sensitive data.

Verifying Request Signatures

Webhook POST requests include a MunoPay-Signature header. To verify the request, generate a signature using your webhook key and compare it with the header value.

Webhook Authentication Key

Your webhook key is automatically generated when you create a business account. You can view or reset it in your account settings.

Signature Generation Steps

To verify a webhook request in your application:

  1. Construct the webhook URL exactly as registered, including any query parameters.
  2. Extract the timestamp (t) and signature (v) from the MunoPay-Signature header. Reject requests with outdated timestamps to prevent replay attacks.
  3. Append the timestamp to the webhook URL.
  4. Sort POST variables alphabetically and concatenate each key-value pair to the URL string. Include only the required fields: status, reference_id, transaction_id.
  5. Compute an HMAC-SHA256 hash of the string using your webhook key to generate the signature.
  6. Compare your computed signature with the one in the MunoPay-Signature header. Accept the request only if they match.

Sample PHP implementation to generate verification signature:

    
        /**
         * @param string $webhookKey The webhook's authentication key.
         * @param string $timestamp The signature timestamp.
         * @param array $params The request's POST parameters.
         */

        // Only include these from POST data
        $params = [
            'status' => 'Approved',
            'reference_id' => '52750b30ffbc7de3b36',
            'transaction_id' => 'shafbc7de352b30ffbc73b36'
        ];

        $webhookKey = '<--- Your Webhook Key ---->';
        $signature = $_SERVER['HTTP_MunoPay_SIGNATURE'];

        preg_match('/t=([0-9]+),v=([a-f0-9]{64})/', $signature, $matches);
        if (count($matches) !== 3) {
            echo 'Invalid signature format';
            exit;
        }
        $receivedTimestamp = $matches[1];
        $receivedSignature = $matches[2];

        function generateSignature($webhookKey, $timestamp, $params) {
            $signed_data = $timestamp;
            ksort($params);
            foreach ($params as $key => $value) {
                $signed_data .= strval($key) . strval($value);
            }
            return hash_hmac('sha256', $signed_data, $webhookKey, false);
        }

        $generatedSignature = generateSignature($webhookKey, $receivedTimestamp, $params);
        if (!hash_equals($generatedSignature, $receivedSignature)) {
            echo 'Invalid signature';
            exit;
        }