-
Notifications
You must be signed in to change notification settings - Fork 3
GETTING_STARTED.md
A beginner-friendly guide to installing and using PayZephyr in your Laravel application.
- ✅ Complete beginners to payment processing
- ✅ Developers new to Laravel packages
- ✅ Anyone setting up PayZephyr for the first time
- ✅ Developers who want a step-by-step walkthrough
Before you start, make sure you have:
-
PHP 8.2 or higher installed
php -v # Should show 8.2.0 or higher -
Composer installed
composer --version # Should show Composer version -
Laravel 10.x, 11.x, or 12.x project
php artisan --version # Should show Laravel version -
A payment provider account (at least one):
Open your terminal in your Laravel project directory and run:
composer require kendenigerian/payzephyrWhat this does: Downloads and installs the PayZephyr package into your Laravel project.
Expected output:
Using version ^1.0 for kendenigerian/payzephyr
...
Package manifest generated successfully.
php artisan payzephyr:installWhat this does: This command automatically:
- Publishes the configuration file (
config/payments.php) - Publishes migration files
- Optionally runs migrations (you'll be prompted)
Expected output:
Installing PayZephyr...
✓ Configuration file published
✓ Migration files published
Run migrations now? (yes/no) [yes]:
> yes
Running migrations...
2024_01_01_000000_create_payment_transactions_table .......... DONE
✓ Migrations completed
PayZephyr installed successfully!
Please configure your providers in .env
Example environment variables:
PAYMENTS_DEFAULT_PROVIDER=paystack
PAYSTACK_SECRET_KEY=your_secret_key
PAYSTACK_PUBLIC_KEY=your_public_key
💡 Tip: If you want to overwrite existing files, use the --force flag:
php artisan payzephyr:install --force- Your database is configured in
.env - Database connection is working (
php artisan migrate:status)
💡 Alternative Manual Setup: If you prefer to set up manually:
php artisan vendor:publish --tag=payments-config php artisan vendor:publish --tag=payments-migrations php artisan migrate
- Go to https://paystack.com
- Sign up for an account
- Go to Settings → API Keys & Webhooks
- Copy your Test Secret Key (starts with
sk_test_) - Copy your Test Public Key (starts with
pk_test_)
💡 Tip: Use test keys first! Only use live keys when you're ready for production.
- Go to https://stripe.com
- Sign up and go to Developers → API Keys
- Copy your Test Secret Key (starts with
sk_test_) - Copy your Test Publishable Key (starts with
pk_test_)
Open your .env file and add your credentials:
# Default Payment Provider (use 'paystack' for beginners)
PAYMENTS_DEFAULT_PROVIDER=paystack
# Paystack Configuration (Required: secret_key, public_key)
PAYSTACK_SECRET_KEY=sk_test_your_secret_key_here
PAYSTACK_PUBLIC_KEY=pk_test_your_public_key_here
PAYSTACK_CALLBACK_URL=http://localhost:8000/payment/callback
PAYSTACK_ENABLED=true- Never commit your
.envfile to Git - Replace
your_secret_key_herewith your actual key - Use test keys during development
php artisan config:clearWhat this does: Makes sure Laravel reads your new .env values.
Let's create a simple payment page from scratch!
Open routes/web.php and add:
use Illuminate\Support\Facades\Route;
use KenDeNigerian\PayZephyr\Facades\Payment;
// Payment page
Route::get('/payment', function () {
return view('payment');
})->name('payment.page');
// Process payment
Route::post('/payment/process', function () {
$request = request();
return Payment::amount(10000) // ₦100.00 (in kobo)
->email($request->email)
->currency('NGN')
->description('Test Payment')
->callback(route('payment.callback'))
->redirect();
})->name('payment.process');
// Payment callback (after customer pays)
Route::get('/payment/callback', function () {
$reference = request()->input('reference');
if (!$reference) {
return redirect()->route('payment.page')
->with('error', 'No payment reference found');
}
try {
$verification = Payment::verify($reference);
if ($verification->isSuccessful()) {
return redirect()->route('payment.page')
->with('success', 'Payment successful! Amount: ₦' . $verification->amount);
}
return redirect()->route('payment.page')
->with('error', 'Payment failed or is pending');
} catch (\Exception $e) {
return redirect()->route('payment.page')
->with('error', 'Error verifying payment: ' . $e->getMessage());
}
})->name('payment.callback');Create resources/views/payment.blade.php:
<!DOCTYPE html>
<html>
<head>
<title>Payment Test</title>
<style>
body { font-family: Arial, sans-serif; max-width: 600px; margin: 50px auto; padding: 20px; }
.form-group { margin-bottom: 15px; }
label { display: block; margin-bottom: 5px; font-weight: bold; }
input { width: 100%; padding: 10px; border: 1px solid #ddd; border-radius: 4px; }
button { background: #007bff; color: white; padding: 12px 24px; border: none; border-radius: 4px; cursor: pointer; }
button:hover { background: #0056b3; }
.alert { padding: 15px; margin-bottom: 20px; border-radius: 4px; }
.alert-success { background: #d4edda; color: #155724; border: 1px solid #c3e6cb; }
.alert-error { background: #f8d7da; color: #721c24; border: 1px solid #f5c6cb; }
</style>
</head>
<body>
<h1>💳 Test Payment</h1>
@if(session('success'))
<div class="alert alert-success">
✅ {{ session('success') }}
</div>
@endif
@if(session('error'))
<div class="alert alert-error">
❌ {{ session('error') }}
</div>
@endif
<form method="POST" action="{{ route('payment.process') }}">
@csrf
<div class="form-group">
<label for="email">Email Address *</label>
<input
type="email"
id="email"
name="email"
value="{{ old('email', 'test@example.com') }}"
required
placeholder="customer@example.com"
>
</div>
<div class="form-group">
<label>Amount</label>
<input type="text" value="₦100.00" disabled>
<small style="color: #666;">This is a test payment of ₦100.00</small>
</div>
<button type="submit">Pay Now</button>
</form>
<hr style="margin: 30px 0;">
<h3>📚 What Happens Next?</h3>
<ol>
<li>Click "Pay Now" button</li>
<li>You'll be redirected to Paystack's secure payment page</li>
<li>Use test card: <code>4084084084084081</code> (any future expiry, any CVV)</li>
<li>Complete the payment</li>
<li>You'll be redirected back to see the result</li>
</ol>
<h3>🧪 Test Cards</h3>
<p>For Paystack test mode, use:</p>
<ul>
<li><strong>Card:</strong> 4084084084084081</li>
<li><strong>Expiry:</strong> Any future date (e.g., 12/25)</li>
<li><strong>CVV:</strong> Any 3 digits (e.g., 123)</li>
<li><strong>PIN:</strong> Any 4 digits (e.g., 0000)</li>
</ul>
</body>
</html>-
Start your Laravel server:
php artisan serve
-
Open your browser:
http://localhost:8000/payment -
Enter an email and click "Pay Now"
-
You'll be redirected to Paystack's payment page
-
Use the test card details shown on the page
-
Complete the payment
-
You'll be redirected back to see the result!
🎉 Congratulations! You just processed your first payment!
Let's break down what each part does:
Payment::amount(10000) // Amount in smallest currency unit (kobo for NGN)
->email($request->email) // Customer email (required)
->currency('NGN') // Currency code
->description('Test Payment') // What the payment is for
->callback(route('payment.callback')) // Where to return after payment
->redirect(); // Execute and redirect to payment pageWhat happens:
-
amount(10000)= ₦100.00 (10000 kobo) -
email()= Customer's email address -
currency('NGN')= Nigerian Naira -
callback()= URL to return to after payment -
redirect()= Sends user to payment provider's checkout page
$verification = Payment::verify($reference);
if ($verification->isSuccessful()) {
// Payment succeeded!
}What happens:
-
verify($reference)= Checks payment status with provider -
isSuccessful()= Returns true if payment succeeded - You can then update your database, send emails, etc.
Error:
DriverNotFoundException: Payment driver [paystack] not found or disabled
Solution:
- Check
.envhasPAYSTACK_ENABLED=true - Check
.envhasPAYSTACK_SECRET_KEY=... - Run
php artisan config:clear - Check
config/payments.phpexists
Error:
InvalidConfigurationException: Paystack secret key is required
Solution:
- Make sure you copied the full key (including
sk_test_prefix) - Check for extra spaces in
.env - Don't use quotes around the key in
.env - Run
php artisan config:clear
Error: Blank page or redirect loop
Solution:
- Check Laravel logs:
storage/logs/laravel.log - Make sure you're using test keys (not live keys)
- Check callback URL is accessible
- Verify provider is enabled in config
Error:
SQLSTATE[42S02]: Base table or view not found: payment_transactions
Solution:
- Run migrations:
php artisan migrate - Check database connection in
.env - Verify database exists
Now that you've made your first payment:
-
Set Up Queue Workers (CRITICAL for Webhooks!)
- Webhooks are processed asynchronously via Laravel's queue system
- You MUST run queue workers for webhooks to be processed
- See Queue Worker Setup for complete instructions
- Quick start for local development:
# In your .env, set: QUEUE_CONNECTION=sync # For immediate processing (development) # Or for production: QUEUE_CONNECTION=database php artisan queue:table php artisan migrate php artisan queue:work
-
Learn About Webhooks
- Webhook Guide
- Webhooks are more reliable than callbacks
- Remember: Queue workers must be running for webhooks to work!
-
Read the Full Documentation
-
Explore Advanced Features
- Multiple providers with fallback
- Custom metadata
- Transaction logging
-
Production Checklist
- Switch to live API keys
- Enable webhook signature verification
- Set up proper error handling
- Set up queue workers (Supervisor or Systemd)
- Always test first - Use test/sandbox keys before going live
- Start simple - Get basic payments working before adding complexity
- Read error messages - They usually tell you exactly what's wrong
-
Check logs -
storage/logs/laravel.loghas detailed error information - Use one provider first - Master Paystack before adding others
- 📧 Email: ken.de.nigerian@payzephyr.dev
- 🐛 GitHub Issues: Report a bug
- 💬 Discussions: Ask questions
- 📖 Documentation: Full docs
Happy Coding! 🚀