PHPackages                             heccubernny/laravel-multi-payment-gateway - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Payment Processing](/categories/payments)
4. /
5. heccubernny/laravel-multi-payment-gateway

ActiveLibrary[Payment Processing](/categories/payments)

heccubernny/laravel-multi-payment-gateway
=========================================

A Laravel package that acts as a multiple payment gateway API package, supporting Monnify, Stripe, Paystack, XpressPay, Upperlink, and Flutterwave.

00PHP

Since Jun 20Pushed todayCompare

[ Source](https://github.com/Heccubernny/laravel-multi-package-gateway)[ Packagist](https://packagist.org/packages/heccubernny/laravel-multi-payment-gateway)[ RSS](/packages/heccubernny-laravel-multi-payment-gateway/feed)WikiDiscussions main Synced today

READMEChangelogDependenciesVersions (1)Used By (0)

Laravel Multi-Payment Gateway Package
=====================================

[](#laravel-multi-payment-gateway-package)

A modern, robust, and extensible Laravel package designed to handle integrations for multiple payment gateways with runtime driver switching.

Supported Gateways
------------------

[](#supported-gateways)

- **Stripe**
- **Paystack**
- **Flutterwave**
- **Monnify**
- **XpressPayments (XpressPay)**
- **Upperlink (Paygate)**

---

Key Design Patterns &amp; Features
----------------------------------

[](#key-design-patterns--features)

- **Manager Design Pattern**: Leverages Laravel's native driver manager structure to resolve gateway drivers at runtime.
- **Dynamic Gateway Switching**: Easily swap gateways inline using `PaymentGateway::driver('gateway_name')`.
- **Decoupled Architecture**: Fires standard Laravel events (`PaymentSuccessful` &amp; `PaymentFailed`) upon transaction validation. The parent application simply listens to these events to credit or update user transactions.
- **Race Condition Prevention**: Built-in webhook safety sleep delays ensure server-to-server notifications don't conflict with redirect callback processing.

---

Installation
------------

[](#installation)

You can install the package via Composer from Packagist:

```
composer require heccubernny/laravel-multi-payment-gateway
```

The Service Provider will be auto-discovered by Laravel. If you have auto-discovery disabled, manually register it in `config/app.php` (or `bootstrap/providers.php` on Laravel 11+):

```
'providers' => [
    PaymentGateway\MultiPayment\PaymentGatewayServiceProvider::class,
]
```

---

Configuration
-------------

[](#configuration)

Publish the config file:

```
php artisan vendor:publish --provider="PaymentGateway\MultiPayment\PaymentGatewayServiceProvider" --tag="payment-gateway-config"
```

Configure your credentials in `.env`. An example `.env.example` file is included in the package.

---

Usage
-----

[](#usage)

### 1. Initialization Payloads

[](#1-initialization-payloads)

When initiating checkouts, different gateways require specific formats for amounts and metadata.

#### For Upperlink (Paygate)

[](#for-upperlink-paygate)

- **Amount**: Must be in whole Naira, rounded down or to 2 decimal places.
- **Metadata**: Pass stringified JSON using the `meta` key.
- **Success Check**: Redirect to checkout URL on response code `"200"`.

```
use PaymentGateway\MultiPayment\Facades\PaymentGateway;

$payload = [
    'amount' => floor($amountInNaira), // e.g. 5000
    'merchantId' => config('payment-gateway.gateways.upperlink.ref'),
    'meta' => json_encode([
        'user_id' => 1,
        'payment_id' => 2,
    ]),
    'redirectUrl' => config('payment-gateway.gateways.upperlink.redirect_url'),
];

$response = PaymentGateway::driver('upperlink')->initializeTransaction($payload);

if (isset($response['code']) && $response['code'] === '200') {
    $checkoutUrl = $response['data']['checkOutUrl'];
    return redirect()->away($checkoutUrl);
}
```

#### For XpressPayments (XpressPay)

[](#for-xpresspayments-xpresspay)

- **Amount**: Must be in whole Naira, formatted as a string.
- **Metadata**: Array of name-value dictionaries.
- **Success Check**: Redirect to payment URL on responseCode `"00"`.

```
use PaymentGateway\MultiPayment\Facades\PaymentGateway;

$payload = [
    'amount' => (string) $amountInNaira, // e.g. "5000"
    'merchantId' => config('payment-gateway.gateways.xpresspay.merchant_id'),
    'metaData' => [
        ['name' => 'user_id', 'value' => '1'],
        ['name' => 'payment_id', 'value' => '2'],
    ],
    'callbackUrl' => config('payment-gateway.gateways.xpresspay.redirect_url'),
];

$response = PaymentGateway::driver('xpresspay')->initializeTransaction($payload);

if (isset($response['responseCode']) && $response['responseCode'] === '00') {
    $paymentUrl = $response['data']['paymentUrl'];
    return redirect()->away($paymentUrl);
}
```

---

### 2. Manual Verification

[](#2-manual-verification)

You can manually verify a transaction reference using:

```
$reference = 'TX-123456';

// For Default Gateway
$result = PaymentGateway::verifyTransaction($reference);

// For Specific Gateway
$result = PaymentGateway::driver('upperlink')->verifyTransaction($reference);
```

---

### 3. Dynamic Configuration Overrides

[](#3-dynamic-configuration-overrides)

If your application uses dynamic database-driven credentials (e.g. multi-tenancy), you can dynamically override configuration options on the fly using the `withConfig()` or `setConfig()` methods:

```
use PaymentGateway\MultiPayment\Facades\PaymentGateway;

$customConfig = [
    'api_key' => 'XP_SEC_LIVE_DynamicKey123',
    'merchant_id' => 'XP_MERCH_DynamicId456'
];

$response = PaymentGateway::driver('xpresspay')
    ->withConfig($customConfig)
    ->initializeTransaction($payload);
```

You can pass any custom or optional parameters via the `$payload` array directly to `initializeTransaction()`, and the driver will forward it:

```
$payload = [
    'amount' => '5000',
    'merchantId' => 'XP_MERCH_12345',
    'currency' => 'NGN', // Optional parameter passed dynamically
    'custom_channel' => 'card', // Optional parameter
    'metaData' => [
        ['name' => 'user_id', 'value' => '1'],
    ]
];
```

---

### 4. Exception Handling

[](#4-exception-handling)

The package handles gateway connections and configuration issues gracefully. You can intercept exceptions thrown by the package for precise error handling:

- `PaymentGateway\MultiPayment\Exceptions\InvalidConfigurationException`: Thrown if mandatory config keys are missing.
- `PaymentGateway\MultiPayment\Exceptions\PaymentApiException`: Thrown for HTTP-level connection failures or gateway API errors (HTTP codes &gt;= 400).

```
use PaymentGateway\MultiPayment\Exceptions\InvalidConfigurationException;
use PaymentGateway\MultiPayment\Exceptions\PaymentApiException;

try {
    $result = PaymentGateway::driver('xpresspay')->initializeTransaction($payload);
} catch (InvalidConfigurationException $e) {
    // Config not set up correctly in .env
    Log::error("Configuration error: " . $e->getMessage());
} catch (PaymentApiException $e) {
    // API error (e.g., unauthorized or bad request)
    Log::error("Gateway error: " . $e->getMessage() . " (Code: " . $e->getCode() . ")");
}
```

---

Callbacks and Webhooks
----------------------

[](#callbacks-and-webhooks)

The package includes preconfigured endpoints and controller mappings:

EndpointMethodPurpose`/api/payment/xpresspay-callback``GET`/`POST`XpressPay synchronous redirect callback`/api/payment/upperlink-callback``GET`/`POST`Upperlink synchronous redirect callback`/api/payment/xpresspay-webhook``POST`XpressPay asynchronous server-to-server webhook`/api/payment/upperlink-webhook``POST`Upperlink asynchronous server-to-server webhook---

Event-Driven Local Crediting
----------------------------

[](#event-driven-local-crediting)

When a webhook or callback successfully verifies a transaction, the package fires the `PaymentSuccessful` event. You can create a Listener in your host application to credit transactions locally.

### Example Listener Setup

[](#example-listener-setup)

1. Register your listener in `app/Providers/EventServiceProvider.php`:

```
use PaymentGateway\MultiPayment\Events\PaymentSuccessful;
use App\Listeners\CreditLocalPayment;

protected $listen = [
    PaymentSuccessful::class => [
        CreditLocalPayment::class,
    ],
];
```

2. Implement `App\Listeners\CreditLocalPayment.php`:

```
namespace App\Listeners;

use PaymentGateway\MultiPayment\Events\PaymentSuccessful;
use App\Models\Transaction;
use App\Models\User;

class CreditLocalPayment
{
    public function handle(PaymentSuccessful $event)
    {
        $gateway = $event->gateway;       // e.g. 'xpresspay' or 'upperlink'
        $reference = $event->reference;   // e.g. transaction reference string
        $metadata = $event->metadata;     // Array containing ['user_id' => 1, 'payment_id' => 2]

        // Process crediting logic
        $userId = $metadata['user_id'] ?? null;
        $paymentId = $metadata['payment_id'] ?? null;

        $transaction = Transaction::where('reference', $reference)->first();

        if ($transaction && !$transaction->isCompleted()) {
            $transaction->update([
                'status' => 'completed',
                'gateway' => $gateway,
                'metadata' => json_encode($metadata)
            ]);

            // Credit student wallet or application fee
            // User::find($userId)->creditWallet($transaction->amount);
        }
    }
}
```

###  Health Score

20

—

LowBetter than 13% of packages

Maintenance65

Regular maintenance activity

Popularity0

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity11

Early-stage or recently created project

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/42838142?v=4)[Paul Oladayo](/maintainers/heccubernny)[@Heccubernny](https://github.com/Heccubernny)

---

Top Contributors

[![Heccubernny](https://avatars.githubusercontent.com/u/42838142?v=4)](https://github.com/Heccubernny "Heccubernny (2 commits)")

### Embed Badge

![Health badge](/badges/heccubernny-laravel-multi-payment-gateway/health.svg)

```
[![Health](https://phpackages.com/badges/heccubernny-laravel-multi-payment-gateway/health.svg)](https://phpackages.com/packages/heccubernny-laravel-multi-payment-gateway)
```

###  Alternatives

[omnipay/coinbase

Coinbase driver for the Omnipay payment processing library

18570.2k1](/packages/omnipay-coinbase)[oxid-esales/amazon-pay-module

AmazonPay module for OXID

1824.3k](/packages/oxid-esales-amazon-pay-module)[yenepay/php-sdk

YenePay SDK for PHP

112.7k](/packages/yenepay-php-sdk)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
