Webhook Security
Integrators can utilise a client key to verify a webhook's authenticity. The client key is used to digitally sign the payloads, and the signature is used to confirm the webhook's authenticity, further protecting your platform from malicious activities.
Register a client key
To receive secure requests, register a client key via:
- add
clientKey
parameter in the request body.
{
"url": "https://companyName.net/callback",
"eventTypes": [
"invoice_created",
"customer_create",
"subscription_activate",
"subscription_payment_reactivate",
"payment_method_invalid",
"payment_method_replaced",
"invoice_paid",
"invoice_past_due",
"subscription_create",
"subscription_cancel",
"invoice_batch_created",
"invoice_batch_processing",
"invoice_batch_success",
"invoice_batch_invoice_failed"
],
"clientKey": "{{clientKey}}"
}
- set
updateSecurity
to true in request body. - add
clientKey
parameter in request body.
{
"webhookId": "2c4e8865-1e9f-4dcb-88d4-c36f3cc9ea83",
"clientKey": "{{clientKey}}",
"updateSecurity": true
}
Verifying webhook authenticity
Ezypay uses HMAC SHA-1 to compute a signature, using the client key and request payload as arguments. The signature is then included in the X-Ezypay-Signature
header.
To verify the signature:
- Retrieve
X-Ezypay-Signature
from headers. - Obtain the raw payload body from the HTTP request.
- Compute the HMAC SHA-1 hash string using the client key and raw payload.
- Compare this string to the
X-Ezypay-Signature
.
Code examples on computing HMAC SHA-1 hash from some common languages are as follows.
import org.apache.commons.codec.digest.HmacUtils;
public class Example {
public String computeSignature(String clientKey, String payload) {
return HmacUtils.hmacSha1Hex(clientKey, payload);
}
}
using System.Security.Cryptography;
namespace Example {
public class Signature {
public string computeSignature(string clientKey, string payload) {
byte[] clientKeyBytes = System.Text.Encoding.UTF8.GetBytes(clientKey);
byte[] payloadBytes = System.Text.Encoding.UTF8.GetBytes(payload);
HMACSHA1 hmac = new HMACSHA1(clientKeyBytes);
byte[] hashValue = hmac.ComputeHash(payloadBytes);
return BitConverter.ToString(hashValue).ToLower().Replace("-", "");
}
}
}
function computeSignature(clientKey, payload) {
var crypto = require('crypto');
var hmac = crypto.createHmac('sha1', clientKey).update(payload);
return hmac.digest('hex');
}
import hashlib
import hmac
def computeSignature(clientKey, payload):
utf8 = "utf-8"
clientKeyBytes = bytes(clientKey).encode(utf8)
payloadBytes = bytes(payload).encode(utf8)
computedHmac = hmac.new(clientKeyBytes, payloadBytes, digestmod=hashlib.sha1)
return computedHmac.digest().encode("hex")
<?php
function computeSignature($clientKey, $payload) {
return hash_hmac('sha1', $payload, $clientKey, false);
}
?>
require 'openssl'
def computeSignature(clientKey, payload)
digest = OpenSSL::Digest.new('sha1')
return OpenSSL::HMAC.hexdigest(digest, clientKey, payload)
end
use Digest::HMAC_SHA1;
sub compute_signature {
my ($clientKey, $payload) = @_;
my $hmac = Digest::HMAC_SHA1->new($clientKey);
$hmac->add($payload);
return $hmac->hexdigest;
}
The payload is the raw body of the HTTP request, meaning it is the JSON data in its raw form. Do not parse, re-encode, or manipulate it in any way; use it as is.
Testing signature verification
You can test the signature verification process using the following reference example:
- client key =
key
- payload =
{"requestId":"4cb74646-4d30-4d6a-ac71-7a26a4a623d3","merchantId":"aad25d2b-85f2-40cf-8b6d-44b5439a220f","eventType":"INVOICE_BATCH_CREATED","createdOn":"2024-07-11T06:42:28.296","data":{"id":"26055389-927b-41b9-bc13-77a50887db5c","batchReference":"tyj56","createdOn":"2024-07-11T06:42:28.135","status":"SUBMITTED"}}
The hexadecimal HMAC SHA-1 produces:
- Expected output =
6354ecd501ca4c87da2b42872949c7fa02fefd89
Updated about 2 months ago