Webhooks
Learn how to listen to events whenever certain actions occur on your integration.

What are webhooks?

Whenever certain transaction actions occur on your Vesicash integration, we trigger events which your application can listen to. This is where webhooks come in. A webhook is a URL on your server where we send payloads for such events. For example, if you implement webhooks, once a payment for a transaction is successful, we will immediately notify your server with a payment.success event. Here is a list of events we can send to your webhook URL.
We recommend that you use webhook to provide value to your customers over using a callback. Callbacks can fail if the network connection on a customer's device fails or is weak or if the device goes off after a transaction and several other situations that are outside both our and your control.
You can specify your webhook URL on your live dashboard if you've gone live or on your sandbox dashboard if you're still testing where we would send POST requests to whenever an event occurs.
Here are some things to note when setting up a webhook URL:
  1. 1.
    If using .htaccess, remember to add the trailing / to the url you set.
  2. 2.
    Do a test post to your URL and ensure the script gets the post body.
  3. 3.
    Ensure your webhook URL is publicly available (localhost URLs cannot receive events)

Receiving an event

All you have to do to receive the event is to create an unauthenticated POST route on your application. The event object is sent as JSON in the request body.
NodeJS
PHP
1
// Using Express
2
app.post("/my/webhook/url", function(req, res) {
3
4
// Retrieve the request's body
5
var event = req.body;
6
7
// Do something with event
8
res.send(200);
9
10
});
Copied!
1
<?php
2
3
// Retrieve the request's body and parse it as JSON
4
$input = @file_get_contents("php://input");
5
$event = json_decode($input);
6
7
// Do something with $event
8
http_response_code(200); // PHP 5.4 or greater
9
?>
Copied!

Verifying events

It is important to verify that events originate from Vesicash to avoid delivering value based on a counterfeit event.
You can do any or both of the below to verify events from Paystack:
  1. 1.
    Validate the Signature - Valid events are raised with a header X-Vesicash-Webhook-Secret which is essentially a HMAC SHA256 signature of the event payload signed using your secret key.
  2. 2.
    Watch the IPs - We only call your webhooks from these IPs: 52.204.32.79, 3.85.176.242
You can whitelist these IPs. Any webhook from outside of these can safely be considered counterfeit.
NodeJS
PHP
1
var crypto = require('crypto');
2
var business_id = '<BUSINESS ID>';
3
4
var secret = process.env.SECRET_KEY . ':' . business_id;
5
6
// Using Express
7
app.post("/my/webhook/url", function(req, res) {
8
9
//validate event
10
var hash = crypto.createHmac('sha256', secret).update(JSON.stringify(req.body)).digest('hex');
11
if (hash == req.headers['x-vesicash-webhook-secret']) {
12
// Retrieve the request's body
13
var event = req.body;
14
// Do something with event
15
}
16
res.send(200);
17
18
});
19
Copied!
1
<?php
2
3
function logWebhook($log) {
4
file_put_contents("post.log", $log, FILE_APPEND);
5
}
6
7
$body = json_decode(file_get_contents("php://input"), true);
8
9
// retrieve the signature sent in the request header's.
10
$signature = (isset($_SERVER['HTTP_X_VESICASH_WEBHOOK_SECRET']) ? $_SERVER['HTTP_X_VESICASH_WEBHOOK_SECRET'] : false);
11
12
/* It is a good idea to log all events received. Add code *
13
* here to log the signature and body to db or file */
14
15
if (!$signature) {
16
// only a post with rave signature header gets our attention
17
logWebhook("Signature Header is missing");
18
exit();
19
}
20
21
$private_key = '<YOUR PRIVATE KEY>';
22
$business_id = '<YOUR BUSINESS ID>';
23
24
$headerSignature = "$private_key:$business_id";
25
26
// Store the same signature on your server as an env variable and check against what was sent in the headers
27
$local_signature = hash_hmac('sha256', $headerSignature, $private_key);
28
29
// confirm the event's signature
30
if( $signature !== $local_signature ) {
31
// silently forget this ever happened
32
logWebhook("Signature Header Does Not Match");
33
exit();
34
}
35
36
logWebhook("Authenticated");
37
38
// PHP 5.4 or greater
39
// parse event (which is json string) as object
40
// Give value to your customer but don't give any output
41
// Remember that this is a call from vesicash's servers and
42
// Your customer is not seeing the response here at all
43
44
$response = json_decode($body);
45
46
http_response_code(200);
Copied!

Responding to an event

You should respond to an event with a 200 OK. We consider this an acknowledgement by your application. If your application responds with any status outside of the 2xx range, we will consider it unacknowledged and thus, continue to send it every hour for 72 hours. You don't need to send a request body or some other parameter as it would be discarded - we only pay attention to the status code.
If your application is likely to start a long running task in response to the event, Vesicash may timeout waiting for the response and would ultimately consider the event unacknowledged and queue to be raised later. You can mitigate duplicity by having your application respond immediately with a 200 before it goes on to perform the rest of the task.

Supported events

Payment Successful
Payment Failed
Disbursement Successful
Disbursement Failed
1
{
2
"event":"payment.success",
3
"data":{
4
"transaction_title":"Test Transaction Milestone One",
5
"transaction_id":"r1nwNapV09Stk4fhdUB7",
6
"payment_status":"success"
7
}
8
}
Copied!
1
{
2
"event":"payment.failed",
3
"data":{
4
"transaction_title":"Test Transaction Milestone One",
5
"transaction_id":"r1nwNapV09Stk4fhdUB7",
6
"payment_status":"failed"
7
}
8
}
Copied!
1
{
2
"event":"disbursement.success",
3
"data":{
4
"disbursement_id":3436452439,
5
"reference":"vc6430461564",
6
"status":"success"
7
}
8
}
Copied!
1
{
2
"event":"disbursement.failed",
3
"data":{
4
"disbursement_id":3436452439,
5
"reference":"vc6430461564",
6
"status":"failed"
7
}
8
}
Copied!

Types of events

Here are the events we currently raise. We would add more to this list as we hook into more actions in the future.
Event
Description
payment.success
A transaction was paid for successfully
payment.failed
The payment for a transaction failed.
disbursement.success
Funds disbursement was sent successfully
disbursement.failed
Funds disbursement failed or was unsuccessful.
Last modified 6mo ago