Paystack Payment Integration - Test Guide
Overview
The platform now supports Paystack payments for wallet funding. Users can fund their wallets using Paystack's inline widget or redirect method.
Environment Variables Required
PAYSTACK_SECRET_KEY=sk_test_... # Your Paystack secret key
PAYSTACK_PUBLIC_KEY=pk_test_... # Your Paystack public key
PAYSTACK_CALLBACK_URL=http://localhost:3000/payment/callback # Optional
FRONTEND_URL=http://localhost:3000 # Optional, for callback URL fallback
POINT_VALUE_USD=0.05 # 1 point = $0.05
NGN_PER_USD=750 # Exchange rate (adjust as needed)
API Endpoints
1. Initialize Payment (Fund Wallet)
POST /api/wallet/fund
Headers:
Authorization: Bearer <user_token>
Content-Type: application/json
Request Body:
{
"amount": 1000 // Amount in Naira (NGN)
}
Response:
{
"publicKey": "pk_test_...",
"reference": "wallet_...",
"authorization_url": "https://checkout.paystack.com/...",
"access_code": "...",
"payment": {
"reference": "wallet_...",
"amount": 1000,
"currency": "NGN",
"points": 26,
"amountInDollars": "1.33"
},
"message": "Use authorization_url to redirect or use Paystack inline widget with access_code"
}
2. Verify Transaction (Manual Verification)
GET /api/wallet/verify/:reference
Headers:
Authorization: Bearer <user_token>
Response:
{
"success": true,
"message": "Payment verified and points added",
"transaction": {
"id": "...",
"type": "purchase",
"amount": 26,
"balanceAfter": 26
},
"wallet": {
"balance": 26,
"balanceInDollars": 1.3
}
}
3. Webhook (Paystack β Server)
POST /api/wallet/webhook/paystack
Headers:
x-paystack-signature: <hmac_sha512_signature>
Note: This is called automatically by Paystack. No authentication needed (uses signature verification).
Frontend Integration Examples
Option 1: Using Paystack Inline Widget (Recommended)
<script src="https://js.paystack.co/v1/inline.js"></script>
// After calling POST /api/wallet/fund
async function fundWallet(amountInNaira) {
const response = await fetch('/api/wallet/fund', {
method: 'POST',
headers: {
'Authorization': `Bearer ${userToken}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({ amount: amountInNaira })
});
const data = await response.json();
// Use Paystack inline widget
const handler = PaystackPop.setup({
key: data.publicKey,
email: userEmail,
amount: data.payment.amount * 100, // Convert to kobo
ref: data.reference,
metadata: {
custom_fields: [
{
display_name: 'User ID',
variable_name: 'userId',
value: userId
}
]
},
onClose: function() {
// Handle payment cancellation
console.log('Payment cancelled');
},
callback: function(response) {
// Verify payment
verifyPayment(response.reference);
}
});
handler.openIframe();
}
async function verifyPayment(reference) {
const response = await fetch(`/api/wallet/verify/${reference}`, {
method: 'GET',
headers: {
'Authorization': `Bearer ${userToken}`
}
});
const result = await response.json();
if (result.success) {
console.log('Payment successful!', result);
// Update wallet balance in UI
updateWalletBalance(result.wallet.balance);
}
}
Option 2: Using Redirect URL
async function fundWalletRedirect(amountInNaira) {
const response = await fetch('/api/wallet/fund', {
method: 'POST',
headers: {
'Authorization': `Bearer ${userToken}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({ amount: amountInNaira })
});
const data = await response.json();
// Redirect to Paystack checkout
window.location.href = data.authorization_url;
}
// On callback page (after redirect)
const urlParams = new URLSearchParams(window.location.search);
const reference = urlParams.get('reference');
if (reference) {
verifyPayment(reference);
}
Testing
Test Mode
Use Paystack test keys:
- Public Key:
pk_test_... - Secret Key:
sk_test_...
Test Cards
- Success:
4084084084084081 - Decline:
5060666666666666666 - Insufficient Funds:
5078607857785078
Test Flow
- Call
POST /api/wallet/fundwith amount (e.g., 1000 NGN) - Use the returned
publicKeyandreferencein Paystack widget - Complete payment with test card
- Call
GET /api/wallet/verify/:referenceto verify and credit wallet - Check wallet balance:
GET /api/wallet
Notes
- Idempotency: The system checks for duplicate transactions by reference. Calling verify multiple times won't double-credit.
- Webhook: Paystack automatically calls the webhook endpoint. Both webhook and manual verification work independently.
- Currency: Amounts are in Naira (NGN). The system converts to points automatically.
- Points Calculation: Points = (NGN / NGN_PER_USD) / POINT_VALUE_USD