PHPackages                             santosdave/paystack-wrapper - 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. [API Development](/categories/api)
4. /
5. santosdave/paystack-wrapper

ActiveLibrary[API Development](/categories/api)

santosdave/paystack-wrapper
===========================

A comprehensive and secure Laravel wrapper for Paystack payment gateway

1.4.0(4mo ago)06MITPHPPHP ^8.1|^8.2|^8.3

Since Dec 1Pushed 4mo agoCompare

[ Source](https://github.com/santosdave/paystack-wrapper)[ Packagist](https://packagist.org/packages/santosdave/paystack-wrapper)[ RSS](/packages/santosdave-paystack-wrapper/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (5)Dependencies (9)Versions (5)Used By (0)

Laravel Paystack Wrapper
========================

[](#laravel-paystack-wrapper)

A comprehensive, secure, and production-ready Laravel wrapper for the Paystack payment gateway API.

Features
--------

[](#features)

- ✅ **Complete API Coverage** - All Paystack API endpoints covered
- 🔒 **Secure by Default** - SSL verification, webhook signature validation
- 🚀 **Performance Optimized** - Built-in caching for frequently accessed data
- 📝 **Comprehensive Logging** - Track all API interactions with sensitive data redaction
- 🎯 **Type-Safe** - Proper exception handling with custom exception classes
- 🧪 **Fully Tested** - Extensive test coverage
- 📦 **Framework Agnostic Core** - Easy integration with Laravel
- 🔄 **Automatic Conversions** - Currency amount conversion to/from subunits
- 🎨 **Fluent API** - Clean, intuitive method chaining
- 🔔 **Webhook Support** - Secure webhook handling with signature verification

Table of Contents
-----------------

[](#table-of-contents)

- [Requirements](#requirements)
- [Installation](#installation)
- [Configuration](#configuration)
- [Usage](#usage)
    - [Transactions](#transactions)
    - [Customers](#customers)
    - [Plans &amp; Subscriptions](#plans--subscriptions)
    - [Subaccounts](#subaccounts)
    - [Transfers](#transfers)
    - [Refunds](#refunds)
    - [Disputes](#disputes)
    - [Verification](#verification)
    - [Payment Pages](#payment-pages)
    - [Payment Requests](#payment-requests)
    - [Dedicated Accounts](#dedicated-accounts)
    - [Webhooks](#webhooks)
- [Error Handling](#error-handling)
- [Testing](#testing)
- [Security](#security)
- [Contributing](#contributing)

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

[](#requirements)

- PHP 8.1 or higher
- Laravel 10.x or 11.x
- GuzzleHTTP 7.5 or higher

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

[](#installation)

Install via Composer:

```
composer require santosdave/paystack-wrapper
```

Publish the configuration file:

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

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

[](#configuration)

Add your Paystack credentials to `.env`:

```
PAYSTACK_PUBLIC_KEY=pk_test_xxxxxxxxxxxxx
PAYSTACK_SECRET_KEY=sk_test_xxxxxxxxxxxxx
PAYSTACK_MERCHANT_EMAIL=your@email.com
PAYSTACK_CURRENCY=NGN
PAYSTACK_WEBHOOK_SECRET=your_webhook_secret

# Optional
PAYSTACK_LOGGING_ENABLED=true
PAYSTACK_CACHE_ENABLED=true
```

Usage
-----

[](#usage)

### Transactions

[](#transactions)

```
use SantosDave\Paystack\Facades\Paystack;

// Initialize a transaction
$transaction = Paystack::transaction()->initialize([
    'email' => 'customer@email.com',
    'amount' => 10000, // NGN 100.00 (automatically converted to kobo)
    'currency' => 'NGN',
    'callback_url' => route('payment.callback'),
    'metadata' => ['order_id' => 'ORD123'],
]);

// Redirect user to payment page
return redirect($transaction['data']['authorization_url']);

// Verify transaction
$verification = Paystack::transaction()->verify($reference);

// List transactions
$transactions = Paystack::transaction()->list([
    'perPage' => 50,
    'page' => 1,
    'status' => 'success',
]);

// Fetch single transaction
$transaction = Paystack::transaction()->fetch($transactionId);

// Charge authorization (saved card)
$charge = Paystack::transaction()->charge([
    'email' => 'customer@email.com',
    'amount' => 5000,
    'authorization_code' => 'AUTH_xxx',
]);

// Get transaction timeline
$timeline = Paystack::transaction()->timeline($idOrReference);

// Export transactions
$export = Paystack::transaction()->export([
    'from' => '2024-01-01',
    'to' => '2024-12-31',
]);

// Partial debit
$debit = Paystack::transaction()->partialDebit([
    'authorization_code' => 'AUTH_xxx',
    'currency' => 'NGN',
    'amount' => 5000,
    'email' => 'customer@email.com',
]);
```

### Customers

[](#customers)

```
// Create customer
$customer = Paystack::customer()->create([
    'email' => 'customer@email.com',
    'first_name' => 'John',
    'last_name' => 'Doe',
    'phone' => '+2348012345678',
]);

// List customers
$customers = Paystack::customer()->list();

// Fetch customer
$customer = Paystack::customer()->fetch($customerCode);

// Update customer
$updated = Paystack::customer()->update($customerCode, [
    'first_name' => 'Jane',
    'metadata' => ['vip' => true],
]);

// Validate customer (KYC)
$validation = Paystack::customer()->validate($customerCode, [
    'first_name' => 'John',
    'last_name' => 'Doe',
    'type' => 'bank_account',
    'value' => '0123456789',
    'country' => 'NG',
    'bvn' => '12345678901',
    'bank_code' => '007',
    'account_number' => '0123456789',
]);

// Whitelist/blacklist customer
$action = Paystack::customer()->setRiskAction([
    'customer' => 'CUS_xxx',
    'risk_action' => 'allow', // or 'deny'
]);

// Deactivate authorization
Paystack::customer()->deactivateAuthorization($authorizationCode);
```

### Plans &amp; Subscriptions

[](#plans--subscriptions)

```
// Create plan
$plan = Paystack::plan()->create([
    'name' => 'Monthly Premium',
    'amount' => 5000, // NGN 50.00
    'interval' => 'monthly', // daily, weekly, monthly, yearly
    'description' => 'Premium subscription plan',
    'send_invoices' => true,
    'send_sms' => true,
]);

// List plans
$plans = Paystack::plan()->list();

// Fetch plan
$plan = Paystack::plan()->fetch($planCode);

// Update plan
$updated = Paystack::plan()->update($planCode, [
    'name' => 'Updated Plan Name',
    'amount' => 7500,
]);

// Create subscription
$subscription = Paystack::subscription()->create([
    'customer' => 'CUS_xxx',
    'plan' => 'PLN_xxx',
]);

// List subscriptions
$subscriptions = Paystack::subscription()->list();

// Fetch subscription
$subscription = Paystack::subscription()->fetch($subscriptionCode);

// Enable subscription
$enabled = Paystack::subscription()->enable([
    'code' => $subscriptionCode,
    'token' => $emailToken,
]);

// Disable subscription
$disabled = Paystack::subscription()->disable([
    'code' => $subscriptionCode,
    'token' => $emailToken,
]);

// Generate update subscription link
$link = Paystack::subscription()->generateUpdateLink($subscriptionCode);

// Send update subscription link via email
$sent = Paystack::subscription()->sendUpdateLink($subscriptionCode);
```

### Subaccounts

[](#subaccounts)

```
// Create subaccount
$subaccount = Paystack::subaccount()->create([
    'business_name' => 'ABC Corp',
    'settlement_bank' => '058',
    'account_number' => '0123456789',
    'percentage_charge' => 10.5,
    'description' => 'Marketplace vendor account',
]);

// List subaccounts
$subaccounts = Paystack::subaccount()->list();

// Fetch subaccount
$subaccount = Paystack::subaccount()->fetch($subaccountCode);

// Update subaccount
$updated = Paystack::subaccount()->update($subaccountCode, [
    'business_name' => 'Updated Business Name',
    'percentage_charge' => 15.0,
    'active' => true,
]);
```

### Transfers

[](#transfers)

```
// Create transfer recipient
$recipient = Paystack::transferRecipient()->create([
    'type' => 'nuban',
    'name' => 'John Doe',
    'account_number' => '0123456789',
    'bank_code' => '058',
    'currency' => 'NGN',
]);

// List transfer recipients
$recipients = Paystack::transferRecipient()->list();

// Initiate transfer
$transfer = Paystack::transfer()->initiate([
    'source' => 'balance',
    'amount' => 50000, // NGN 500.00
    'recipient' => 'RCP_xxx',
    'reason' => 'Payment for services',
]);

// Bulk transfers
$bulk = Paystack::transfer()->bulkInitiate([
    'source' => 'balance',
    'transfers' => [
        [
            'amount' => 50000,
            'recipient' => 'RCP_xxx1',
            'reason' => 'Payment 1',
        ],
        [
            'amount' => 30000,
            'recipient' => 'RCP_xxx2',
            'reason' => 'Payment 2',
        ],
    ],
]);

// List transfers
$transfers = Paystack::transfer()->list();

// Fetch transfer
$transfer = Paystack::transfer()->fetch($transferCode);

// Finalize transfer (with OTP)
$finalized = Paystack::transfer()->finalize([
    'transfer_code' => 'TRF_xxx',
    'otp' => '123456',
]);

// Verify transfer
$verification = Paystack::transfer()->verify($reference);

// Disable OTP for transfers
$disabled = Paystack::transfer()->disableOtp();

// Check balance
$balance = Paystack::transferControl()->checkBalance();
```

### Refunds

[](#refunds)

```
// Create refund
$refund = Paystack::refund()->create([
    'transaction' => $transactionId,
    'amount' => 5000, // Optional: partial refund
    'merchant_note' => 'Customer requested refund',
    'customer_note' => 'Refund for cancelled order',
]);

// List refunds
$refunds = Paystack::refund()->list([
    'reference' => $transactionReference,
]);

// Fetch refund
$refund = Paystack::refund()->fetch($reference);
```

### Disputes

[](#disputes)

```
// List disputes
$disputes = Paystack::dispute()->list([
    'status' => 'pending',
]);

// Fetch dispute
$dispute = Paystack::dispute()->fetch($disputeId);

// Update dispute
$updated = Paystack::dispute()->update($disputeId, [
    'refund_amount' => 5000,
]);

// Add evidence
$evidence = Paystack::dispute()->addEvidence($disputeId, [
    'customer_email' => 'customer@email.com',
    'customer_name' => 'John Doe',
    'customer_phone' => '+2348012345678',
    'service_details' => 'Product delivered on 2024-01-15',
]);

// Get upload URL for evidence
$url = Paystack::dispute()->getUploadUrl($disputeId);

// Resolve dispute
$resolved = Paystack::dispute()->resolve($disputeId, [
    'resolution' => 'merchant-accepted',
    'message' => 'Refund processed',
    'refund_amount' => 5000,
    'uploaded_filename' => 'evidence.pdf',
]);

// Export disputes
$export = Paystack::dispute()->export();
```

### Verification

[](#verification)

```
// Resolve account number
$account = Paystack::verification()->resolveAccountNumber([
    'account_number' => '0123456789',
    'bank_code' => '058',
]);

// Validate account
$validation = Paystack::verification()->validateAccount([
    'account_name' => 'John Doe',
    'account_number' => '0123456789',
    'account_type' => 'personal',
    'bank_code' => '058',
    'country_code' => 'NG',
    'document_type' => 'identityNumber',
    'document_number' => 'ABC123456',
]);

// Resolve card BIN
$cardInfo = Paystack::verification()->resolveCardBin('539983');

// Match BVN
$bvnMatch = Paystack::verification()->matchBvn([
    'bvn' => '12345678901',
    'account_number' => '0123456789',
    'bank_code' => '058',
    'first_name' => 'John',
    'last_name' => 'Doe',
]);

// List supported banks
$banks = Paystack::miscellaneous()->listBanks(['country' => 'nigeria']);

// List countries
$countries = Paystack::miscellaneous()->listCountries();
```

### Payment Pages

[](#payment-pages)

```
// Create payment page
$page = Paystack::paymentPage()->create([
    'name' => 'Product Purchase',
    'description' => 'Purchase our amazing product',
    'amount' => 50000, // Optional: fixed amount
    'slug' => 'product-purchase',
]);

// List payment pages
$pages = Paystack::paymentPage()->list();

// Fetch payment page
$page = Paystack::paymentPage()->fetch($pageIdOrSlug);

// Update payment page
$updated = Paystack::paymentPage()->update($pageIdOrSlug, [
    'name' => 'Updated Page Name',
    'active' => true,
]);

// Check slug availability
$available = Paystack::paymentPage()->checkSlugAvailability('my-slug');
```

### Payment Requests

[](#payment-requests)

```
// Create payment request (invoice)
$request = Paystack::paymentRequest()->create([
    'customer' => 'CUS_xxx',
    'amount' => 100000,
    'due_date' => '2024-12-31',
    'description' => 'Invoice for services',
    'line_items' => [
        ['name' => 'Service 1', 'amount' => 50000],
        ['name' => 'Service 2', 'amount' => 50000],
    ],
    'send_notification' => true,
]);

// List payment requests
$requests = Paystack::paymentRequest()->list();

// Fetch payment request
$request = Paystack::paymentRequest()->fetch($requestCode);

// Verify payment request
$verification = Paystack::paymentRequest()->verify($requestCode);

// Send notification
$sent = Paystack::paymentRequest()->sendNotification($requestCode);

// Finalize draft
$finalized = Paystack::paymentRequest()->finalize($requestCode);

// Archive payment request
$archived = Paystack::paymentRequest()->archive($requestCode);
```

### Dedicated Accounts

[](#dedicated-accounts)

```
// Create dedicated virtual account
$account = Paystack::dedicatedAccount()->create([
    'customer' => 'CUS_xxx',
    'preferred_bank' => 'wema-bank',
]);

// Assign dedicated account
$assigned = Paystack::dedicatedAccount()->assign([
    'email' => 'customer@email.com',
    'first_name' => 'John',
    'last_name' => 'Doe',
    'phone' => '+2348012345678',
    'preferred_bank' => 'wema-bank',
    'country' => 'NG',
]);

// List dedicated accounts
$accounts = Paystack::dedicatedAccount()->list();

// Fetch dedicated account
$account = Paystack::dedicatedAccount()->fetch($accountId);

// Deactivate dedicated account
$deactivated = Paystack::dedicatedAccount()->deactivate($accountId);

// Fetch available providers
$providers = Paystack::dedicatedAccount()->fetchProviders();
```

### Webhooks

[](#webhooks)

Set up webhook handling in your routes:

```
// routes/web.php
use App\Http\Controllers\WebhookController;
use SantosDave\Paystack\Http\Middleware\VerifyWebhookSignature;

Route::post('/webhook/paystack', [WebhookController::class, 'handle'])
    ->middleware(VerifyWebhookSignature::class);
```

Create a webhook controller:

```
use SantosDave\Paystack\Webhook\WebhookHandler;

class WebhookController extends Controller
{
    public function handle(Request $request, WebhookHandler $handler)
    {
        $payload = $handler->parse($request);
        $eventType = $handler->getEventType($payload);
        $data = $handler->getEventData($payload);

        match ($eventType) {
            'charge.success' => $this->handleChargeSuccess($data),
            'transfer.success' => $this->handleTransferSuccess($data),
            'subscription.create' => $this->handleSubscriptionCreated($data),
            // ... handle other events
        };

        return response()->json(['status' => 'success']);
    }
}
```

Error Handling
--------------

[](#error-handling)

The wrapper provides specific exception classes:

```
use SantosDave\Paystack\Exceptions\PaystackException;
use SantosDave\Paystack\Exceptions\AuthenticationException;
use SantosDave\Paystack\Exceptions\ValidationException;
use SantosDave\Paystack\Exceptions\NotFoundException;
use SantosDave\Paystack\Exceptions\RateLimitException;

try {
    $transaction = Paystack::transaction()->initialize([
        'email' => 'customer@email.com',
        'amount' => 10000,
    ]);
} catch (AuthenticationException $e) {
    // Invalid API key
    Log::error('Authentication failed: ' . $e->getMessage());
} catch (ValidationException $e) {
    // Invalid parameters
    $errors = $e->getErrors();
} catch (RateLimitException $e) {
    // Rate limit exceeded
} catch (PaystackException $e) {
    // General Paystack error
}
```

Testing
-------

[](#testing)

Run the test suite:

```
composer test
```

Run with coverage:

```
composer test -- --coverage
```

Security Features
-----------------

[](#security-features)

- ✅ **SSL Verification**: Enforced in production environments
- ✅ **Webhook Signature Validation**: Verify webhook authenticity
- ✅ **Sensitive Data Redaction**: Automatic redaction in logs
- ✅ **Secure Headers**: Proper authentication headers
- ✅ **Input Validation**: Required field validation
- ✅ **Rate Limiting**: Graceful handling of rate limits

Performance
-----------

[](#performance)

- ✅ **Response Caching**: Automatic caching for GET requests
- ✅ **Connection Pooling**: Efficient HTTP connection management
- ✅ **Timeout Configuration**: Configurable request timeouts

Currency Support
----------------

[](#currency-support)

- **NGN** (Nigerian Naira) - Min: ₦50.00
- **USD** (US Dollar) - Min: $2.00
- **GHS** (Ghanaian Cedi) - Min: ₵0.10
- **ZAR** (South African Rand) - Min: R1.00
- **KES** (Kenyan Shilling) - Min: Ksh. 3.00
- **XOF** (West African CFA Franc) - Min: XOF 1.00

All amounts are automatically converted to subunits.

Helper Utilities
----------------

[](#helper-utilities)

```
use SantosDave\Paystack\Support\Helpers;

// Generate unique reference
$reference = Helpers::generateReference('ORDER');

// Format amount
$formatted = Helpers::formatAmount(10000, 'NGN'); // ₦ 100.00

// Get supported currencies
$currencies = Helpers::getSupportedCurrencies();

// Validate amount
$isValid = Helpers::validateAmount(100, 'NGN'); // true

// Get webhook event types
$events = Helpers::getWebhookEventTypes();
```

License
-------

[](#license)

MIT License

Support
-------

[](#support)

For issues and questions, please use the GitHub issue tracker.

Credits
-------

[](#credits)

Built with ❤️ for the Laravel community

###  Health Score

37

—

LowBetter than 83% of packages

Maintenance76

Regular maintenance activity

Popularity4

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity53

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 ~13 days

Total

4

Last Release

130d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/c58a87513095fe0454c5dd566a2a18cf274ec91c3d4de92fb0854f863d84da9e?d=identicon)[santodave86](/maintainers/santodave86)

---

Top Contributors

[![santosdave](https://avatars.githubusercontent.com/u/51959957?v=4)](https://github.com/santosdave "santosdave (10 commits)")

---

Tags

apilaravelwrapperpaymentgatewaypaystack

###  Code Quality

TestsPHPUnit

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/santosdave-paystack-wrapper/health.svg)

```
[![Health](https://phpackages.com/badges/santosdave-paystack-wrapper/health.svg)](https://phpackages.com/packages/santosdave-paystack-wrapper)
```

###  Alternatives

[mollie/laravel-mollie

Mollie API client wrapper for Laravel &amp; Mollie Connect provider for Laravel Socialite

3624.1M28](/packages/mollie-laravel-mollie)[checkout/checkout-sdk-php

Checkout.com SDK for PHP

553.3M7](/packages/checkout-checkout-sdk-php)[dariusiii/tmdb-laravel

Laravel Package for TMDB ( The Movie Database ) API. Provides easy access to the wtfzdotnet/php-tmdb-api library.

1821.1k](/packages/dariusiii-tmdb-laravel)

PHPackages © 2026

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