Webhook
Webhook Authenticity Verification
Method to decode SHA-256 Hashing
public PaymentNotificationModel DecryptPaymentNotification(string encryptedData, string integrationKey, string merchantCode)
{
try {
string decryptedData = DecryptString(encryptedData, integrationKey, merchantCode);
return JsonConvert.DeserializeObject<PaymentNotificationModel>(decryptedData);
}
catch (Exception ex)
{
Console.WriteLine($"Error in DecryptPaymentNotification: {ex.Message}");
throw;
}
}
public string DecryptString(string cipherText, string integrationKey, string merchantCode)
{
try
{
byte[] cipherBytes = Convert.FromBase64String(cipherText);
using (Aes aesAlg = Aes.Create())
{
aesAlg.Key = ConvertToBase64Bytes(integrationKey, 32);
aesAlg.IV = ConvertToBase64Bytes(merchantCode, 16);
aesAlg.Mode = CipherMode.CBC;
aesAlg.Padding = PaddingMode.PKCS7;
ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
using (MemoryStream msDecrypt = new MemoryStream(cipherBytes))
{
using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
{
using (StreamReader srDecrypt = new StreamReader(csDecrypt))
{
return srDecrypt.ReadToEnd();
}
}
}
}
}
catch (Exception ex)
{
Console.WriteLine($"Error in DecryptString: {ex.Message}");
throw;
}
}
private static byte[] ConvertToBase64Bytes(string input, int requiredLength)
{
try
{
byte[] bytes = Convert.FromBase64String(input);
return AdjustLength(bytes, requiredLength);
}
catch (FormatException)
{
byte[] bytes = Encoding.UTF8.GetBytes(input);
return AdjustLength(bytes, requiredLength);
}
}
private static byte[] AdjustLength(byte[] inputBytes, int requiredLength)
{
if (inputBytes.Length == requiredLength)
{
return inputBytes;
}
else if (inputBytes.Length > requiredLength)
{
return inputBytes.Take(requiredLength).ToArray();
}
else
{
byte[] paddedBytes = new byte[requiredLength];
Array.Copy(inputBytes, paddedBytes, inputBytes.Length);
return paddedBytes;
}
}
//Notification Class
public class PaymentNotificationModel
{
public string Hash { get; set; } //A URL Encoded String containing the encryption hash of the remaining properties
public TransactionData Transaction { get; set; }
public CustomerData Customer { get; set; }
public OrderData Order { get; set; }
public string Message { get; set; }
public string Code { get; set; }
}
public class TransactionData
{
public string MerchantCode { get; set; }
public string PaymentReference { get; set; }
public string MerchantReference { get; set; }
public string SessionId { get; set; }
public DateTimeOffset Date { get; set; }
}
public class CustomerData
{
public CustomerAccountData Account { get; set; }
public CustomerCardData Card { get; set; }
public CustomerUssdData Ussd { get; set; }
}
public class OrderData
{
public decimal Amount { get; set; }
public string Currency { get; set; }
public string Description { get; set; }
}
public class CustomerAccountData
{
public string Name { get; set; }
public string VirtualAccountNumber { get; set; }
public string Bank { get; set; }
public string SenderBankCode { get; set; }
public string SenderBankName { get; set; }
public string SenderAccountNumber { get; set; }
public string SenderName { get; set; }
}
public class CustomerCardData
{
public string Name { get; set; }
public string Processor { get; set; }
public string SenderCardNumber { get; set; }
public string SenderName { get; set; }
}
public class CustomerUssdData
{
public string Name { get; set; }
public string UssdCode { get; set; }
public string SenderPhoneNumber { get; set; }
}Sample Webhook for Bank Transfer Transactions
Sample Webhook for Card Option
Sample Webhook for USSD Transactions
Expected Webhook Response Format
Last updated