PHPackages                             mosesadewale/kora-laravel - 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. mosesadewale/kora-laravel

ActiveLibrary[Payment Processing](/categories/payments)

mosesadewale/kora-laravel
=========================

Laravel integration for the Kora payment API (formerly KoraPay)

v2.0.0(2w ago)04MITPHPPHP ^8.2

Since Jun 10Pushed 2w agoCompare

[ Source](https://github.com/mosesadewale/kora-laravel)[ Packagist](https://packagist.org/packages/mosesadewale/kora-laravel)[ RSS](/packages/mosesadewale-kora-laravel/feed)WikiDiscussions master Synced 1w ago

READMEChangelogDependencies (27)Versions (4)Used By (0)

kora-laravel
============

[](#kora-laravel)

Laravel integration for the [Kora PHP SDK](https://github.com/mosesadewale/kora-php). Provides a service provider, facade, and an optional verified webhook receiver.

Requirements
------------

[](#requirements)

- PHP 8.2+
- Laravel 10, 11, 12, or 13
- [mosesadewale/kora-php](https://github.com/mosesadewale/kora-php) ^2.0

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

[](#installation)

```
composer require mosesadewale/kora-laravel
```

The service provider and `Kora` facade are auto-discovered via Laravel's package discovery.

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

[](#configuration)

Publish the config file:

```
php artisan vendor:publish --tag=kora-config
```

Then add to your `.env`:

```
KORA_SECRET_KEY=sk_live_...
KORA_ENCRYPTION_KEY=...        # required for card payments (32 bytes)
```

`KORA_ENVIRONMENT` is optional. When omitted, the package infers the environment from `KORA_SECRET_KEY`.

Full config reference (`config/kora.php`):

```
return [
    'secret_key'             => env('KORA_SECRET_KEY', ''),
    'encryption_key'         => env('KORA_ENCRYPTION_KEY', ''),
    'environment'            => env('KORA_ENVIRONMENT'),
    'webhook_path'           => env('KORA_WEBHOOK_PATH', 'webhooks/kora'),
    'register_webhook_route' => env('KORA_REGISTER_ROUTE', false),
    'timeout'                => (float) env('KORA_TIMEOUT', 30),
    'retry_attempts'         => (int)   env('KORA_RETRY_ATTEMPTS', 3),
];
```

If you want to be explicit, set `KORA_ENVIRONMENT=live` or `KORA_ENVIRONMENT=sandbox`. A mismatch with the key prefix throws `InvalidArgumentException` at boot time.

Usage
-----

[](#usage)

Use the `Kora` facade anywhere in your application:

```
use Kora\Laravel\Facades\Kora;

// Initialize a charge
$charge = Kora::charges()->charge([
    'reference'    => 'ref_' . uniqid(),
    'amount'       => 5000,
    'currency'     => 'NGN',
    'customer'     => ['email' => 'user@example.com', 'name' => 'Ada Okonkwo'],
    'redirect_url' => 'https://yourapp.com/callback',
]);

return redirect($charge->checkoutUrl);
```

All resources are available on the facade:

```
Kora::charges()        // ChargesResource
Kora::mobileMoney()    // MobileMoneyResource
Kora::payouts()        // PayoutsResource
Kora::bulkPayouts()    // BulkPayoutsResource
Kora::balances()       // BalancesResource
Kora::conversions()    // ConversionsResource
Kora::refunds()        // RefundsResource
Kora::poolAccounts()   // PoolAccountsResource
Kora::chargebacks()    // ChargebacksResource
Kora::webhooks()       // WebhookResource
```

See the [kora-php README](https://github.com/mosesadewale/kora-php) for full method signatures and usage examples for each resource.

Webhooks
--------

[](#webhooks)

Kora signs webhooks with your API `secret_key`.

### Optional route

[](#optional-route)

The package can register `POST webhooks/kora` with signature verification middleware applied, but the route is disabled by default so installing the package does not expose a public endpoint unexpectedly.

Enable it when you want the package-managed receiver:

```
KORA_REGISTER_ROUTE=true
KORA_WEBHOOK_PATH=webhooks/kora
```

The route is registered outside Laravel's `web` middleware group, so no CSRF exemption is needed.

### Laravel event

[](#laravel-event)

When a valid webhook arrives, the controller dispatches one generic event:

```
use Illuminate\Support\Facades\Event;
use Kora\Laravel\Events\KoraWebhookReceived;
use Kora\Sdk\Enums\WebhookEventType;

Event::listen(KoraWebhookReceived::class, function (KoraWebhookReceived $e) {
    match (WebhookEventType::tryFrom($e->event->type)) {
        WebhookEventType::ChargeSuccess => ProcessSuccessfulCharge::dispatch($e->event->data),
        WebhookEventType::PayoutSuccess => ProcessSuccessfulPayout::dispatch($e->event->data),
        WebhookEventType::RefundSuccess => ProcessSuccessfulRefund::dispatch($e->event->data),
        default => null,
    };
});
```

Your application owns business processing, idempotency, queueing, and event-specific jobs/listeners.

Each `KoraWebhookReceived` event carries a `WebhookEvent $event` property:

```
$e->event->type;            // raw event string e.g. "charge.success"
$e->event->data;             // array — the full data payload from Kora
$e->event->data['reference'] // the transaction reference
```

Unknown future Kora event strings are still dispatched through `KoraWebhookReceived`; use `$e->event->type` when you need the raw provider value.

### Custom webhook route

[](#custom-webhook-route)

If you need full control, disable the built-in route and define your own:

```
// KORA_REGISTER_ROUTE=false in .env

// routes/api.php
Route::post('webhooks/kora', function (Request $request) {
    $raw       = $request->getContent();
    $signature = $request->headers->get('x-korapay-signature') ?? '';

    if (!Kora::webhooks()->verify($raw, $signature)) {
        abort(401);
    }

    $event = Kora::webhooks()->parse($raw);
    // dispatch your own event/job or handle $event manually
    return response()->json(['received' => true]);
});
```

Error handling
--------------

[](#error-handling)

```
use Kora\Sdk\Exceptions\ApiException;
use Kora\Sdk\Exceptions\AuthenticationException;
use Kora\Sdk\Exceptions\DuplicateReferenceException;
use Kora\Sdk\Exceptions\InsufficientFundsException;
use Kora\Sdk\Exceptions\KoraException;
use Kora\Sdk\Exceptions\NetworkException;
use Kora\Sdk\Exceptions\ValidationException;

try {
    Kora::payouts()->disburse($payload);
} catch (DuplicateReferenceException $e) {
    // reference already used
} catch (InsufficientFundsException $e) {
    // wallet balance too low
} catch (ValidationException $e) {
    Log::warning('Kora validation', $e->errors());
} catch (ApiException $e) {
    Log::error('Kora server error', ['context' => $e->context()]);
} catch (KoraException $e) {
    Log::error($e->getMessage());
}
```

Testing
-------

[](#testing)

Bind a mock against `KoraClientInterface` in your test — no network calls, no real credentials:

```
use Kora\Sdk\Contracts\KoraClientInterface;
use Kora\Sdk\DTOs\ChargeResponse;
use Kora\Sdk\Resources\ChargesResource;

$charges = $this->createMock(ChargesResource::class);
$charges->method('charge')->willReturn(ChargeResponse::fromArray([
    'reference'    => 'ref_001',
    'status'       => 'pending',
    'amount'       => 5000,
    'currency'     => 'NGN',
    'checkout_url' => 'https://pay.korahq.com/checkout/ref_001',
]));

$kora = $this->createMock(KoraClientInterface::class);
$kora->method('charges')->willReturn($charges);

$this->app->instance(KoraClientInterface::class, $kora);

// Kora facade and injected KoraClientInterface now use the mock
```

For webhook controller tests, use `Event::fake()` and post a signed payload:

```
use Illuminate\Support\Facades\Event;
use Kora\Laravel\Events\KoraWebhookReceived;

Event::fake();

$secret  = config('kora.secret_key');
$data    = ['reference' => 'ref_001', 'status' => 'success'];
$payload = json_encode(['event' => 'charge.success', 'data' => $data]);
$sig     = hash_hmac('sha256', json_encode($data, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE), $secret);

$this->call('POST', config('kora.webhook_path'), [], [], [], [
    'HTTP_X_KORAPAY_SIGNATURE' => $sig,
    'CONTENT_TYPE'             => 'application/json',
], $payload)->assertStatus(200);

Event::assertDispatched(KoraWebhookReceived::class, function (KoraWebhookReceived $e) {
    return $e->event->type === 'charge.success'
        && $e->event->data['reference'] === 'ref_001';
});
```

Laravel
-------

[](#laravel)

This package is the Laravel integration. For framework-agnostic usage see [mosesadewale/kora-php](https://github.com/mosesadewale/kora-php).

License
-------

[](#license)

MIT

###  Health Score

41

—

FairBetter than 87% of packages

Maintenance97

Actively maintained with recent releases

Popularity5

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity48

Maturing project, gaining track record

 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.

###  Release Activity

Cadence

Every ~14 days

Total

3

Last Release

16d ago

Major Versions

v1.1.0 → v2.0.02026-07-09

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/32101786?v=4)[moses ADEWALE](/maintainers/mosesadewale)[@mosesadewale](https://github.com/mosesadewale)

---

Top Contributors

[![mosesadewale](https://avatars.githubusercontent.com/u/32101786?v=4)](https://github.com/mosesadewale "mosesadewale (7 commits)")

---

Tags

laravelsdkpaymentsafricakorapaykora

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Type Coverage Yes

### Embed Badge

![Health badge](/badges/mosesadewale-kora-laravel/health.svg)

```
[![Health](https://phpackages.com/badges/mosesadewale-kora-laravel/health.svg)](https://phpackages.com/packages/mosesadewale-kora-laravel)
```

###  Alternatives

[psalm/plugin-laravel

Psalm plugin for Laravel

3345.3M347](/packages/psalm-plugin-laravel)[laravel/mcp

Rapidly build MCP servers for your Laravel applications.

77922.3M186](/packages/laravel-mcp)[api-platform/laravel

API Platform support for Laravel

58174.6k17](/packages/api-platform-laravel)[laravel/cashier

Laravel Cashier provides an expressive, fluent interface to Stripe's subscription billing services.

2.5k30.2M151](/packages/laravel-cashier)[laravel/pulse

Laravel Pulse is a real-time application performance monitoring tool and dashboard for your Laravel application.

1.7k15.1M136](/packages/laravel-pulse)[roots/acorn

Framework for Roots WordPress projects built with Laravel components.

9762.4M133](/packages/roots-acorn)

PHPackages © 2026

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