Bulk transfers using Flutterwave’s Rave PHP SDK

This project elaborates how to perform bulk transfers on the rave dashboard. You can find the website here and also download the starter files for this project here.

Bulk transfer using rave

The requirements needed are -:

  • OOP PHP Knowledge
  • Your Rave account needs to be funded for the application to complete a transfer. You can read about it here.
  • A Pusher Account
  • A webhook test website. To test the webhook that will be returned from rave

Goal

  • Learn how to use rave’s PHP SDK in your PHP project
  • Learn how to handle webhooks in your PHP project
  • Learn how to use Pusher to perform real-time app notifications
  • Learn how to transfer money using Rave.

So, first of all, we download the official PHP SDK from the Flutterwave Github repo. This repo contains a PHP wrapper for the Flutterwave APIs which we would use in this project.

How to download the repo — we can download the project in one of 3 ways as follows:

  1. By a git clone
git clone https://github.com/Flutterwave/Flutterwave-Rave-PHP-SDK

2. By using composer

composer require flutterwave-php-sdk

3. By manually downloading the git project

PHP-SDK Github repository

When our download is complete. Add the Flutterwave PHP SDK to our starter files like so

Project folder showing the project structure

Rename the .env.example file to .env . Add your public key, secret key, environment and secret_hash (we will use the secret hash to set up a webhook later), like so

PUBLIC_KEY = "****YOUR**PUBLIC**KEY****"
SECRET_KEY = "****YOUR**SECRET**KEY****"
ENV = "staging or live"
SECRET_HASH = "****YOUR**SECRET_HASH**FOR****WEBHOOKS"

Next, we open the class.api.php file which is the file where we would be making our API calls and include the codes to pull the API files from our PHP SDK, like so

require_once('Flutterwave/api/Transfer.php'); 
use Flutterwave\Transfer;
Project folder showing the class.api.php

For this project, we will need only the transfer API file to make transfers on our application.

Setting up the bulk transfer

When we open our application, it pulls the available balance and ledger balance from the rave account that matches with the public key and secret key added in the (.env) file.

Our Application Dashboard

Below is an image showing how we initiate a bulk transfer. First of all, we create a group which can be a team in an organization

Creating a group/team for bulk transfers

Then we add the team members to that group by including the names, salary, bank account and so on.

Adding members to a group/team

A bulk transfer involves sending money to multiple individuals. We have set up an empty function (bulkTransfer ) in the class.api.phpfile which will be used to make calls to the flutterwave transfer API. To initiate a bulk transfer we add the following code to the empty function which calls the (bulkTransfer) function on the rave PHP SDK.

//arrange bulk_data in array
foreach ($members as $member) {
$bulk_data[] = array (
'Bank' => $member['staffbank'],
'Account Number' => $member['staffacctno'],
'Amount' => $member['amount'],
'Narration' => 'Something goes here',
'currency' => 'NGN',
'reference' => 'rave-'.time()
);
}
$data["seckey"] = $_ENV['SECRET_KEY'];
$data["title"] = "My staff salary";
$data["bulk_data"] = $bulk_data;
$bulk = new Transfer();
$result = $bulk->bulkTransfer($data);
$trx = json_decode($result, true);
return $trx;

We pass the ($data )variable into the (bulkTransfer ) function. The variable contains an array which the first index is the secret_key, the second index is the title of the transfer and the third index is an array ( $bulk_data ) containing the values of the members we want to transfer money to. The ( foreach) loop above loops through the ($member) variable which is an array of members pulled from our database and adds each member along with the data associated with that member (such as the bank name, account number, amount) to an index in $bulk_data

project folder showing empty bulk function

Results from a single transfer

We have set up pusher to send alerts across our application and will take advantage of this feature in this section. You can sign up for your own pusher account here and set it up. We will log all our responses to the console using pusher but pusher is capable of so much more.

Setting up Pusher

The API returns the following results

{
"status": "success",
"message": "BULK-TRANSFER-CREATED",
"data": {
"id": 21,
"uuid": 21,
"date_created": "2018-05-17T08:39:54.000Z",
"approver": "N/A"
}
}

We have logged the results from the API in a console. This is made possible by using pusher which we have already set up.

The final response from the rave API

The result returned doesn’t mean that the process is complete, there are further steps to complete the process which involve setting up a webhook and a callback function.

Implementing a webhook for the single transfer

The concept of a WebHook is simple. A WebHook is an HTTP callback: an HTTP POST that occurs when something happens; a simple event-notification via HTTP POST.

A web application implementing WebHooks will POST a message to a URL when certain things happen. To implement a webhook to receive notifications on the progress on our transfer, we need to set up our rave account for webhooks. Login to your rave account and navigate to the webhook section on your settings page.

Setting up a webhook on rave dashboard

Add your secret hash and URL (a link to the callback script that will process the responses from your rave account). We will now set up our callback function.

We have added a script (webhook.php). This is where we will process the responses from our rave dashboard. The URL to a hosted version of this file will be the URL of our webhook. You can also use this website to test your webhooks by copying and pasting the URL in your rave dashboard.

Add the following function to the webhook file like so

<?php 
require __DIR__.'/vendor/autoload.php'; // Uncomment this autoloader if you need it
$dotenv = new Dotenv\Dotenv(__DIR__.'/include/classes/Flutterwave');
$dotenv->load();
$options = array(
'cluster' => 'eu',
'encrypted' => true
);

$pusher = new Pusher\Pusher(
'084259e4e356fb9a0622',
'bfb407e2dc876b7fe5a3',
'636291',
$options
);

// Retrieve the request's body
$body = @file_get_contents("php://input");
// retrieve the signature sent in the reques header's.
$signature = (isset($_SERVER['HTTP_VERIF_HASH']) ? $_SERVER['HTTP_VERIF_HASH'] : '');
/* It is a good idea to log all events received. Add code *
* here to log the signature and body to db or file */
if (!$signature) {
// only a post with rave signature header gets our attention
exit();
}
// Store the same signature on your server as an env variable and check against what was sent in the headers
$local_signature = $_ENV['SECRET_HASH'];
// confirm the event's signature
if( $signature !== $local_signature ){
// silently forget this ever happened
exit();
}
http_response_code(200); // PHP 5.4 or greater
// parse event (which is json string) as object
// Give value to your customer but don't give any output
// Remember that this is a call from rave's servers and
// Your customer is not seeing the response here at all
$response = json_decode($body);
if (isset($response)) {
$data['message'] = $response;
$pusher->trigger('my-channel', 'my-event', $data);

echo '<script src="https://js.pusher.com/4.3/pusher.min.js"></script>';
echo'<script>
Pusher.logToConsole = true;
var pusher = new Pusher("084259e4e356fb9a0622", {
cluster: "eu",
forceTLS: true
});
var channel = pusher.subscribe("my-channel");
channel.bind("my-event", function(data) {
console.log(data);
});
});
</script>';


}else{
$data['message'] = $response;
$pusher->trigger('my-channel', 'my-event',$data);
echo '<script src="https://js.pusher.com/4.3/pusher.min.js"></script>';
echo'<script>
Pusher.logToConsole = true;
var pusher = new Pusher("084259e4e356fb9a0622", {
cluster: "eu",
forceTLS: true
});
var channel = pusher.subscribe("my-channel");
channel.bind("my-event", function(data) {
console.log(data);
});
});
</script>';

}
exit();
?>

The webhook returns the following response which can be logged to the console

{
"event.type":"Transfer",
"transfer":{
"id":3168,
"account_number":"0690000031",
"bank_code":"044",
"fullname":"Forrest Green",
"date_created":"2018-11-02T16:31:45.000Z",
"currency":"NGN",
"debit_currency":null,
"amount":4000,
"fee":45,
"status":"FAILED",
"reference":null,
"meta":null,
"narration":"Something goes here",
"approver":null,
"complete_message":"DISBURSE FAILED: Insufficient funds",
"requires_approval":0,
"is_approved":1,
"bank_name":"ACCESS BANK NIGERIA"}
}

This is the response from the webhook logged in the console

The final response from the rave API

From the result, we can see that our transfer is unsuccessful because we do not have enough funds

Thanks for reading