Webhooks are a crucial component of the Fenan Pay system, allowing real-time notifications of transaction events to be sent directly to your server. This guide will walk you through the process of handling these webhook notifications securely and efficiently.
Webhooks are POST requests sent from Fenan Pay to your server, containing important transaction status updates.
Event Types
Fenan Pay sends different types of webhook events based on the transaction status:
Payment Events
PAYMENT_SUCCESS
PAYMENT_FAILED
PAYMENT_EXPIRED
Withdrawal Events
WITHDRAWAL_SUCCESS
WITHDRAWAL_FAILED
Webhook Payload Structure
The webhook payload contains a transaction event object with the following key components:
{
"webHookEvent": "PAYMENT_SUCCESS",
"signature": "...",
"body": "{\"paymentIntentId\":246283,...}" // JSON string that needs to be parsed
}
Field | Type | Description |
---|
webHookEvent | string | Specifies the type of webhook notification (e.g., PAYMENT_SUCCESS). |
signature | string | A cryptographic signature to verify the payload’s authenticity. |
body | string | A JSON string containing either a PaymentIntent or WithdrawalIntent object, depending on the event type. You need to parse this string to get the actual object. |
Example Webhook Events
Success Transaction
{
"webHookEvent": "PAYMENT_SUCCESS",
"signature": "vDXK9SOK3WEPYvktTFODPj+bjLPPAzcSQRsYpx17+QF04aaqFrqNQQAzlwDItwERkRelH1vlQLaioZxGBDZhAgj3JN5qaTUptWBPhZTORXV8yxNnBhjKJMvKhtVlAynePyTdZDeW8xkNqzmzWZY4bxdMXCbVAzKzgRgL1fFORBH4s78sLhWGOip8SCqvLw70k2/KXs5fT2Q8tWZA+Wqek2WbWzJ4Vc0oBJbkemm69DWuSS1QYXz0Muv6bzjcaSFEQYqjmmZ4n20QfNLRLhHkn26aUCWk8i/fUYR3/zmzLMgEuX9es8YIO9hOIdF5MCZdhzJKqH6DWbJ6f2o7uVcTmQ==",
"body": "{\"paymentIntentId\":246283,\"callbackUrl\":\"https://webhook.site/3fb1bdfb-6689-4a69-90a7-90cdd550c1f6\",\"returnUrl\":\"https://google.com\",\"uniqueId\":\"004-a6da72074f127195242of\",\"paymentLinkUniqueId\":null,\"uuid\":\"96aa5069-7360-49b0-8d1d-56c797252fdd\",\"test\":false,\"commissionPaidByCustomer\":false,\"creationDate\":1745918318670,\"lastUpdateDate\":1745918318670,\"expireDate\":1746004718669,\"totalAmount\":1.00,\"currency\":\"ETB\",\"checkoutBeneficiaries\":[],\"productItems\":[],\"transaction\":{\"id\":245060,\"message\":\"Process service request successfully.\",\"debitAccount\":null,\"phoneNumber\":\"251961186323\",\"trac2\":null,\"test\":false,\"referenceId\":\"96aa5069-7360-49b0-8d1d-56c797252fdd\",\"transactionStatus\":\"SUCCESS\",\"paymentType\":{\"paymentTypeId\":7,\"name\":\"Telebirr USSD\",\"description\":\"Telebirr USSD Payment\",\"type\":\"type\",\"options\":\"zf81i8SD/J901G+wILmy4rR7UnFYconop/aosio3hf1vhGf08DnNtHiPIYGeNhZObWz0Hg2WE5oWWoOrDxKFH3HiV0oiGR+TySt08xW2jCO6LtIYrBnB6mpHDKZiFBgIrB5ds4QZd9OwahO6BkYrXcBnYA2mrhOOoM7POTcrGhfoUK/aL+OhP5X4j6q0GGBT/cfD8fp4rRM89qyv6C/IOuWnfzp0cyTgxmpUhpso4N5nlKPSG3mzZYvXntgCxw0GjM+/6iIpqcLnw3g82y7HON53RBJdQEi1SvJLCGhK/KptQb6drYJ/nLyNgOxBfbq2\",\"currency\":\"ETB\",\"code\":\"TELE_BIRR_USSD\"},\"merchantNet\":0.94,\"adminNet\":0.06,\"totalAmount\":1.00,\"pspTxId\":\"CDT51S5XAD\",\"virtualAccountId\":null,\"virtualCardId\":null,\"creationDate\":1745918318674,\"lastUpdateDate\":1745918329174},\"merchantCustomer\":{\"id\":null,\"name\":null,\"email\":null,\"phone\":null},\"paymentMethodTypes\":[\"TELE_BIRR_USSD\"]}"
}
Withdrawal Success Example
{
"webHookEvent": "WITHDRAWAL_SUCCESS",
"signature": "...",
"body": "{\"withdrawalIntentId\":12345,\"amount\":500.00,\"currency\":\"ETB\",...}"
}
Acknowledging Webhooks
To properly acknowledge receipt of a webhook, your server must respond with:
Fenan Pay will retry the webhook up to 3 times at 2-minute intervals if not properly acknowledged.
Best Practices
- Verify signatures: Always verify the webhook signature before processing the payload.
- Parse the body: Remember that the
body
field is a JSON string that needs to be parsed.
- Process asynchronously: Handle webhook processing in the background to respond quickly.
- Idempotency: Design your webhook handler to be idempotent to safely handle potential duplicate events.
- Logging: Maintain detailed logs of received webhooks for troubleshooting and auditing.
Example Webhook Handler
Here’s a basic example of a webhook handler in Node.js:
const express = require('express');
const app = express();
app.post('/webhook', express.json(), (req, res) => {
const { webHookEvent, signature, body } = req.body;
// Verify the signature
if (verifySignature(body, signature, PUBLIC_KEY)) {
// Parse the body string into a JavaScript object
const payloadData = JSON.parse(body);
// Process the webhook asynchronously
processWebhookAsync(webHookEvent, payloadData);
// Acknowledge receipt
res.status(200).contentType('text/plain').send('SUCCESS');
} else {
res.status(400).send('Invalid signature');
}
});
async function processWebhookAsync(event, data) {
// Implement your webhook processing logic here
console.log('Processing webhook:', event);
// Update your database, trigger notifications, etc.
switch(event) {
case 'PAYMENT_SUCCESS':
// Handle successful payment
break;
case 'PAYMENT_FAILED':
// Handle failed payment
break;
// Handle other event types
}
}
Webhook Log
You can track how your server is handling webhooks in the Fenan Pay dashboard. This is very important for debugging and ensuring that your webhook processing is functioning correctly.
By following these guidelines, you’ll ensure robust and secure handling of Fenan Pay webhooks, keeping your system in sync with the latest transaction statuses.