This guide explains how to integrate Flutterwave payment gateway with the Laravel Payments package.
Flutterwave is a leading African payment gateway that supports multiple payment methods including:
composer require abraham-flutterwave/laravel-payment
php artisan vendor:publish --tag=flutterwave-config
Add your Flutterwave credentials to your .env file:
FLUTTERWAVE_PUBLIC_KEY=your_public_key_here
FLUTTERWAVE_SECRET_KEY=your_secret_key_here
FLUTTERWAVE_SECRET_HASH=your_webhook_secret_hash
FLUTTERWAVE_ENCRYPTION_KEY=your_encryption_key_here
FLUTTERWAVE_LOG_CHANNEL=stack
You can obtain these keys from your Flutterwave dashboard.
For development/testing:
FLUTTERWAVE_ENV=staging
For production:
FLUTTERWAVE_ENV=production
use Mdiqbal\LaravelPayments\Facades\Payment;
$paymentRequest = [
'amount' => 100.00,
'currency' => 'NGN',
'email' => 'customer@example.com',
'transaction_id' => 'TXN' . time(),
'redirect_url' => 'https://yoursite.com/payment/callback',
'payment_options' => 'card,banktransfer,ussd',
'customer' => [
'name' => 'John Doe',
'phone' => '+2341234567890',
'address' => '123 Main St, Lagos, Nigeria'
],
'customizations' => [
'title' => 'My Company',
'description' => 'Payment for products',
'logo' => 'https://yoursite.com/logo.png'
]
];
$payment = Payment::gateway('flutterwave')->pay($paymentRequest);
$verification = Payment::gateway('flutterwave')->verify($transactionId);
if ($verification['success']) {
$status = $verification['data']['status'];
$amount = $verification['data']['amount'];
if ($status === 'successful') {
// Payment was successful
}
}
$refundData = [
'transaction_id' => 'FLW_TRANSACTION_ID',
'amount' => 50.00
];
$refund = Payment::gateway('flutterwave')->refund($refundData);
$customerData = [
'email' => 'customer@example.com',
'name' => 'John Doe',
'phone' => '+2341234567890',
'address' => '123 Main St, Lagos, Nigeria'
];
$customer = Payment::gateway('flutterwave')->createCustomer($customerData);
$linkData = [
'amount' => 100.00,
'currency' => 'NGN',
'description' => 'Payment for services',
'redirect_url' => 'https://yoursite.com/success',
'duration' => 24, // Duration in hours
'is_fixed_amount' => true
];
$paymentLink = Payment::gateway('flutterwave')->createPaymentLink($linkData);
$subscriptionData = [
'customer' => [
'email' => 'customer@example.com',
'name' => 'John Doe'
],
'plan' => 'RQP_PLAN_ID',
'amount' => 5000,
'currency' => 'NGN'
];
$subscription = Payment::gateway('flutterwave')->createSubscription($subscriptionData);
$virtualAccountData = [
'email' => 'customer@example.com',
'bvn' => '12345678901',
'is_permanent' => true,
'customer_name' => 'John Doe'
];
$virtualAccount = Payment::gateway('flutterwave')->createVirtualAccount($virtualAccountData);
$banks = Payment::gateway('flutterwave')->getSupportedBanks('NGN'); // NGN, GHS, KES, TZS, UGX, ZAR
$binValidation = Payment::gateway('flutterwave')->validateCardBin('539983');
$transferData = [
'account_bank' => '044', // Sort code
'account_number' => '0690000032',
'amount' => 5000,
'narration' => 'Payment for services',
'currency' => 'NGN',
'reference' => 'TRF_' . time()
];
$transfer = Payment::gateway('flutterwave')->sendMoney($transferData);
Set up your webhook endpoint in the Flutterwave dashboard
Create a route to handle webhooks:
// routes/web.php
Route::post('/flutterwave/webhook', [FlutterwaveWebhookController::class, 'handleWebhook']);
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Mdiqbal\LaravelPayments\Facades\Payment;
class FlutterwaveWebhookController extends Controller
{
public function handleWebhook(Request $request)
{
$webhookSecret = config('services.flutterwave.secret_hash');
$signature = $request->header('verif-hash');
if ($signature !== $webhookSecret) {
return response()->json(['error' => 'Invalid signature'], 401);
}
$payload = $request->all();
// Process the webhook
$result = Payment::gateway('flutterwave')->processWebhook($payload);
if ($result['success']) {
$eventType = $payload['event'];
switch ($eventType) {
case 'charge.completed':
// Handle successful payment
$this->handleSuccessfulPayment($payload['data']);
break;
case 'charge.failed':
// Handle failed payment
$this->handleFailedPayment($payload['data']);
break;
case 'refund.completed':
// Handle refund
$this->handleRefund($payload['data']);
break;
case 'transfer.completed':
// Handle transfer
$this->handleTransfer($payload['data']);
break;
case 'subscription.create':
// Handle subscription creation
$this->handleSubscriptionCreated($payload['data']);
break;
}
}
return response()->json(['status' => 'success']);
}
protected function handleSuccessfulPayment($data)
{
// Update order status, send confirmation email, etc.
}
protected function handleFailedPayment($data)
{
// Log failed payment, notify user, etc.
}
protected function handleRefund($data)
{
// Update refund status, etc.
}
protected function handleTransfer($data)
{
// Update transfer status, etc.
}
protected function handleSubscriptionCreated($data)
{
// Handle subscription creation
}
}
The Flutterwave gateway provides detailed error messages:
$payment = Payment::gateway('flutterwave')->pay($paymentRequest);
if (!$payment['success']) {
$error = $payment['error'];
$message = $error['message'];
$code = $error['code'];
// Handle error based on type
if ($code === 'INVALID_REQUEST') {
// Invalid request parameters
} elseif ($code === 'INSUFFICIENT_FUNDS') {
// Insufficient funds
} elseif ($code === 'CARD_DECLINED') {
// Card declined
}
}
INVALID_REQUEST: Request parameters are invalidP004: Insufficient fundsCARD_DECLINED: Card was declinedINVALID_OTP: Invalid OTP providedTRANSACTION_NOT_FOUND: Transaction not foundDUPLICATE_TRANSACTION: Duplicate transaction attemptUse these test cards for testing:
Test CVV: 123 Test Expiry: Any future date Test PIN: 3310
Use 123456 as the OTP for test transactions.
Use these test USSD codes:
*123*456# - MTN*555*678# - Airtel*888*901# - 9mobile*666*234# - GloFlutterwave supports payments in the following countries:
Flutterwave supports multiple currencies including:
Flutterwave implements rate limits:
Implement proper rate limiting in your application to avoid being blocked.
pay() - Initialize a paymentverify() - Verify a transactionrefund() - Process a refundcapturePayment() - Capture an authorized paymentvoidPayment() - Void an authorized paymentcreateCustomer() - Create a new customerupdateCustomer() - Update customer detailsgetCustomer() - Retrieve customer informationgetCustomerTransactions() - Get customer's transaction historycreatePaymentLink() - Create a payment linkupdatePaymentLink() - Update a payment linkgetPaymentLink() - Retrieve payment link detailscreateSubscription() - Create a subscriptionupdateSubscription() - Update subscriptioncancelSubscription() - Cancel a subscriptiongetSubscriptions() - List all subscriptionssendMoney() - Send money to bank accountgetTransfer() - Get transfer detailsverifyAccount() - Verify bank account numbergetSupportedBanks() - Get supported banks for a countryvalidateCardBin() - Validate card BIN informationgetExchangeRate() - Get currency exchange ratesgetPaymentMethods() - Get available payment methodsFor Flutterwave-specific support:
For Laravel Payments package support:
How can I help you explore Laravel packages today?