Webhook notifications
UNIPaaS will notify your platform of important events using webhook notifications. There are notification endpoints available for each UNIPaaS products, such as onboarding, accepting payments and paying out.
Using webhook notifications with UNIPaaS
1. Identify the webhook notifications needed to run your application
Each UNIPaaS product fires different webhook notifications to your platform. For example, if you are using the UNIPaaS vendor onboarding product, you should listen to onboarding/update
webhooks, which will update your application about every vendor's onboarding status change. Use the UNIPaaS product webhook guide to subscribe to the webhook notifications you need.
2. Subscribe to webhook notifications
Use our webhooks API endpoint to subscribe to the webhook notifications you need.
3. Capture and test webhook notifications on your server
Use the UNIPaaS sandbox environment to simulate events that will trigger webhook notifications. For example, take a payment as a vendor, or go through a vendor onboarding flow, while listening to the respective webhook notifications.
4. Return 200 response code
UNIPaaS will re-send any webhook notification unless a 200 response status code is received within 10 seconds. There will be 15 webhook notification retries sent until the webhook will be invalidated. UNIPaaS will send an email notification after each 5 failed retries.
5. Verifying webhooks
To verify that the request came from UNIPaaS, compute the HMAC digest according to the following algorithm and compare it to the value in the X-Hmac-SHA256
header. If they match, then you can be sure that the webhook was sent from UNIPaaS.
Webhooks created through the API are verified by calculating a digital signature. Each webhook request includes a base64-encoded X-Hmac-SHA256
header, which is generated using the <PLATFORM_SECRET_KEY>
along with the data sent in the request.
const express = require('express')
const bodyParser = require('body-parser');
const { createHmac } = require('crypto');
const app = express();
const SECRET = '<PLATFORM_SECRET_KEY>';
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use(bodyParser.raw());
app.post('/webhook', function (req, res) {
const {headers, body} = req;
const signedHeader = headers["x-hmac-sha256"];
const hash = createHmac('sha256', SECRET)
.update(JSON.stringify(body))
.digest('hex');
const buff = new Buffer(hash);
const calculated = buff.toString('base64');
if (calculated === signedHeader) {
console.log('hook verified successfully')
}
else {
console.log('failed to verify hook!')
}
res.send('Hello World')
})
app.listen(8080)
using System;
using System.Text;
using System.Security.Cryptography;
public class HashC
{
public static string CreateHash(string data ,string sharedSecretKey)
{
if (String.IsNullOrEmpty(data))
{
return String.Empty;
}
var keyBytes = Encoding.UTF8.GetBytes(sharedSecretKey);
var dataBytes = Encoding.UTF8.GetBytes(data);
var hmac = new HMACSHA256(keyBytes);
var hmacBytes = hmac.ComputeHash(dataBytes);
StringBuilder hash = new StringBuilder(hmacBytes.Length * 2);
for (int i = 0; i < hmacBytes.Length; i++) {
hash.Append(hmacBytes[i].ToString("x2"));
}
var hex = hash.ToString();
//retun as base64 string.
return System.Convert.ToBase64String(Encoding.UTF8.GetBytes(hex));
}
//createdHash and receivedHash need to be base64
public static void compreHash(string createdHash , string signedHeader)
{
bool isHashequal = createdHash.Equals(signedHeader);
if (isHashequal == true)
{
Console.WriteLine("hook verified successfully");
}
else{
Console.WriteLine("failed to verify hook");
}
}
public static void Main()
{
string receivedHash = "NWM3ZDBiYzRiNzdjYTIwNDZlNzZmMjA5MTkzNTZlYjgzZGY2NmVhYTY5MjI1MzI1NzAxZGQ5NjM4Zjc0Nzc1ZQ==";
string secret = "GO6DX3FIvIu5ucXwk9rmMQ==";
string deserializeObject = "{\"vendorId\":\"6227285317bdf46531435a71\",\"vendorName\":\"Abbey Bickmarsh Caddington\",\"acceptPayments\":false,\"receivePayout\":false,\"status\":\"STARTED\",\"onboardingStatus\":\"STARTED\",\"type\":\"individual\",\"completionRate\":75,\"pendingFields\":[{\"alias\":\"business.accountHolderName\",\"status\":\"PENDING\",\"type\":\"TEXT_FIELD\",\"label\":\"Bank Account holder name\",\"required\":true,\"errors\":null,\"value\":null},{\"alias\":\"business.bankAccount\",\"status\":\"PENDING\",\"type\":\"TEXT_FIELD\",\"label\":\"Your Bank Account Number\",\"required\":true,\"errors\":null,\"value\":null},{\"alias\":\"business.sortCode\",\"status\":\"PENDING\",\"type\":\"TEXT_FIELD\",\"label\":\"Your Sort-code\",\"required\":true,\"errors\":null,\"value\":null}]}";
string computedHash = HashC.CreateHash(deserializeObject , secret);
Console.WriteLine(computedHash);
//example: NWM3ZDBiYzRiNzdjYTIwNDZlNzZmMjA5MTkzNTZlYjgzZGY2NmVhYTY5MjI1MzI1NzAxZGQ5NjM4Zjc0Nzc1ZQ==
HashC.compreHash(computedHash , "12345");
//failed to verify hook
HashC.compreHash(computedHash , computedHash);
//hook verified successfully
}
}
Updated over 1 year ago