PHP code example of nexuspay / payment-made-easy

1. Go to this page and download the library: Download nexuspay/payment-made-easy library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

nexuspay / payment-made-easy example snippets


use Alphabalex\PaymentMadeEasy\GatewayCapabilities;
use Alphabalex\PaymentMadeEasy\Contracts\SubscriptionDriverInterface;

if (GatewayCapabilities::driverImplements('paystack', SubscriptionDriverInterface::class)) {
    // safe to call subscription APIs
}

$slugs = GatewayCapabilities::gatewaysImplementing(SubscriptionDriverInterface::class);

use Alphabalex\PaymentMadeEasy\Facades\Payment;

// Default driver (same payload shape as your configured gateway)
$response = Payment::initializePayment([
    'email'        => '[email protected]',
    'amount'       => 5000.00,
    'reference'    => 'ORDER_123',
    'callback_url' => 'https://yoursite.com/payment/callback',
    'metadata'     => ['order_id' => '123', 'customer_id' => '456'],
]);

// Other drivers — same general flow; see Gateway-Specific Notes for redirects and quirks
Payment::driver('flutterwave')->initializePayment([
    'email'    => '[email protected]',
    'amount'   => 5000.00,
    'name'     => 'John Doe',
    'phone'    => '+2348123456789',
    'currency' => 'NGN',
]);

Payment::driver('stripe')->initializePayment([
    'email'    => '[email protected]',
    'amount'   => 50.00,
    'currency' => 'usd',
]);

Payment::driver('seerbit')->initializePayment([
    'email'    => '[email protected]',
    'amount'   => 5000.00,
    'currency' => 'NGN',
    'name'     => 'John Doe',
    'phone'    => '+2348123456789',
]);

// Paystack — hosted checkout
$response = Payment::driver('paystack')->initializePayment([
    'email'        => '[email protected]',
    'amount'       => 5000.00,
    'reference'    => 'ORDER_123',
    'callback_url' => 'https://yoursite.com/payment/callback',
    'metadata'     => ['order_id' => '123'],
]);

// Redirect customer to $response['data']['authorization_url']

// Verify after callback
$verification = Payment::driver('paystack')->verifyPayment('ORDER_123');

// Payment details by reference
$payment = Payment::driver('paystack')->getPayment('ORDER_123');

// Refund
$refund = Payment::driver('paystack')->refundPayment('ORDER_123', 2500.00); // partial
$full   = Payment::driver('paystack')->refundPayment('ORDER_123');           // full

// List transactions
$txns = Payment::driver('paystack')->getTransactions(['per_page' => 50, 'page' => 1]);

use Alphabalex\PaymentMadeEasy\Facades\Payment;

// Hosted checkout (Paystack, Flutterwave, Seerbit, Squad, OPay, Budpay, Remita, PayPal, Paddle)
$result = Payment::driver('paystack')->pay([
    'email'  => '[email protected]',
    'amount' => 5000.00,
]);
// $result['status'] === 'redirect'
// $result['auth_url'] → redirect customer here
// $result['reference'] for later verification

// Client-side SDK (Stripe, Razorpay)
$result = Payment::driver('stripe')->pay([
    'email'    => '[email protected]',
    'amount'   => 5000.00,
    'currency' => 'NGN',
]);
// $result['status'] === 'sdk'
// $result['client_secret'] → pass to Stripe.js

// Card-on-file (Paystack, Flutterwave)
$result = Payment::driver('paystack')->pay([
    'email'              => '[email protected]',
    'amount'             => 5000.00,
    'authorization_code' => 'AUTH_xxxxx',
], function (array $response) {
    // Called on success — fulfill the order
});
// $result['status'] === 'completed' | 'failed'

// OTP flow (Interswitch)
$result = Payment::driver('interswitch')->pay(
    ['email' => '[email protected]', 'amount' => 5000.00],
    function (array $initResponse): ?string {
        // Collect OTP from user (email/SMS/API input)
        return $this->requestOtpFromUser($initResponse);
    }
);
// $result['status'] === 'otp_

// In callback controller after user returns from checkout
$result = Payment::driver('paystack')->pay([
    'email'        => '[email protected]',
    'amount'       => 5000,
    '_auto_verify' => true,
], function ($response) {
    // Payment confirmed — fulfill the order
});

use Alphabalex\PaymentMadeEasy\Contracts\SubscriptionDriverInterface;

$driver = Payment::driver('paystack');

// --- Plans ---
$plan = $driver->createPlan([
    'name'     => 'Pro Monthly',
    'amount'   => 5000.00,
    'interval' => 'monthly',   // monthly | weekly | annually | quarterly
]);
$planCode = $plan['data']['plan_code'];

$driver->updatePlan($planCode, ['name' => 'Pro Monthly (Updated)']);
$driver->getPlan($planCode);
$driver->listPlans(['per_page' => 20]);
$driver->deletePlan($planCode);

// --- Subscriptions ---
$sub = $driver->createSubscription([
    'email'      => '[email protected]',
    'plan_code'  => $planCode,
    'start_date' => '2026-06-01T00:00:00.000Z', // optional
]);
$subCode = $sub['data']['subscription_code'];

$driver->getSubscription($subCode);
$driver->listSubscriptions(['plan' => $planCode]);
$driver->listCustomerSubscriptions('[email protected]');
$driver->pauseSubscription($subCode);
$driver->resumeSubscription($subCode);
$driver->cancelSubscription($subCode);

$stripePlan = Payment::driver('stripe')->createPlan([
    'name'     => 'Pro Monthly',
    'amount'   => 29.99,
    'currency' => 'usd',
    'interval' => 'month',
]);
$priceId = $stripePlan['data']['plan_code'];

Payment::driver('stripe')->createSubscription([
    'email'     => '[email protected]',
    'plan_code' => $priceId,
]);

// Resolve an account number before transferring
$account = Payment::driver('paystack')->resolveAccountNumber([
    'account_number' => '0123456789',
    'bank_code'      => '044',
]);

// Create recipient
$recipient = Payment::driver('paystack')->createTransferRecipient([
    'name'           => 'Jane Doe',
    'account_number' => '0123456789',
    'bank_code'      => '044',
    'currency'       => 'NGN',
]);
$recipientCode = $recipient['data']['recipient_code'];

// Single transfer
$transfer = Payment::driver('paystack')->transfer([
    'amount'    => 10000.00,
    'recipient' => $recipientCode,
    'reason'    => 'Salary payout',
    'reference' => 'PAYOUT_001',
]);

// Bulk transfer
Payment::driver('paystack')->bulkTransfer([
    'transfers' => [
        ['amount' => 5000.00, 'recipient' => 'RCP_abc', 'reference' => 'B1'],
        ['amount' => 3000.00, 'recipient' => 'RCP_def', 'reference' => 'B2'],
    ],
]);

// Verify & list
Payment::driver('paystack')->verifyTransfer('PAYOUT_001');
Payment::driver('paystack')->listTransfers(['per_page' => 50]);

// List banks
$banks = Payment::driver('paystack')->listBanks(['country' => 'nigeria']);

Payment::driver('monnify')->resolveAccountNumber([
    'account_number' => '0123456789',
    'bank_code'      => '044',
]);

Payment::driver('monnify')->transfer([
    'amount'                => 10000.00,
    'account_number'        => '0123456789',
    'bank_code'             => '044',
    'narration'             => 'Salary payout',
    'reference'             => 'MNFY_PAYOUT_001',
    'wallet_account_number' => config('payment-gateways.gateways.monnify.wallet_account_number'),
]);

Payment::driver('squad')->transfer([
    'account_number' => '0123456789',
    'bank_code'      => '044',
    'amount'         => 5000.00,
    'currency'       => 'NGN',
    'reference'      => 'SQ_PAYOUT_001',
    'narration'      => 'Salary',
]);

Payment::driver('remita')->bulkTransfer([
    'batchRef'  => 'BATCH_001',
    'narration' => 'Payroll',
    'transfers' => [
        ['amount' => 5000.00, 'account_number' => '0123456789', 'bank_code' => '044', 'name' => 'Jane Doe'],
    ],
]);

Payment::driver('budpay')->transfer([
    'amount'         => 5000.00,
    'currency'       => 'NGN',
    'account_number' => '0123456789',
    'bank_code'      => '044',
    'narration'      => 'Payout',
    'reference'      => 'BDP_PAYOUT_001',
]);

// Create a dedicated virtual account (bank transfer → auto-credited)
$va = Payment::driver('paystack')->createVirtualAccount([
    'email'          => '[email protected]',
    'name'           => 'Jane Doe',
    'bvn'            => '12345678901',
    'preferred_bank' => 'wema-bank',  // or 'titan-paystack'
]);

$accountNumber = $va['data']['account_number'];
$bankName      = $va['data']['bank']['name'];

Payment::driver('paystack')->getVirtualAccount($va['data']['id']);
Payment::driver('paystack')->listVirtualAccounts(['active' => true]);
Payment::driver('paystack')->deactivateVirtualAccount($va['data']['id']);

$link = Payment::driver('paystack')->createPaymentLink([
    'name'        => 'Product Launch Special',
    'amount'      => 2500.00,
    'description' => 'Early-bird ticket',
    'currency'    => 'NGN',
]);

$url = $link['data']['link'];

Payment::driver('paystack')->updatePaymentLink($link['data']['id'], ['amount' => 3000.00]);
Payment::driver('paystack')->getPaymentLink($link['data']['id']);
Payment::driver('paystack')->listPaymentLinks();
Payment::driver('paystack')->disablePaymentLink($link['data']['id']);

// config/payment-gateways.php
'webhooks' => [
    // ...
    'throttle' => [
        'enabled' => env('PAYMENT_WEBHOOK_THROTTLE_ENABLED', false),
        // ...
    ],
    'middleware' => [
        \Alphabalex\PaymentMadeEasy\Http\Middleware\ThrottlePaymentWebhooks::class,
    ],
],

use Alphabalex\PaymentMadeEasy\Events\PaymentSuccessful;
use Alphabalex\PaymentMadeEasy\Events\PaymentFailed;
use Alphabalex\PaymentMadeEasy\Events\PaymentPending;
use Alphabalex\PaymentMadeEasy\Events\RefundProcessed;
use Alphabalex\PaymentMadeEasy\Events\SubscriptionCreated;
use Alphabalex\PaymentMadeEasy\Events\SubscriptionCancelled;
use Alphabalex\PaymentMadeEasy\Events\SubscriptionRenewed;
use Alphabalex\PaymentMadeEasy\Events\TransferSuccessful;
use Alphabalex\PaymentMadeEasy\Events\TransferFailed;
use Alphabalex\PaymentMadeEasy\Events\DisputeCreated;
use Alphabalex\PaymentMadeEasy\Events\ChargebackCreated;

protected $listen = [
    PaymentSuccessful::class   => [App\Listeners\HandleSuccessfulPayment::class],
    PaymentFailed::class       => [App\Listeners\HandleFailedPayment::class],
    PaymentPending::class      => [App\Listeners\HandlePendingPayment::class],
    RefundProcessed::class     => [App\Listeners\HandleRefundProcessed::class],
    SubscriptionCreated::class   => [App\Listeners\HandleSubscriptionCreated::class],
    SubscriptionCancelled::class => [App\Listeners\HandleSubscriptionCancelled::class],
    SubscriptionRenewed::class   => [App\Listeners\HandleSubscriptionRenewed::class],
    TransferSuccessful::class    => [App\Listeners\HandleTransferSuccessful::class],
    TransferFailed::class        => [App\Listeners\HandleTransferFailed::class],
    DisputeCreated::class        => [App\Listeners\HandleDisputeCreated::class],
    ChargebackCreated::class     => [App\Listeners\HandleChargebackCreated::class],
];

// app/Listeners/HandleSuccessfulPayment.php
class HandleSuccessfulPayment
{
    public function handle(PaymentSuccessful $event): void
    {
        $gateway   = $event->webhookEvent->getGateway();   // e.g. 'paystack'
        $eventType = $event->webhookEvent->getEventType(); // e.g. 'charge.success'
        $data      = $event->paymentData;

        // Normalized keys commonly 

use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
use Alphabalex\PaymentMadeEasy\WebhookManager;
use Alphabalex\PaymentMadeEasy\Exceptions\WebhookException;

class CustomWebhookController extends Controller
{
    public function handle(Request $request, string $gateway, WebhookManager $webhookManager)
    {
        try {
            $webhookManager->handle($gateway, $request);

            return response()->json(['status' => 'success']);
        } catch (WebhookException $e) {
            return response()->json(['error' => $e->getMessage()], 400);
        }
    }
}

use Alphabalex\PaymentMadeEasy\Contracts\SubscriptionDriverInterface;
use Alphabalex\PaymentMadeEasy\Contracts\DisbursementDriverInterface;
use Alphabalex\PaymentMadeEasy\Contracts\VirtualAccountDriverInterface;
use Alphabalex\PaymentMadeEasy\Contracts\PaymentLinkDriverInterface;
use Alphabalex\PaymentMadeEasy\Contracts\CustomerDriverInterface;
use Alphabalex\PaymentMadeEasy\Contracts\DisputeDriverInterface;
use Alphabalex\PaymentMadeEasy\Contracts\BalanceDriverInterface;
use Alphabalex\PaymentMadeEasy\Contracts\SettlementDriverInterface;
use Alphabalex\PaymentMadeEasy\Contracts\SubaccountDriverInterface;
use Alphabalex\PaymentMadeEasy\Contracts\SplitDriverInterface;
use Alphabalex\PaymentMadeEasy\Contracts\ChargeAuthorizationDriverInterface;

$driver = Payment::driver('paystack');

if ($driver instanceof SubscriptionDriverInterface) {
    $driver->createPlan([...]);
}

if ($driver instanceof DisbursementDriverInterface) {
    $driver->transfer([...]);
}

if ($driver instanceof VirtualAccountDriverInterface) {
    $driver->createVirtualAccount([...]);
}

if ($driver instanceof PaymentLinkDriverInterface) {
    $driver->createPaymentLink([...]);
}

if ($driver instanceof CustomerDriverInterface) {
    $driver->createCustomer([...]);
}

if ($driver instanceof DisputeDriverInterface) {
    $driver->listDisputes();
}

if ($driver instanceof BalanceDriverInterface) {
    $driver->getBalance('NGN');
}

if ($driver instanceof SettlementDriverInterface) {
    $driver->listSettlements();
}

use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
use Alphabalex\PaymentMadeEasy\PaymentManager;
use Alphabalex\PaymentMadeEasy\Contracts\SubscriptionDriverInterface;

class PaymentController extends Controller
{
    public function __construct(private PaymentManager $paymentManager) {}

    public function charge(Request $request)
    {
        $driver = $this->paymentManager->driver($request->gateway ?? 'paystack');

        return $driver->initializePayment([
            'email'     => $request->email,
            'amount'    => $request->amount,
            'reference' => $request->reference,
        ]);
    }

    public function createPlan(Request $request)
    {
        $driver = $this->paymentManager->driver($request->gateway ?? 'paystack');

        if (!$driver instanceof SubscriptionDriverInterface) {
            abort(422, 'Selected gateway does not support subscriptions.');
        }

        return $driver->createPlan($request->validated());
    }
}

use Alphabalex\PaymentMadeEasy\Contracts\CustomerDriverInterface;

$driver = Payment::driver('paystack');

// Create a customer
$customer = $driver->createCustomer([
    'email'      => '[email protected]',
    'first_name' => 'John',
    'last_name'  => 'Doe',
    'phone'      => '+2348012345678',
    'metadata'   => ['plan' => 'premium'],
]);
$customerCode = $customer['data']['customer_code'];

// Get a customer by email or code
$fetched = $driver->getCustomer('CUS_xxxxx');

// List all customers
$customers = $driver->listCustomers(['per_page' => 50]);

// Update a customer
$driver->updateCustomer($customerCode, ['first_name' => 'Jane']);

// Validate customer identity (Paystack)
$driver->validateCustomer($customerCode, [
    'country'        => 'NG',
    'type'           => 'bank_account',
    'account_number' => '0123456789',
    'bvn'            => '20012345677',
    'bank_code'      => '058',
    'first_name'     => 'John',
    'last_name'      => 'Doe',
]);

// Whitelist or blacklist a customer (Paystack)
$driver->setCustomerRiskAction($customerCode, 'allow'); // or 'deny' or 'default'

use Alphabalex\PaymentMadeEasy\Contracts\ChargeAuthorizationDriverInterface;

$driver = Payment::driver('paystack');

// Charge a reusable authorization
$response = $driver->chargeAuthorization([
    'email'              => '[email protected]',
    'amount'             => 5000.00,
    'authorization_code' => 'AUTH_xxxxx',
    'reference'          => 'RECURRING_001',
]);

// Get authorization details
$auth = $driver->getAuthorization('AUTH_xxxxx');

// List all authorizations
$auths = $driver->listAuthorizations(['per_page' => 50]);

// Deactivate an authorization
$driver->deactivateAuthorization('AUTH_xxxxx');

use Alphabalex\PaymentMadeEasy\Contracts\DisputeDriverInterface;

$driver = Payment::driver('paystack');

// List disputes
$disputes = $driver->listDisputes(['status' => 'pending']);

// Get a single dispute
$dispute = $driver->getDispute('2867');

// Update a dispute (e.g. set refund amount)
$driver->updateDispute('2867', ['refund_amount' => 1002]);

// Add evidence to a dispute (Paystack)
$driver->addDisputeEvidence('2867', [
    'customer_email'   => '[email protected]',
    'customer_name'    => 'John Doe',
    'customer_phone'   => '+2348012345678',
    'service_details'  => 'Service was delivered on 2025-01-15',
]);

// Get upload URL for evidence attachments (Paystack)
$upload = $driver->getDisputeUploadUrl('2867');

// Get disputes for a specific transaction (Paystack)
$txDisputes = $driver->getTransactionDisputes('12345');

// Respond to a dispute message
$driver->respondToDisputeMessage('2867', ['message' => 'We delivered the service']);

$driver = Payment::driver('flutterwave');

// List chargebacks
$chargebacks = $driver->listChargebacks();

// Accept or reject a chargeback
$driver->acceptChargeback('1');
$driver->rejectChargeback('1');

use Alphabalex\PaymentMadeEasy\Contracts\BalanceDriverInterface;

$driver = Payment::driver('paystack');

// Get available balance (all currencies)
$balance = $driver->getBalance();

// Get balance for a specific currency
$ngnBalance = $driver->getBalance('NGN');

// Get ledger balance (

use Alphabalex\PaymentMadeEasy\Contracts\SettlementDriverInterface;

$driver = Payment::driver('paystack');

// List settlements
$settlements = $driver->listSettlements(['status' => 'success']);

// Get transactions that make up a settlement
$txns = $driver->getSettlementTransactions('3090024', ['per_page' => 50]);

use Alphabalex\PaymentMadeEasy\Services\BalanceAggregator;

$aggregator = app(BalanceAggregator::class);

// Get balances from all gateways that support it
$result = $aggregator->aggregate();

// Filter by currency
$result = $aggregator->aggregate(currency: 'NGN');

// Query specific gateways only
$result = $aggregator->aggregate(gateways: ['paystack', 'flutterwave']);

[
    'gateways' => [
        'paystack' => [
            'status' => 'success',
            'data'   => [['currency' => 'NGN', 'balance' => 500000.0]],
        ],
        'flutterwave' => [
            'status' => 'success',
            'data'   => [['currency' => 'NGN', 'balance' => 300000.0]],
        ],
    ],
    'totals'     => ['NGN' => 800000.0],
    'queried_at' => '2026-08-21T12:00:00+00:00',
    'successful' => 2,
    'failed'     => 0,
    'skipped'    => 0,
]

use Alphabalex\PaymentMadeEasy\Contracts\SubaccountDriverInterface;

$driver = Payment::driver('paystack');

// Create a subaccount
$subaccount = $driver->createSubaccount([
    'business_name'     => 'Vendor Store',
    'settlement_bank'   => '058',
    'account_number'    => '0123456047',
    'percentage_charge' => 30.0,
    'description'       => 'Vendor marketplace account',
]);
$subaccountCode = $subaccount['data']['subaccount_code'];

// List, get, update subaccounts
$driver->listSubaccounts();
$driver->getSubaccount($subaccountCode);
$driver->updateSubaccount($subaccountCode, ['business_name' => 'Updated Name']);

use Alphabalex\PaymentMadeEasy\Contracts\SplitDriverInterface;

$driver = Payment::driver('paystack');

// Create a split
$split = $driver->createSplit([
    'name'        => 'Marketplace Split',
    'type'        => 'percentage',
    'currency'    => 'NGN',
    'subaccounts' => [
        ['subaccount' => 'ACCT_vendor1', 'share' => 40],
        ['subaccount' => 'ACCT_vendor2', 'share' => 30],
    ],
    'bearer_type' => 'all-proportional', // who bears transaction fees
]);
$splitCode = $split['data']['split_code'];

// List, get, update splits
$driver->listSplits();
$driver->getSplit($splitCode);
$driver->updateSplit($splitCode, ['bearer_type' => 'all']);

// Add or remove subaccounts from a split
$driver->addSubaccountToSplit($splitCode, 'ACCT_vendor3', 20);
$driver->removeSubaccountFromSplit($splitCode, 'ACCT_vendor2');

Payment::driver('paystack')->initializePayment([
    'email'      => '[email protected]',
    'amount'     => 10000.00,
    'split_code' => $splitCode,
]);

// Automatic — gets a generated idem_<uuid> key
Payment::driver('paystack')->initializePayment([
    'email'  => '[email protected]',
    'amount' => 5000.00,
]);

// Custom key — for retry-safe operations like transfers
Payment::driver('paystack')->transfer([
    'amount'    => 10000.00,
    'recipient' => $recipientCode,
    'reference' => 'PAYOUT_001',
], 'idempotency_key' => 'payout_001');

// config/payment-gateways.php
'gateways' => [
    'paystack' => [
        'driver'           => 'paystack',
        'secret_key'       => env('PAYSTACK_SECRET_KEY'),
        // ...
        'retry_attempts'   => 3,        // default: 3 (0 = disabled)
        'retry_base_delay' => 500,      // default: 500ms
        'retry_max_delay'  => 5000,     // default: 5000ms (5s)
    ],
],

// Disable retry for a specific call
Payment::driver('paystack')->transfer([
    'amount'    => 10000.00,
    'recipient' => $recipientCode,
], 'retry' => false);

Payment::driver('monnify')->initializePayment([
    'email'       => '[email protected]',
    'amount'      => 5000.00,
    'currency'    => 'NGN',
    'name'        => 'John Doe',
    'description' => 'Order #123',
    'reference'   => 'ORDER_123',
]);

$va = Payment::driver('monnify')->createVirtualAccount([
    'email'             => '[email protected]',
    'name'              => 'Jane Doe',
    'bvn'               => '12345678901',
    'currency_code'     => 'NGN',
    'contract_code'     => config('payment-gateways.gateways.monnify.contract_code'),
    'reference'         => 'VA_' . uniqid(),
    'split_percentages' => [],
]);

Payment::driver('squad')->initializePayment([
    'email'     => '[email protected]',
    'amount'    => 5000.00,
    'currency'  => 'NGN',
    'reference' => 'TXN_' . uniqid(),
]);

// Virtual account
Payment::driver('squad')->createVirtualAccount([
    'customer_identifier' => 'customer_001',
    'email'               => '[email protected]',
    'name'                => 'Jane Doe',
]);

$result = Payment::driver('remita')->initializePayment([
    'email'       => '[email protected]',
    'amount'      => 5000.00,
    'description' => 'Invoice #1001',
    'reference'   => 'ORDER_1001',
]);

// Redirect to checkout: $result['data']['authorization_url']
// After callback, verify with RRR:
Payment::driver('remita')->verifyPayment($result['data']['rrr']);

Payment::driver('budpay')->initializePayment([
    'email'     => '[email protected]',
    'amount'    => 5000.00,
    'reference' => 'BDP_' . uniqid(),
    'currency'  => 'NGN',
]);

$result = Payment::driver('interswitch')->pay(
    ['email' => '[email protected]', 'amount' => 5000.00],
    function (array $initResponse): ?string {
        return $this->requestOtpFromUser($initResponse);
    }
);

if ($result['status'] === 'completed') {
    // Payment approved (responseCode '00')
} elseif ($result['status'] === 'otp_

// OTP authentication (Verve/Mastercard)
Payment::driver('interswitch')->authenticateOtp([
    'paymentId'    => '12345',
    'otp'          => '123456',
    'transactionId' => 'ISW_TXN_001',
]);

// Card tokenization for recurring billing
Payment::driver('interswitch')->tokenizeCard([
    'pan'     => '5061020100000000009',
    'expiry'  => '10/25',
    'cvv'     => '123',
    'amount'  => 100,
    'email'   => '[email protected]',
    'pin'     => '1111',
]);

// Charge a tokenized card
Payment::driver('interswitch')->chargeRecurring([
    'token'   => 'isw_token_xxx',
    'amount'  => 5000.00,
    'email'   => '[email protected]',
]);

// Subscriptions
Payment::driver('interswitch')->createPlan([
    'name'     => 'Pro Monthly',
    'amount'   => 5000.00,
    'interval' => 'monthly',
]);

// Disbursements
Payment::driver('interswitch')->transfer([
    'amount'         => 10000.00,
    'account_number' => '0123456789',
    'bank_code'      => '044',
    'narration'      => 'Salary payout',
]);

$order = Payment::driver('paypal')->initializePayment([
    'amount'   => 50.00,
    'currency' => 'USD',
    'email'    => '[email protected]',
]);
// Redirect to $order['links'][n]['href'] where rel == 'approve'
// After approval, capture using the order ID:
Payment::driver('paypal')->verifyPayment($order['id']);

$response = Payment::driver('mpesa')->initializePayment([
    'phone'  => '254712345678',   // international format, no +
    'amount' => 500,              // KES whole number
]);
$checkoutRequestId = $response['data']['checkout_request_id'];

// Poll or wait for callback, then verify:
Payment::driver('mpesa')->verifyPayment($checkoutRequestId);

$response = Payment::driver('mtnmomo')->initializePayment([
    'phone'    => '256771234567',   // MSISDN, no +
    'amount'   => 1000,
    'currency' => 'UGX',
]);
$referenceId = $response['data']['reference'];

// Poll for status:
Payment::driver('mtnmomo')->verifyPayment($referenceId);

// Disbursement:
Payment::driver('mtnmomo')->transfer([
    'phone'    => '256771234567',
    'amount'   => 1000,
    'currency' => 'UGX',
    'narration' => 'Salary payout',
]);

$order = Payment::driver('razorpay')->initializePayment([
    'email'    => '[email protected]',
    'amount'   => 499.00,
    'currency' => 'INR',
    'name'     => 'Jane Doe',
    'phone'    => '+919876543210',
]);
// Pass $order['id'], $order['data']['key_id'], etc. to Razorpay checkout.js

$transaction = Payment::driver('paddle')->initializePayment([
    'amount'      => 29.99,
    'currency'    => 'USD',
    'description' => 'Pro plan',
    'email'       => '[email protected]',
]);
// Redirect to $transaction['data']['authorization_url']

// In your test
Payment::shouldReceive('driver->initializePayment')
    ->once()
    ->andReturn(['status' => true, 'data' => ['authorization_url' => 'https://...']]);

use Alphabalex\PaymentMadeEasy\Services\PaymentRecorder;

$recorder = app(PaymentRecorder::class);

// After initializing a payment
$transaction = $recorder->recordTransaction('paystack', $requestData, $gatewayResponse);

// After verifying / receiving a webhook
$recorder->updateTransactionStatus('ORDER_001', 'successful', 'PS_GATEWAY_REF');

// Record a transfer
$transfer = $recorder->recordTransfer('paystack', $transferData, $transferResponse);

// Log a webhook event for auditing
$recorder->logWebhookEvent('paystack', $webhookEvent);

// Refunds (e.g. after a refund webhook) — appends `payment_refunds` rows and updates parent status
// (partially_refunded vs refunded from summed amounts). Optional 6th arg: provider refund id for dedupe.
$recorder->handleRefundWebhook('paystack', 'ORDER_001', 50.0, 'NGN', $rawPayload, 're_abc123');

// Attach a transaction to a user
$transaction->payable()->associate($user)->save();

// Scope helpers
PaymentTransaction::successful()->gateway('paystack')->get();
PaymentSubscription::active()->forEmail('[email protected]')->get();
PaymentTransfer::successful()->gateway('mtnmomo')->get();
bash
composer 
bash
php artisan vendor:publish --provider="Alphabalex\PaymentMadeEasy\PaymentServiceProvider"
bash
# Publish migrations
php artisan vendor:publish --tag=payment-gateways-migrations

# Run migrations
php artisan migrate
bash
php artisan payment:gateways --configured
bash
php artisan payment:transactions
php artisan payment:transactions --gateway=paystack --status=successful --limit=50