Handle webhook
All things event
When a payment occurs, Bani sends a webhook event to the webhook URL that you saved on your dashboard.
It is highly recommended that you use webhooks or verify the payment transaction status before delivering value to your customers.
We advise you to verify the response before carrying out any further action.
Please note: if the payout_status value is 'system_closed', kindly wait until the status change to either 'failed' or 'completed' before taking action on your end.
To verify the response, you will have to form the signature and compare your result with the value of 'BANI-HOOK-SIGNATURE' sent to you. The signature is a combination of your merchant_private_key
and request payload.
import hmac
import hashlib
import six
my_hook_signature = hmac.new(six.b(merchant_private_key), msg=str(request_payload).encode('utf-8'), digestmod=hashlib.sha256).hexdigest()
if not hmac.compare_digest(my_hook_signature, bani-hook-signature):
content = {"message":"Invalid signature"}
return JsonResponse(content, status=400)
app.post("/webhook", (req, res) => {
const merchant_private_key = "privatekey";
const headers = req.headers;
const body = req.rawBody;
const sig = Buffer.from(headers["bani-hook-signature"] || "", "utf8");
//Calculate HMAC
const hmac = crypto.createHmac("sha256", merchant_private_key);
const digest = Buffer.from(hmac.update(body).digest("hex"), "utf8");
if (sig.length !== digest.length || !crypto.timingSafeEqual(digest, sig)) {
return false;
} else {
return true;
}
});
$requestBody = 'request_payload';
$secret = 'merchant_private_key';
$signature = hash_hmac('sha256', $requestBody, $secret);
echo $signature;
using System;
using System.Security.Cryptography;
using System.Text;
class Program
{
static void Main()
{
string requestBody = "request_payload";
string merchantPrivateKey = "your_merchant_private_key";
string signature = ComputeHmacSha256Signature(requestBody, merchantPrivateKey);
Console.WriteLine(signature);
}
static string ComputeHmacSha256Signature(string data, string secret)
{
byte[] keyBytes = Encoding.UTF8.GetBytes(secret);
byte[] dataBytes = Encoding.UTF8.GetBytes(data);
using (HMACSHA256 hmac = new HMACSHA256(keyBytes))
{
byte[] hashBytes = hmac.ComputeHash(dataBytes);
return BitConverter.ToString(hashBytes).Replace("-", "").ToLower();
}
}
}
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
public class Main {
public static void main(String[] args) {
String requestBody = "request_payload";
String secret = "merchant_private_key";
String signature = computeHmacSha256(requestBody, secret);
System.out.println(signature);
}
public static String computeHmacSha256(String data, String secret) {
try {
Mac hmacSha256 = Mac.getInstance("HmacSHA256");
SecretKeySpec secretKeySpec = new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), "HmacSHA256");
hmacSha256.init(secretKeySpec);
byte[] hash = hmacSha256.doFinal(data.getBytes(StandardCharsets.UTF_8));
StringBuilder hexString = new StringBuilder();
for (byte b : hash) {
String hex = Integer.toHexString(0xFF & b);
if (hex.length() == 1) {
hexString.append('0');
}
hexString.append(hex);
}
return hexString.toString();
} catch (NoSuchAlgorithmException | InvalidKeyException e) {
e.printStackTrace();
return null;
}
}
}
require 'openssl'
require 'digest'
def compute_hmac_sha256(data, secret)
hmac = OpenSSL::HMAC.digest(OpenSSL::Digest.new('sha256'), secret, data)
hmac_hex = hmac.unpack1('H*')
hmac_hex
end
request_body = 'request_payload'
secret = 'merchant_private_key'
signature = compute_hmac_sha256(request_body, secret)
puts signature
Find sample request payload below.
{
"event": "payin_mobile_money",
"data": {
"pay_ref": "BNPay-j6bva8xcesc2vrhhh4w1vs51t9xj96",
"pay_ext_ref": "",
"holder_first_name": "Star",
"holder_last_name": "Lord",
"custom_data": {
"me": "userr"
},
"pay_amount": "30.88",
"pay_method": "mobile_money",
"holder_phone": "+254713674757",
"holder_phone_carrier": "safke",
"order_details": null,
"holder_currency": "KES",
"holder_country_code": "KE",
"pay_status": "paid",
"holder_account_number": "",
"pub_date": "2022-04-07T11:32:24.084772Z",
"modified_date": "2022-04-07T11:32:33.166011Z",
"holder_bank_name": "",
"merch_currency": "NGN",
"merch_amount": "150.00"
}
}
{
"event": "payin_bank_transfer",
"data": {
"pay_ref": "BNPay-6je71r6y7yd8x0a6pxpp1b2absx56c",
"pay_ext_ref": "",
"holder_first_name": "Mac",
"holder_last_name": "Keita",
"custom_data": {
"me": "userr"
},
"pay_amount": "150.00",
"pay_method": "bank_transfer",
"holder_phone": null,
"holder_phone_carrier": "",
"order_details": null,
"holder_currency": "NGN",
"holder_country_code": "NG",
"pay_status": "paid",
"holder_account_number": "8180000003",
"pub_date": "2022-04-07T08:27:54.481411Z",
"modified_date": "2022-04-07T08:31:16.452737Z",
"holder_bank_name": "Wema Bank",
"merch_currency": "NGN",
"merch_amount": "150.00"
}
}
{
"event": "payin_ewallet",
"data": {
"pay_ref": "BNPay-ck0rhghzhb8wtaqycmk8b4as2bpdma",
"pay_ext_ref": "",
"holder_first_name": "Rodney",
"holder_last_name": "Jackson-Cole",
"custom_data": {
"me": "userr"
},
"pay_amount": "150.00",
"pay_method": "ewallet",
"holder_phone": "",
"holder_phone_carrier": "",
"order_details": null,
"holder_currency": "NGN",
"holder_country_code": "NG",
"pay_status": "paid",
"holder_account_number": "",
"pub_date": "2022-04-06T23:10:13.719380Z",
"modified_date": "2022-04-06T23:12:01.638946Z",
"holder_bank_name": "",
"merch_currency": "NGN",
"merch_amount": "150.00"
}
}
{
"event": "collection_service_status",
"data": {
"pay_method": "Bank Transfer",
"pay_provider_name": "Ocean Bank",
"pay_method_status": "active",
"pay_currency": "NGN",
"pay_keyword":["ocean", "000017"],
"pay_country": [
"NG"
]
}
}
{
"event": "payout",
"data": {
"transaction_note": "Remittance to 0066492583|John Scodo",
"fiat_amount": "10.00",
"coin_amount": "0.000000000000000000",
"transaction_reference": "f6gktkjykamr40mtq13cc76qx",
"pub_date": "2022-10-23T10:59:48.586327Z",
"modified_date": "2022-10-23T10:59:48.588187Z",
"is_done": true,
"payout_details": {
"payout_method": "Bank Transfer",
"receiver_amount": "10.00",
"receiver_phone": "",
"receiver_sort_code": "000005",
"payout_status": "completed",
"payout_ref": "WMPRM_jeebzavhj3",
"payout_ext_ref": "WEMBA-1013",
"payout_receiver_type": "personal",
"receiver_account_name": "John Scodo",
"receiver_account_num": "0000010101",
"receiver_account_type": "",
"receiver_address": "",
"receiver_bank_name": "GRANT BANK",
"receiver_city": "",
"receiver_currency": "NGN",
"receiver_personal_num": "",
"receiver_postcode": "",
"receiver_state": "",
"receiver_country_code": "NG",
"receiver_bank_branch": "",
"receiver_first_name": "",
"receiver_last_name": "",
"pub_date": "2022-10-23T10:59:48.582486Z",
"modified_date": "2022-10-23T11:21:49.899924Z",
"is_beneficiary": false
},
"source_account_name": "Nest Cafe"
}
}
{
"event": "payout_reversal",
"data": {
"transaction_note": "Remittance to 0066492583|John Scodo",
"fiat_amount": "10.00",
"coin_amount": "0.000000000000000000",
"transaction_reference": "f6gktkjykamr40mtq13cc76qx",
"pub_date": "2022-10-23T10:59:48.586327Z",
"modified_date": "2022-10-23T10:59:48.588187Z",
"is_done": true,
"payout_details": {
"payout_method": "Bank Transfer",
"receiver_amount": "10.00",
"receiver_phone": "",
"receiver_sort_code": "000005",
"payout_status": "failed",
"payout_ref": "WMPRM_jeebzavhj3",
"payout_ext_ref": "WEMBA-1013",
"payout_receiver_type": "personal",
"receiver_account_name": "John Scodo",
"receiver_account_num": "0000010101",
"receiver_account_type": "",
"receiver_address": "",
"receiver_bank_name": "GRANT BANK",
"receiver_city": "",
"receiver_currency": "NGN",
"receiver_personal_num": "",
"receiver_postcode": "",
"receiver_state": "",
"receiver_country_code": "NG",
"receiver_bank_branch": "",
"receiver_first_name": "",
"receiver_last_name": "",
"pub_date": "2022-10-23T10:59:48.582486Z",
"modified_date": "2022-10-23T11:21:49.899924Z",
"is_beneficiary": false
},
"source_account_name": "Nest Cafe"
}
}
{
"event": "vas_completed",
"data": {
"amount": "3200.00",
"biller_customer_item": "12345678910",
"customer_biller_code": "91 Abodunrin Street 60 313 IfeomaVille",
"customer_biller_name": "Wale Emeka Sylvester",
"vas_type": "Bills Payment",
"customer_phone_number": "+2348053022958",
"currency": "NGN",
"transaction_ext_ref": "",
"customer_phone_network": "",
"transaction_status": "completed",
"main_category": "ELECTRICITY",
"sub_category": "IKEDC",
"biller_extra_info": "60114651373352292125|Units Purchased: 5.1",
"vas_item_name": "",
"transaction_ref": "BV-xaz8h4c8k7bjwmw",
"pub_date": "2023-06-11T20:44:51.648453Z"
}
}
{
"event": "vas_failed",
"data": {
"amount": "100.00",
"biller_customer_item": "",
"customer_biller_code": "",
"customer_biller_name": "",
"vas_type": "Mobile Data",
"customer_phone_number": "+2348053022958",
"currency": "NGN",
"country_code": "NG",
"transaction_ext_ref": "",
"customer_phone_network": "glo",
"transaction_status": "failed",
"main_category": "mobile_data",
"sub_category": "glo",
"biller_extra_info": "",
"vas_item_name": "GLO-150MB-3",
"transaction_ref": "BV-am75yb6zf82z0k8",
"pub_date": "2023-06-11T21:11:26.399568Z"
}
}
Last updated