laravel-fincra maintained by prevailexcel
Laravel Fincra
A Laravel Package for working with Fincra Payments seamlessly.
Fincra offers a contemporary financial infrastructure designed for businesses and developers, enabling them to facilitate local and international payouts, gather payments from customers, and create virtual accounts.
This package allows you to:
- Accept payments via Checkout (Pop widget & Redirect)
- Create and manage virtual accounts
- Process local and international payouts
- Manage beneficiaries
- Verify identities (BVN, Account Numbers)
- Handle webhooks with verification
- And much more!

Requirements
PHP 7.4+ or PHP 8.0+, and Composer are required.
Installation
To get the latest version of Laravel Fincra, simply require it:
composer require prevailexcel/laravel-fincra
Or add the following line to the require block of your composer.json file:
"prevailexcel/laravel-fincra": "1.0.*"
You'll then need to run composer install or composer update to download it and have the autoloader updated.
Service Provider & Facade (Laravel < 5.5)
Once Laravel Fincra is installed, you need to register the service provider. Open up config/app.php and add the following to the providers key:
'providers' => [
...
PrevailExcel\Fincra\FincraServiceProvider::class,
...
]
Also, register the Facade:
'aliases' => [
...
'Fincra' => PrevailExcel\Fincra\Facades\Fincra::class,
...
]
If you use Laravel >= 5.5 you can skip this step and go to configuration
Configuration
You can publish the configuration file using this command:
php artisan vendor:publish --provider="PrevailExcel\Fincra\FincraServiceProvider"
A configuration-file named fincra.php with sensible defaults will be placed in your config directory:
<?php
return [
/**
* Public Key From Fincra Dashboard
*/
'publicKey' => getenv('FINCRA_PUBLIC_KEY'),
/**
* Secret Key From Fincra Dashboard
*/
'secretKey' => getenv('FINCRA_SECRET_KEY'),
/**
* Business ID From Fincra Dashboard
*/
'businessId' => getenv('FINCRA_BUSINESS_ID'),
/**
* Webhook Secret for verifying webhooks
*/
'webhookSecret' => getenv('FINCRA_WEBHOOK_SECRET'),
/**
* Environment: sandbox or live
*/
'env' => env('FINCRA_ENV', 'sandbox'),
/**
* Fincra Sandbox URL
*/
'sandboxUrl' => env('FINCRA_SANDBOX_URL', 'https://sandboxapi.fincra.com'),
/**
* Fincra Live URL
*/
'liveUrl' => env('FINCRA_LIVE_URL', 'https://api.fincra.com'),
];
Environment Variables
Open your .env file and add your Fincra API keys:
FINCRA_PUBLIC_KEY=pk_test_****************************
FINCRA_SECRET_KEY=sk_test_****************************
FINCRA_BUSINESS_ID=****************************
FINCRA_WEBHOOK_SECRET=****************************
FINCRA_ENV=sandbox
Note: Remember to change
FINCRA_ENVtoliveand update the keys when you're in production.
Usage
Payment Flow Overview
- Collect payment information from your customer
- Initialize payment using either:
- Inline Checkout (Pop Widget) - User pays without leaving your site
- Checkout Redirect - Redirect user to Fincra hosted page
- Verify the transaction
- Handle webhook notifications
Routes Setup
Add these routes to handle payments:
Route::post('/pay', [PaymentController::class, 'redirectToGateway'])->name('pay');
Route::callback(PaymentController::class, 'handleGatewayCallback');
Route::webhook(WebhookController::class, 'handleWebhook');
Checkout Methods
1. Inline Checkout (Pop Widget)
The inline checkout displays a payment modal on your page, allowing customers to pay without leaving your site.
Controller Example
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use PrevailExcel\Fincra\Facades\Fincra;
class PaymentController extends Controller
{
/**
* Display checkout widget
*/
public function redirectToGateway()
{
try {
return Fincra::payWithWidget();
} catch (\Exception $e) {
return redirect()->back()->withMessage([
'msg' => $e->getMessage(),
'type' => 'error'
]);
}
}
/**
* Handle callback from widget
*/
public function handleGatewayCallback()
{
$paymentDetails = fincra()->getPaymentData();
// Process payment details
// Mark order as paid, send email, etc.
dd($paymentDetails);
}
}
Blade Form
<form method="POST" action="{{ route('pay') }}">
@csrf
<div class="form-group">
<label for="name">Full Name</label>
<input class="form-control" type="text" name="name" required />
</div>
<div class="form-group">
<label for="email">Email</label>
<input class="form-control" type="email" name="email" required />
</div>
<div class="form-group">
<label for="phoneNumber">Phone Number</label>
<input class="form-control" type="tel" name="phoneNumber" required />
</div>
<div class="form-group">
<label for="amount">Amount</label>
<input class="form-control" type="number" name="amount" required />
</div>
<input type="hidden" name="currency" value="NGN" />
<input type="hidden" name="reference" value="{{ uniqid() }}" />
<div class="form-submit">
<button class="btn btn-primary" type="submit">Pay Now</button>
</div>
</form>
2. Checkout Redirect
Redirect users to Fincra's hosted checkout page:
public function redirectToGateway()
{
try {
$data = [
'amount' => request()->amount,
'currency' => 'NGN',
'customer' => [
'name' => request()->name,
'email' => request()->email,
'phoneNumber' => request()->phoneNumber,
],
'paymentMethods' => ['card', 'bank_transfer', 'payattitude'],
'feeBearer' => 'customer',
'reference' => uniqid('ref_'),
'redirectUrl' => route('payment.callback'),
];
return Fincra::checkoutRedirect($data)->redirectNow();
// Or for API, return the link:
// return Fincra::checkoutRedirect($data, true);
} catch (\Exception $e) {
return back()->with('error', $e->getMessage());
}
}
Virtual Accounts
Create Virtual Account
// Create Temporary Virtual Account
$data = [
'currency' => 'NGN',
'accountType' => 'individual',
'accountName' => 'John Doe',
'bvn' => '12345678901', // Required for Nigerian accounts
'meansOfId' => [
[
'type' => 'identityCard',
'number' => 'A1234567890',
]
],
];
$virtualAccount = Fincra::createVirtualAccount($data);
// Create Permanent Virtual Account
$data['isPermanent'] = true;
$permanentAccount = Fincra::createVirtualAccount($data);
Get Virtual Accounts
// Get all virtual accounts
$accounts = Fincra::getVirtualAccounts();
// Get single virtual account
$account = Fincra::getVirtualAccount($virtualAccountId);
// Get virtual account requests
$requests = Fincra::getVirtualAccountRequests();
Payouts
Initiate Payout
$data = [
'sourceCurrency' => 'NGN',
'destinationCurrency' => 'NGN',
'amount' => 10000,
'business' => config('fincra.businessId'),
'description' => 'Payment for services',
'beneficiary' => [
'firstName' => 'John',
'lastName' => 'Doe',
'email' => '[email protected]',
'phoneNumber' => '+2348012345678',
'accountHolderName' => 'John Doe',
'accountNumber' => '1234567890',
'type' => 'individual',
'bankCode' => '058', // GTBank
'country' => 'NG',
],
'paymentDestination' => 'bank_account',
];
$payout = Fincra::initiatePayout($data);
Get Payouts
// Get all payouts
$payouts = Fincra::getPayouts();
// Get single payout
$payout = Fincra::getPayout($payoutId);
// Get payout by reference
$payout = Fincra::getPayoutByReference($reference);
Beneficiaries
// Create beneficiary
$data = [
'firstName' => 'John',
'lastName' => 'Doe',
'email' => '[email protected]',
'phoneNumber' => '+2348012345678',
'accountHolderName' => 'John Doe',
'bank' => [
'name' => 'GTBank',
'code' => '058',
'accountNumber' => '1234567890',
],
'type' => 'individual',
'currency' => 'NGN',
'paymentDestination' => 'bank_account',
'destinationAddress' => 'Lagos, Nigeria',
];
$beneficiary = Fincra::createBeneficiary($data);
// Get all beneficiaries
$beneficiaries = Fincra::getBeneficiaries();
// Get single beneficiary
$beneficiary = Fincra::getBeneficiary($beneficiaryId);
// Update beneficiary
$updated = Fincra::updateBeneficiary($beneficiaryId, $data);
// Delete beneficiary
$deleted = Fincra::deleteBeneficiary($beneficiaryId);
Identity Verification
Verify BVN
$verification = Fincra::verifyBvn($bvn);
Verify Bank Account
$data = [
'accountNumber' => '1234567890',
'bankCode' => '058',
];
$verification = Fincra::verifyBankAccount($data);
Verify IBAN
$verification = Fincra::verifyIban($iban);
BIN Resolution
$binInfo = Fincra::resolveBin($bin);
Balance & Transactions
// Get balance
$balance = Fincra::getBalance();
// Get balance by currency
$balance = Fincra::getBalance('NGN');
// Get all transactions
$transactions = Fincra::getTransactions();
// Get single transaction
$transaction = Fincra::getTransaction($transactionId);
Conversions
// Create conversion quote
$data = [
'sourceCurrency' => 'NGN',
'destinationCurrency' => 'USD',
'amount' => 100000,
];
$quote = Fincra::createConversion($data);
// Get conversion rate
$rate = Fincra::getConversionRate('NGN', 'USD');
Webhooks
Setup Webhook Handler
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class WebhookController extends Controller
{
public function handleWebhook()
{
// Verify and get webhook data
fincra()->getWebhookData()->processData(function ($data) {
// Process the webhook data
logger('Fincra Webhook:', $data);
$event = $data['event'] ?? null;
switch ($event) {
case 'charge.successful':
// Handle successful charge
$this->handleSuccessfulCharge($data);
break;
case 'charge.failed':
// Handle failed charge
$this->handleFailedCharge($data);
break;
case 'payout.successful':
// Handle successful payout
$this->handleSuccessfulPayout($data);
break;
case 'virtual_account.credited':
// Handle virtual account credit
$this->handleVirtualAccountCredit($data);
break;
}
// Dispatch queued jobs for heavy operations
// ProcessPaymentJob::dispatch($data);
});
// Acknowledge receipt
return response()->json(['status' => 'success'], 200);
}
protected function handleSuccessfulCharge($data)
{
// Your logic here
}
}
CSRF Exception
Add the webhook route to the CSRF exception array in app/Http/Middleware/VerifyCsrfToken.php:
protected $except = [
'fincra/webhook',
];
Webhook Events
Fincra sends webhooks for these events:
charge.successful- Payment completed successfullycharge.failed- Payment failedpayout.successful- Payout completedpayout.failed- Payout failedvirtual_account.credited- Virtual account received paymentconversion.successful- Currency conversion completed
Available Methods
Payments/Collections
Fincra::payWithWidget(?array $data);
Fincra::checkoutRedirect(?array $data, bool $returnLink = false);
Fincra::verifyPayment(?string $reference);
Fincra::getPaymentData();
Virtual Accounts
Fincra::createVirtualAccount(array $data);
Fincra::getVirtualAccounts();
Fincra::getVirtualAccount(string $id);
Fincra::getVirtualAccountRequests();
Fincra::updateVirtualAccount(string $id, array $data);
Fincra::deleteVirtualAccount(string $id);
Payouts
Fincra::initiatePayout(array $data);
Fincra::getPayouts();
Fincra::getPayout(string $id);
Fincra::getPayoutByReference(string $reference);
Fincra::cancelPayout(string $id);
Beneficiaries
Fincra::createBeneficiary(array $data);
Fincra::getBeneficiaries();
Fincra::getBeneficiary(string $id);
Fincra::updateBeneficiary(string $id, array $data);
Fincra::deleteBeneficiary(string $id);
Identity Verification
Fincra::verifyBvn(string $bvn);
Fincra::verifyBankAccount(array $data);
Fincra::verifyIban(string $iban);
Fincra::resolveBin(string $bin);
Balance & Transactions
Fincra::getBalance(?string $currency);
Fincra::getTransactions();
Fincra::getTransaction(string $id);
Conversions
Fincra::createConversion(array $data);
Fincra::getConversions();
Fincra::getConversionRate(string $from, string $to);
Webhooks
Fincra::getWebhookData();
Utilities
Fincra::getBanks(?string $country);
Fincra::getCurrencies();
Fincra::getCountries();
Changelog
Please see CHANGELOG for more information what has changed recently.
Contributing
Please feel free to fork this package and contribute by submitting a pull request to enhance the functionalities.
Security
If you discover any security related issues, please email prevailexcellent@gmail.com instead of using the issue tracker.
Credits
License
The MIT License (MIT). Please see License File for more information.
Support
For support, please reach out via:
- Email: prevailexcellent@gmail.com
- X/Twitter: @EjimaduPrevail
- LinkedIn: Chimeremeze Prevail Ejimadu
Also check out my page on medium to catch articles and tutorials on Laravel follow me on medium!
Thanks! Chimeremeze Prevail Ejimadu.
Show some ❤️ by starring this repository!