PayZephyr is a Laravel package that makes accepting payments simple. Instead of writing different code for each payment provider (Paystack, Stripe, PayPal, etc.), you write code once and PayZephyr handles the rest.
Features
See Provider Details for currency and channel support.
New to PayZephyr? Check out our Getting Started Guide.
# 1. Install the package
composer require kendenigerian/payzephyr
# 2. Run the install command (publishes config, migrations, and optionally runs migrations)
php artisan payzephyr:install
# 3. Configure your environment variables (see below)
That's it! You're ready to start accepting payments.
Alternative: Manual setup:
php artisan vendor:publish --tag=payments-config php artisan vendor:publish --tag=payments-migrations php artisan migrate
Add provider credentials to .env:
PAYMENTS_DEFAULT_PROVIDER=paystack
PAYSTACK_SECRET_KEY=sk_test_xxxxx
PAYSTACK_PUBLIC_KEY=pk_test_xxxxx
PAYSTACK_ENABLED=true
See Configuration Guide for all options.
What happens: Customer clicks "Pay" → Redirected to payment page → Returns to your site → You verify payment
use KenDeNigerian\PayZephyr\Facades\Payment;
// Basic payment (amount in major currency unit: 100.00 = ₦100.00 for NGN)
return Payment::amount(100.00)
->email('customer@example.com')
->callback(route('payment.callback')) // Where to return after payment
->redirect(); // Sends customer to payment page
// With more options (including idempotency for retry safety)
return Payment::amount(500.00) // ₦500.00
->currency('NGN')
->email('customer@example.com')
->callback(route('payment.callback'))
->reference('ORDER_123') // Your order ID
->description('Premium subscription')
->metadata(['order_id' => 12345]) // Custom data
->idempotency('unique-key-123') // Prevents duplicate charges on retries
->with('paystack') // Optional: force specific provider
->redirect();
After customer returns from payment page:
public function callback(Request $request)
{
// Get payment reference from URL
$verification = Payment::verify($request->input('reference'));
if ($verification->isSuccessful()) {
// Payment succeeded - update your database
Order::where('payment_reference', $verification->reference)
->update(['status' => 'paid']);
return view('payment.success');
}
// Payment failed
return view('payment.failed');
}
Queue workers required. Configure webhook URLs in provider dashboards:
https://yourdomain.com/payments/webhook/paystackhttps://yourdomain.com/payments/webhook/stripe// app/Providers/EventServiceProvider.php
protected $listen = [
'payments.webhook.paystack' => [
\App\Listeners\HandlePaystackWebhook::class,
],
];
// app/Listeners/HandlePaystackWebhook.php
public function handle(array $payload): void
{
if ($payload['event'] === 'charge.success') {
Order::where('payment_reference', $payload['data']['reference'])
->update(['status' => 'paid']);
}
}
See Webhook Guide for complete setup.
Currently, only PaystackDriver supports subscriptions. Support for other providers will be added in future releases.
PayZephyr provides enterprise-grade subscription management with automatic transaction logging, idempotency support, lifecycle events, business validation, and comprehensive state management. All subscription operations are automatically logged to the database for audit and analytics.
use KenDeNigerian\PayZephyr\Facades\Payment;
use KenDeNigerian\PayZephyr\DataObjects\SubscriptionPlanDTO;
// Create a subscription plan (using facade)
$planDTO = new SubscriptionPlanDTO(
name: 'Monthly Premium',
amount: 5000.00, // ₦5,000.00
interval: 'monthly',
currency: 'NGN',
);
$plan = Payment::subscription()
->planData($planDTO)
->with('paystack') // Currently only PaystackDriver supports subscriptions
->createPlan();
// Create a subscription with idempotency (prevents duplicates on retries)
$subscription = payment()->subscription()
->customer('customer@example.com')
->plan($plan['plan_code'])
->idempotency() // Auto-generates UUID, or pass custom key
->with('paystack')
->subscribe(); // Final action method (create() is also available as an alias)
// Query subscriptions using query builder
$activeSubscriptions = Payment::subscriptions()
->forCustomer('customer@example.com')
->active()
->from('paystack')
->get();
// Subscription automatically logged to subscription_transactions table
// Access logged subscription:
use KenDeNigerian\PayZephyr\Models\SubscriptionTransaction;
$logged = SubscriptionTransaction::where('subscription_code', $subscription->subscriptionCode)->first();
// Save subscription details to your own table
DB::table('subscriptions')->insert([
'subscription_code' => $subscription->subscriptionCode,
'email_token' => $subscription->emailToken, // Important for cancel/enable
'status' => $subscription->status,
]);
Key Features:
Payment::subscriptions()->forCustomer()->active()->get()📖 See Subscriptions Guide for complete documentation
👨💻 Developers: Want to add subscription support for a new driver? See the Developer Guide.
All payment and subscription transactions are automatically logged:
use KenDeNigerian\PayZephyr\Models\PaymentTransaction;
use KenDeNigerian\PayZephyr\Models\SubscriptionTransaction;
// Payment transactions
PaymentTransaction::where('reference', 'ORDER_123')->first();
PaymentTransaction::successful()->get();
PaymentTransaction::failed()->get();
// Subscription transactions (automatically logged on create/update/cancel)
SubscriptionTransaction::where('subscription_code', 'SUB_xyz')->first();
SubscriptionTransaction::active()->get();
SubscriptionTransaction::forCustomer('user@example.com')->get();
SubscriptionTransaction::forPlan('PLN_abc123')->get();
Use sandbox credentials for testing:
PAYSTACK_SECRET_KEY=sk_test_xxxxx
PAYSTACK_PUBLIC_KEY=pk_test_xxxxx
See Testing Guide for examples.
// Fallback providers
Payment::amount(100.00)
->with(['paystack', 'stripe'])
->redirect();
// API-only mode (no redirect)
$response = Payment::amount(100.00)->charge();
return response()->json($response);
// Direct driver access
$driver = app(PaymentManager::class)->driver('paystack');
$driver->healthCheck();
See Architecture Guide for advanced patterns.
Webhooks not processing? Ensure queue workers are running:
php artisan queue:work
Provider not found? Check .env:
PAYSTACK_ENABLED=true
PAYSTACK_SECRET_KEY=sk_test_xxxxx
Health check endpoint: GET /payments/health - Monitor provider availability
See Troubleshooting Guide for more.
Contributions welcome! See Contributing Guide.
See CHANGELOG.md for version history.
Latest: v1.8.0 - Major subscription enhancements with enterprise-grade features
v1.8.0 Highlights:
See Changelog for complete release notes.
The MIT License (MIT). Please see LICENSE for more information.
If PayZephyr helped your project:
Built for the Laravel community by Ken De Nigerian
How can I help you explore Laravel packages today?