laravel-monnify-sdk maintained by scwar
Laravel Monnify SDK
A comprehensive Laravel package for integrating with the Monnify payment gateway. This package provides a clean, fluent interface for handling transactions, invoices, subaccounts, and webhooks.
Features
- ✅ Complete Monnify API coverage (Transactions, Invoices, Subaccounts)
- ✅ Automatic token management with caching
- ✅ Webhook handling with signature verification
- ✅ Laravel Events for transaction status changes
- ✅ Database migrations for storing transactions/invoices locally
- ✅ Type-safe DTOs for all API responses
- ✅ Facade support for clean, expressive API
- ✅ Comprehensive exception handling
- ✅ Full test coverage structure
Requirements
- PHP >= 8.1 (PHP 8.2+ required for Laravel 12)
- Laravel >= 10.0, >= 11.0, or >= 12.0
- Guzzle HTTP Client
Installation
Install the package via Composer:
composer require scwar/laravel-monnify-sdk
Publish Configuration
Publish the configuration file:
php artisan vendor:publish --tag=monnify-config
This will create a config/monnify.php file in your application.
Publish Migrations
Publish the database migrations:
php artisan vendor:publish --tag=monnify-migrations
Run the migrations:
php artisan migrate
Environment Variables
Add the following environment variables to your .env file:
MONNIFY_API_KEY=your_api_key
MONNIFY_SECRET_KEY=your_secret_key
MONNIFY_CONTRACT_CODE=your_contract_code
MONNIFY_WEBHOOK_SECRET=your_webhook_secret
MONNIFY_BASE_URL=https://api.monnify.com
MONNIFY_REDIRECT_URL=https://your-app.com/payment/callback
For sandbox/testing, use:
MONNIFY_BASE_URL=https://sandbox.monnify.com
Configuration
The configuration file is located at config/monnify.php. You can customize:
- API credentials
- Base URL (sandbox/production)
- Webhook secret key
- Cache configuration
- Database table names
- Route prefix and middleware
- Default transaction/invoice settings
Usage
Using the Facade
The package provides a facade for easy access:
use Scwar\Monnify\Facades\Monnify;
Transactions
Initialize a Transaction
use Scwar\Monnify\Facades\Monnify;
$transaction = Monnify::transaction()->initialize([
'amount' => 1000.00,
'customerName' => 'John Doe',
'customerEmail' => 'john@example.com',
'paymentReference' => 'unique-payment-reference',
'paymentDescription' => 'Payment for order #123',
'currencyCode' => 'NGN',
'redirectUrl' => 'https://your-app.com/payment/callback',
'metadata' => [
'order_id' => 123,
'user_id' => 456,
],
]);
// Get the checkout URL
$checkoutUrl = $transaction->checkoutUrl;
// Redirect user to checkout
return redirect($checkoutUrl);
Get Transaction Status
$transaction = Monnify::transaction()->getStatus('transaction-reference');
if ($transaction->status === 'PAID') {
// Transaction is successful
}
Verify Transaction
$transaction = Monnify::transaction()->verify('transaction-reference');
Refund Transaction
$refund = Monnify::transaction()->refund(
transactionReference: 'transaction-reference',
amount: 1000.00,
refundReason: 'Customer requested refund',
customerNote: 'Refund processed'
);
Query Transaction History
$transactions = Monnify::transaction()->queryHistory([
'page' => 0,
'size' => 20,
'fromDate' => '2024-01-01',
'toDate' => '2024-01-31',
]);
Invoices
Create an Invoice
$invoice = Monnify::invoice()->create([
'amount' => 5000.00,
'invoiceReference' => 'unique-invoice-reference',
'description' => 'Invoice for services',
'currencyCode' => 'NGN',
'contractCode' => config('monnify.contract_code'),
'customerEmail' => 'customer@example.com',
'customerName' => 'Jane Doe',
'expiryDate' => now()->addDays(7)->toIso8601String(),
'lineItems' => [
[
'lineItemId' => 'item-1',
'name' => 'Service Fee',
'quantity' => 1,
'unitPrice' => 5000.00,
],
],
]);
// Get the checkout URL
$checkoutUrl = $invoice->checkoutUrl;
Get Invoice Details
$invoice = Monnify::invoice()->getDetails('invoice-reference');
Cancel Invoice
Monnify::invoice()->cancel('invoice-reference');
List Invoices
$invoices = Monnify::invoice()->list([
'page' => 0,
'size' => 20,
]);
Subaccounts
Create Subaccount
$subaccount = Monnify::subaccount()->create([
'subAccountCode' => 'SUB_001',
'subAccountName' => 'Main Subaccount',
'email' => 'subaccount@example.com',
'splitPercentage' => 10.0,
]);
// Get the subaccount code
$subaccountCode = $subaccount['subAccountCode'];
Update Subaccount
Monnify::subaccount()->update('SUB_001', [
'subAccountName' => 'Updated Name',
'splitPercentage' => 15.0,
]);
Delete Subaccount
Monnify::subaccount()->delete('SUB_001');
Get Subaccount Details
$subaccount = Monnify::subaccount()->getDetails('SUB_001');
List Subaccounts
$subaccounts = Monnify::subaccount()->list([
'page' => 0,
'size' => 20,
]);
Webhooks
The package automatically sets up webhook routes. By default, the webhook endpoint is:
POST /api/monnify/webhook
You can customize this in the configuration file.
Webhook Events
The package automatically handles the following webhook events:
SUCCESSFUL_TRANSACTION- FiresTransactionCompletedeventFAILED_TRANSACTION- FiresTransactionFailedeventOVERPAYMENT- FiresTransactionFailedeventPARTIAL_OVERPAYMENT- FiresTransactionFailedeventINVOICE_UPDATE- Updates invoice record
Listening to Events
You can listen to the events in your EventServiceProvider:
use Scwar\Monnify\Events\TransactionCompleted;
use Scwar\Monnify\Events\TransactionFailed;
use Scwar\Monnify\Events\WebhookReceived;
protected $listen = [
TransactionCompleted::class => [
// Your listeners
],
TransactionFailed::class => [
// Your listeners
],
WebhookReceived::class => [
// Your listeners
],
];
Example listener:
use Scwar\Monnify\Events\TransactionCompleted;
class SendPaymentConfirmation
{
public function handle(TransactionCompleted $event)
{
$transaction = $event->transaction;
// Send confirmation email
// Update order status
// etc.
}
}
Webhook Signature Verification
The package automatically verifies webhook signatures using HMAC SHA512. Make sure to set MONNIFY_WEBHOOK_SECRET in your .env file.
Models
The package provides Eloquent models for transactions and invoices:
MonnifyTransaction
use Scwar\Monnify\Models\MonnifyTransaction;
// Get all successful transactions
$transactions = MonnifyTransaction::successful()->get();
// Get transactions for a customer
$transactions = MonnifyTransaction::forCustomer('customer@example.com')->get();
// Check transaction status
$transaction = MonnifyTransaction::where('transaction_reference', 'ref-123')->first();
if ($transaction->isSuccessful()) {
// Transaction is paid
}
MonnifyInvoice
use Scwar\Monnify\Models\MonnifyInvoice;
// Get all paid invoices
$invoices = MonnifyInvoice::paid()->get();
// Get invoices for a customer
$invoices = MonnifyInvoice::forCustomer('customer@example.com')->get();
// Check invoice status
$invoice = MonnifyInvoice::where('invoice_reference', 'inv-123')->first();
if ($invoice->isPaid()) {
// Invoice is paid
}
if ($invoice->isExpired()) {
// Invoice has expired
}
Exceptions
The package provides custom exceptions:
Scwar\Monnify\Exceptions\MonnifyException- Base exceptionScwar\Monnify\Exceptions\AuthenticationException- Authentication errorsScwar\Monnify\Exceptions\RequestException- API request errors
Example:
use Scwar\Monnify\Exceptions\AuthenticationException;
use Scwar\Monnify\Exceptions\RequestException;
try {
$transaction = Monnify::transaction()->initialize([...]);
} catch (AuthenticationException $e) {
// Handle authentication error
} catch (RequestException $e) {
// Handle request error
$response = $e->getResponse();
}
Testing
Run the tests:
composer test
Or using PHPUnit directly:
vendor/bin/phpunit
API Documentation
For complete API documentation, visit the Monnify Developer Documentation.
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
License
This package is open-sourced software licensed under the MIT license.
Support
For issues and questions, please open an issue on GitHub.
Changelog
Please see CHANGELOG for more information on what has changed recently.