alexasomba / paystack-openapi
Paystack API client for PHP
Requires
- php: ^8.1
- ext-curl: *
- ext-json: *
- ext-mbstring: *
- guzzlehttp/guzzle: ^7.3
- guzzlehttp/psr7: ^1.7 || ^2.0
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.5
- phpunit/phpunit: ^8.0 || ^9.0
README
PHP client for the Paystack API, generated from the Paystack OpenAPI spec in this repository.
Why this SDK
- Generated from the Paystack OpenAPI source of truth in this repo
- Includes opt-in helpers for timeouts, retries, idempotency, and structured API errors
- Keeps generated models and API classes aligned with the SDK generation spec
Requirements
PHP 8.1 and later.
Installation
composer require alexasomba/paystack
Or from source:
{
"repositories": [
{
"type": "vcs",
"url": "https://github.com/alexasomba/paystack-php.git"
}
],
"require": {
"alexasomba/paystack": "*"
}
}
Authenticate requests with your Paystack secret key through the generated configuration object:
$config = Configuration::getDefaultConfiguration() ->setAccessToken($_ENV['PAYSTACK_SECRET_KEY']);
Quick Start
<?php require_once __DIR__ . '/vendor/autoload.php'; use Alexasomba\Paystack\Api\TransactionApi; use Alexasomba\Paystack\Configuration; use Alexasomba\Paystack\Model\TransactionInitialize; use GuzzleHttp\Client; $config = Configuration::getDefaultConfiguration() ->setAccessToken($_ENV['PAYSTACK_SECRET_KEY']); $api = new TransactionApi(new Client(), $config); $response = $api->transactionInitialize( new TransactionInitialize([ 'email' => 'customer@example.com', 'amount' => 5000, ]) ); echo $response->getData()->getAuthorizationUrl() . PHP_EOL;
Generated API methods return typed model objects. Catch ApiException when you need raw status codes, headers, or response bodies while debugging.
API Basics
- Base URL:
https://api.paystack.co - HTTPS is required for all requests.
- Requests and responses are JSON-based.
- Most successful responses follow the
status,message,data, and optionalmetaenvelope described inPaystack-API/0a-Introduction.md. - Amounts are usually sent in currency subunits such as kobo, pesewas, or cents. Check the module docs for currency-specific rules.
Authentication & Environments
- Server-side SDKs should use your secret key (
sk_test_*orsk_live_*). - Browser SDKs should use only your public key (
pk_test_*orpk_live_*). - Send server-side API credentials as
Authorization: Bearer YOUR_SECRET_KEY. - Test and live modes use different keys and isolated environments.
- Rotate keys if they are exposed, and never commit secret keys to source control.
- If you enable IP whitelisting in Paystack, requests from non-whitelisted IPs will be blocked.
Reliability
This SDK includes opt-in helpers in Alexasomba\Paystack\Extras:
use Alexasomba\Paystack\Extras\HttpClientFactory; use Alexasomba\Paystack\Extras\Paystack; $config = Paystack::createConfiguration($_ENV['PAYSTACK_SECRET_KEY']); $client = HttpClientFactory::create([ 'timeoutSeconds' => 30, 'idempotency' => ['enabled' => true, 'auto' => true], ]);
Use the extras layer when you want one place to set timeout, retry, and idempotency defaults across your application.
Pagination
- Paystack supports both offset pagination and cursor pagination.
- Offset pagination uses
pageandperPage. - Cursor pagination uses
use_cursor=trueplusnextorpreviouscursors returned inmeta. - Cursor pagination is especially useful for large or frequently changing datasets.
- The exact
metashape varies by endpoint and pagination mode.
Coverage
Errors
- Paystack uses conventional HTTP status codes such as
200,201,400,401,404, and5xx. - Error responses typically include
status,message,type,code, and optional diagnosticmetainformation. - Error types described in
Paystack-API/0d-Errors.mdincludeapi_error,validation_error, andprocessor_error. - For charge and verify flows, always inspect the returned response body and status fields, not just the HTTP code.
This SDK is generated from the SDK spec in this monorepo and covers the operations emitted into the generated API classes under lib/Api.
Modules
For this SDK, these schema families are emitted as generated model classes under lib/Model and used by the API classes under lib/Api.
| Module | Schema / model family |
|---|---|
| Transactions | Transaction* |
| Verify Payments (Transaction verification) | VerifyResponse / TransactionFetchResponse |
| Charges | Charge* |
| Bulk Charges | BulkCharge* |
| Subaccounts | Subaccount* |
| Transaction Splits | Split* |
| Terminal | Terminal* |
| Virtual Terminal | VirtualTerminal* |
| Customers | Customer* |
| Direct Debit | DirectDebit* |
| Dedicated Virtual Accounts | DedicatedNuban* / DedicatedVirtualAccount* |
| Apple Pay | ApplePay* |
| Plans | Plan* |
| Subscriptions | Subscription* |
| Transfer Recipients | TransferRecipient* |
| Transfers | Transfer* |
| Transfers Control (OTP settings; under Transfers) | TransferEnable* / TransferDisable* / TransferFinalize* |
| Balance | Balance* |
| Payment Requests (Invoices) | PaymentRequest* |
| Verification (Resolve Account / Validate Account / Resolve Card BIN) | Verification* |
| Products | Product* |
| Storefronts | Storefront* |
| Orders | Order* |
| Payment Pages | Page* |
| Settlements | Settlement* |
| Integration | Integration* |
| Control Panel (Payment session timeout; under Integration) | ControlPanel* |
| Refunds | Refund* |
| Disputes | Dispute* |
| Banks | Bank* |
| Miscellaneous | Miscellaneous* / Currency |
Module Examples
These are intentionally short examples. Use them as entry points, then expand the generated model objects and API method arguments for your use case.
Transactions
$response = $transactionApi->transactionInitialize( new TransactionInitialize(['email' => 'customer@example.com', 'amount' => 5000]) );
Verify Payments (Transaction verification)
$verified = $transactionApi->transactionVerify('ref_123');
Charges
$chargeApi->chargeCreate(new ChargeCreateRequest(['email' => 'customer@example.com']));
Bulk Charges
$bulkChargeApi->bulkChargeInitiate([ new BulkChargeInitiate(['authorization' => 'AUTH_xxx', 'amount' => 5000, 'reference' => 'bulk-ref-1']), ]);
Subaccounts
$subaccountApi->subaccountCreate(new SubaccountCreate(['business_name' => 'Acme Stores']));
Transaction Splits
$splitApi->splitCreate(new SplitCreate(['name' => 'Main split', 'type' => 'percentage', 'currency' => 'NGN']));
Terminal
$terminals = $terminalApi->terminalList();
Virtual Terminal
$virtualTerminalApi->virtualTerminalCreate(new VirtualTerminalCreate(['name' => 'Web checkout terminal']));
Customers
$customerApi->customerCreate(new CustomerCreate(['email' => 'customer@example.com']));
Direct Debit
$directDebitApi->directdebitInitialize(new DirectDebitInitializeRequest(['email' => 'customer@example.com']));
Dedicated Virtual Accounts
$dedicatedVirtualAccountApi->dedicatedAccountAssign(new DedicatedVirtualAccountAssign(['customer' => 12345]));
Apple Pay
$applePayApi->applePayRegisterDomain(new ApplePayParam(['domain_name' => 'example.com']));
Plans
$planApi->planCreate(new PlanCreate(['name' => 'Starter', 'amount' => 500000, 'interval' => 'monthly']));
Subscriptions
$subscriptionApi->subscriptionCreate(new SubscriptionCreate(['customer' => 'CUS_xxx', 'plan' => 'PLN_xxx']));
Transfer Recipients
$transferRecipientApi->transferrecipientCreate(new TransferRecipientCreate(['name' => 'Ada Lovelace', 'type' => 'nuban']));
Transfers
$transferApi->transferCreate(new TransferInitiate(['source' => 'balance', 'amount' => 5000, 'recipient' => 'RCP_xxx']));
Transfers Control (OTP settings; under Transfers)
$transferApi->transferEnableOtp();
Balance
$balance = $balanceApi->balanceFetch();
Payment Requests (Invoices)
$paymentRequestApi->paymentRequestCreate(new PaymentRequestCreate(['amount' => 5000, 'description' => 'Consulting invoice']));
Verification (Resolve Account / Validate Account / Resolve Card BIN)
$resolved = $bankApi->bankResolveAccountNumber('0001234567', '057');
Products
$productApi->productCreate(new ProductCreate(['name' => 'T-shirt', 'price' => 5000, 'currency' => 'NGN']));
Storefronts
$storefronts = $storefrontApi->storefrontList();
Orders
$orderApi->orderCreate(new OrderCreate(['customer' => 'CUS_xxx']));
Payment Pages
$pageApi->pageCreate(new PageCreate(['name' => 'Event Ticket', 'amount' => 5000]));
Settlements
$settlements = $settlementApi->settlementList();
Integration
$timeout = $integrationApi->integrationFetchPaymentSessionTimeout();
Control Panel (Payment session timeout; under Integration)
$integrationApi->integrationUpdatePaymentSessionTimeout(20);
Refunds
$refundApi->refundCreate(new RefundCreate(['transaction' => 123456789, 'amount' => 5000]));
Disputes
$disputes = $disputeApi->disputeList();
Banks
$banks = $bankApi->bankList('nigeria');
Miscellaneous
$countries = $miscellaneousApi->miscellaneousListCountries();
Configuration Notes
The generated PHP client still exposes the standard OpenAPI Generator configuration surface. In most integrations, the main requirement is setting the bearer token and optionally swapping in a custom Guzzle client.
Related SDKs
- Node: alexasomba/paystack-node
- Axios: alexasomba/paystack-axios
- Browser: alexasomba/paystack-browser
- Go: alexasomba/paystack-go
- Python: alexasomba/paystack-python
Source
- Monorepo source: alexasomba/paystack-openapi
- Standalone SDK repo: https://github.com/alexasomba/paystack-php