File size: 6,124 Bytes
4a285d2 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 |
# Paystack Payment Callback Guide
## Overview
The platform now has a complete callback system for handling Paystack payment redirects. This includes both backend processing and frontend display.
## Callback Flow
### 1. Backend Callback Endpoint
**GET** `/api/wallet/callback`
This is a **public endpoint** (no authentication required) that Paystack redirects to after payment. It:
- Receives the payment reference from Paystack query parameters
- Verifies the transaction with Paystack API
- Credits the user's wallet if successful
- Redirects to frontend success/failure page
**Query Parameters (from Paystack):**
- `reference` or `trxref` - Payment reference
**Redirects:**
- Success: `${FRONTEND_URL}/payment/success?reference=...&points=...&balance=...`
- Failure: `${FRONTEND_URL}/payment/failed?error=...&reference=...`
### 2. Frontend Callback Pages
#### Success Page (`/payment/success`)
**Query Parameters:**
- `reference` - Payment reference
- `points` - Points added to wallet
- `balance` - New wallet balance
- `amount` - Amount paid in Naira
- `already_processed` - If payment was already processed
#### Failure Page (`/payment/failed`)
**Query Parameters:**
- `error` - Error message
- `reference` - Payment reference
- `status` - Payment status from Paystack
- `message` - Gateway response message
### 3. Static HTML Callback Page
A fallback callback page is available at `/public/payment-callback.html` that:
- Shows a loading spinner while processing
- Displays success or error messages
- Shows payment details (reference, points, balance)
- Provides links to navigate back to wallet or retry
## Configuration
### Environment Variables
```env
# Backend URL (where Paystack redirects to)
BACKEND_URL=http://localhost:3000
# Frontend URL (where users are redirected after processing)
FRONTEND_URL=http://localhost:3000
# Optional: Custom callback URL (overrides default)
PAYSTACK_CALLBACK_URL=http://localhost:3000/api/wallet/callback
```
### Paystack Dashboard Setup
#### Webhook Configuration (Required)
1. Go to Settings β API Keys & Webhooks
2. Add webhook URL: `https://yourdomain.com/api/wallet/webhook/paystack`
3. Select events: `charge.success` (required)
4. Save configuration
See [WEBHOOK_SETUP.md](./WEBHOOK_SETUP.md) for detailed webhook setup instructions.
#### Callback URL (Optional)
The callback URL is automatically set when initializing payments. You can override it with:
- Environment variable: `PAYSTACK_CALLBACK_URL`
- Default: `${BACKEND_URL}/api/wallet/callback`
## Callback Scenarios
### Scenario 1: Successful Payment (First Time)
1. User completes payment on Paystack
2. Paystack redirects to `/api/wallet/callback?reference=wallet_...`
3. Backend verifies payment with Paystack API
4. Backend credits wallet
5. Backend redirects to frontend success page with details
### Scenario 2: Successful Payment (Already Processed)
1. User completes payment on Paystack
2. Paystack redirects to `/api/wallet/callback?reference=wallet_...`
3. Backend checks for existing transaction (idempotency)
4. If already processed, redirects to success page with `already_processed=true`
5. No duplicate credit occurs
### Scenario 3: Failed Payment
1. User attempts payment on Paystack
2. Payment fails or is abandoned
3. Paystack redirects to `/api/wallet/callback?reference=...`
4. Backend verifies and finds status != 'success'
5. Backend redirects to frontend failure page with error details
### Scenario 4: Webhook Processing (Parallel)
1. Paystack sends webhook to `/api/wallet/webhook/paystack`
2. Webhook handler verifies signature and processes payment
3. This happens independently of redirect callback
4. Both webhook and callback are idempotent (no double-crediting)
## Frontend Integration
### Option 1: Use Backend Redirect (Recommended)
```javascript
// When initializing payment
const response = await fetch('/api/wallet/fund', {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({ amount: 1000 })
});
const data = await response.json();
// Redirect to Paystack
window.location.href = data.authorization_url;
// Backend callback will handle redirect to your success/failure pages
```
### Option 2: Use Inline Widget + Manual Verification
```javascript
// Use Paystack inline widget
const handler = PaystackPop.setup({
key: data.publicKey,
email: userEmail,
amount: data.payment.amount * 100,
ref: data.reference,
callback: function(response) {
// Verify payment manually
verifyPayment(response.reference);
}
});
async function verifyPayment(reference) {
const response = await fetch(`/api/wallet/verify/${reference}`, {
headers: {
'Authorization': `Bearer ${token}`
}
});
const result = await response.json();
if (result.success) {
// Redirect to success page
window.location.href = `/payment/success?reference=${reference}&points=${result.transaction.amount}&balance=${result.wallet.balance}`;
}
}
```
## Testing
### Test Callback Flow
1. Start server: `npm run dev`
2. Initialize payment: `POST /api/wallet/fund`
3. Use test card: `4084084084084081`
4. After payment, Paystack redirects to callback
5. Check redirect URL for success/failure parameters
### Test with cURL
```bash
# Simulate callback (after payment)
curl "http://localhost:3000/api/wallet/callback?reference=wallet_test_123"
```
## Security Considerations
1. **Public Endpoint**: The callback endpoint is public (no auth) because Paystack redirects to it
2. **Verification**: Always verify with Paystack API (never trust redirect parameters)
3. **Idempotency**: Both callback and webhook check for existing transactions
4. **Signature Verification**: Webhook uses HMAC signature verification
5. **Error Handling**: All errors redirect to frontend with safe error messages
## Error Handling
The callback handler catches all errors and redirects to the failure page with:
- Error message (URL encoded)
- Reference (if available)
- Status (if available)
Frontend should display these safely and allow users to retry or contact support.
|