I inherited a project recently written in laravel 5.8 to be precise, at this time, laravel has moved on to version 7, but my main issue here is how to setup flutterwave webhook (A very efficient Nigerian payment gateway) to work in this project, the previous developer had started work on it. After many attempts and reaching out to the rave team.
I’ll be sharing a step-by-step process of how to do that successfully, from the A-Z. Before now a laravel package had been created for this purpose, its called kingflamez/laravelrave or check the official docs. Follow the steps to get the rave package into your laravel project.
First, create a controller in laravel and call it RaveController with this command
php artisan make:controller RaveController
If you correctly setup your flutterwave composer package, you should have the file rave.php in your config folder in laravel i.e. config/rave.php. Also your environment variables ( .env file) need to be setup correctly too as this
RAVE_PUBLIC_KEY=FLWPUBK_TEST-xxxxxxx
RAVE_SECRET_KEY=FLWSECK_TEST-XXXXXXX
RAVE_TITLE="Name of your Company"
RAVE_ENVIRONMENT="test/live --(choose anyone)"
RAVE_LOGO="link to the rave logo"
RAVE_PREFIX="rave"
RAVE_SECRET_HASH='your secret hash string'
Once all these are setup properly, let’s proceed to the rave controller that you have created. Assume that you have a TransactionHistory model and thus a table in your database names transactionhistory.
First, rave looks for the initialize method, therefore, you should generate your transaction reference in this method before sending to the webhook. Generate a prefix, this is provided by the rave package, and save all the created objects to the database like the code below
<?php namespace App\Http\Controllers; use App\TransactionHistory; use App\User; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; use Rave; class RaveController extends Controller { /** * Initialize Rave payment process * @return void */ public function initialize() { request()->validate([ 'phone' => 'sometimes|required|min:11|starts_with:0', 'category' => 'sometimes|required|string', 'product_id' => 'sometimes|required|integer', 'amount' => 'sometimes|required|integer', ], ['phone.starts_with' => ' :attribute number must begin with 0. e.g 070123456789', 'amount.integer' => ' :attribute number must be a number']); $prefix = config()->get('rave.prefix'); $transactionPrefix = $prefix . '_'; request()->request->add(['user_id' => auth()->user()->id]); request()->request->add(['ref' => uniqid($transactionPrefix)]); TransactionHistory::create(request()->all()); Rave::initialize(route('callback')); } /** * Obtain Rave callback information * @return void */ public function callback() { $res_json = json_decode(request()->request->get('resp')); $txref = $res_json->data->data->txRef; $data = Rave::verifyTransaction($txref); $chargeResponsecode = $data->data->chargecode; $transaction = TransactionHistory::where('ref', $txref)->first(); if (($chargeResponsecode == "00" || $chargeResponsecode == "0")) { $user = User::whereId($transaction->user_id)->first(); $referred_by = ''; $transaction->update([ 'status' => 'paid', ]); return redirect()->route('home')->withSuccess('Wallet top-up successful.'); } else { return redirect()->route('home')->withErrors(['Something went wrong.']); } } }
You can write the webhook function just before the callback function. The web-hook automatically runs as a background service, you don’t get to see how it happens except you use a logger which is also provided by laravel.
Also, for the webhook to work, your RAVE_SECRET_HASH=’your secret hash string’ in your .env file must be the same as on your rave dashboard — (go to settings on your dashboard, and click the webhooks tab.
Your url should look like this; https://yourdomainname/rave/receive
public function webhook(){
$data = Rave::receiveWebhook();
$txref = $data['txRef'];
if ($data['status'] == 'successful') {
$transaction = TransactionHistory::where('ref', $txref)- >first();
$user = User::whereId($transaction->user_id)->first();
//give your user value here
$transaction->update([
'flwref' => $data['flwRef'],
'type' => $data['event.type'],
]);
}
}
Bypassing csrf
Also, we need to update the VerifyCsrfToken.php file to exempt the POST call of the webhook from using the CSRF which is the custom behaviour of all POST method calls in laravel. Head on to app/Http/VerifyCsrfToken.php and add the following code
protected $except = [ 'rave/callback', 'rave/receive', ];
Routes
Finally, we need to create a route of this to work. In the routes/web.php file , add this
Route::post(‘/pay’, ‘RaveController@initialize’)->name(‘pay’); Route::get(‘/rave/callback’, ‘RaveController@callback’)->name(‘callback’);
And that’s all….., you’re done.
Let’s talk about the errors you might encounter.
I had an issue first with the package, because my project is version 5.8, all I needed to do was:
php artisan vendor:publish --provider="KingFlamez\Rave\RaveServiceProvider"
but it didn’t work as expected. (well, after solving this, it will make you a senior developer)When this happens to you, try to clear cache, OR delete the vendor folder and re-install OR use these commands
php artisan cache:clear php artisan config:clear
These two commands are very important. Lastly check the function called receiveWebhook
in the Rave.php file inside the kingflamez/laravelrave/src located in your vendor folder to see if it is the same with the one the official docs on event-webhook has. GOODLUCK
If you need a developer to help you integrate flutterwave to receive payment on your site, you can reach out to Pianistprogrammer on whatsapp +2347030507502 or jeremiahabimbola0@gmail.com