130 lines
3.6 KiB
Markdown
130 lines
3.6 KiB
Markdown
# Billing Cooldown Runtime Checklist (Staging)
|
|
|
|
## Scope
|
|
Validate these behaviors end-to-end:
|
|
1. `pending_cooldown` lock on new checkout (120s)
|
|
2. Continue pending payment via `Pay` button
|
|
3. PayPal/Pakasir webhook delay handling
|
|
4. Auto-status transition from `pending` to `paid`
|
|
|
|
## Preconditions
|
|
1. Staging is deployed with latest billing changes.
|
|
2. Config is refreshed:
|
|
- `php artisan optimize:clear`
|
|
- `php artisan config:cache`
|
|
3. Env includes:
|
|
- `DEWEMOJI_CHECKOUT_PENDING_COOLDOWN=120`
|
|
4. Webhooks are configured and reachable:
|
|
- PayPal webhook endpoint
|
|
- Pakasir webhook endpoint
|
|
5. Test account available (verified email, logged in).
|
|
|
|
## Quick Observability
|
|
1. Browser devtools open (`Network` tab).
|
|
2. Keep Billing page open in another tab for status checks.
|
|
3. Optional server logs tail:
|
|
- `tail -f storage/logs/laravel.log`
|
|
|
|
## Test Matrix
|
|
|
|
### A. Cooldown Lock (PayPal)
|
|
1. Start Personal checkout in USD.
|
|
2. Before webhook settles, try starting another checkout from Pricing.
|
|
3. Expected:
|
|
- API returns `409` with `error: pending_cooldown`.
|
|
- UI shows wait message with countdown (`retry_after` seconds).
|
|
- Checkout CTA stays disabled until countdown reaches 0.
|
|
|
|
### B. Cooldown Lock (Pakasir)
|
|
1. Start Personal checkout in IDR (QRIS modal opens).
|
|
2. Close/cancel modal only if needed for this test case.
|
|
3. Immediately try another new checkout from Pricing.
|
|
4. Expected:
|
|
- API returns `409 pending_cooldown`.
|
|
- UI countdown appears and blocks new checkout.
|
|
|
|
### C. Continue Pending (PayPal)
|
|
1. Create a PayPal pending payment.
|
|
2. Go to `/dashboard/billing`.
|
|
3. Click `Pay` on pending row.
|
|
4. Expected:
|
|
- Redirect to PayPal approve URL.
|
|
- No new payment row created just for resume action.
|
|
|
|
### D. Continue Pending (Pakasir)
|
|
1. Create a Pakasir pending payment.
|
|
2. Go to `/dashboard/billing`.
|
|
3. Click `Pay` on pending row.
|
|
4. Expected:
|
|
- QR modal opens with amount + expiry.
|
|
- Polling runs and closes modal when status becomes paid.
|
|
|
|
### E. Webhook Delay UX
|
|
1. Complete payment at provider.
|
|
2. Observe app while webhook is delayed.
|
|
3. Expected:
|
|
- Status may remain `pending` briefly.
|
|
- User can continue pending (`Pay` button).
|
|
- After webhook/poll settles: status updates to `paid`.
|
|
|
|
### F. Pending Timeout to New Checkout
|
|
1. Keep a payment pending beyond cooldown (`>=120s`).
|
|
2. Try new checkout from Pricing.
|
|
3. Expected:
|
|
- New checkout is allowed again.
|
|
- Existing behavior for replacing/canceling pending remains intact.
|
|
|
|
### G. Edge Responses
|
|
1. Try `Pay` on a row that is no longer pending (race condition).
|
|
2. Expected:
|
|
- UI handles response (`payment_not_pending`) and refreshes state safely.
|
|
3. If pending QR is expired:
|
|
- Expected `payment_expired`, prompt to start new checkout.
|
|
|
|
## API Assertions (Network)
|
|
Check response payloads:
|
|
1. Cooldown block:
|
|
```json
|
|
{
|
|
"error": "pending_cooldown",
|
|
"retry_after": 87,
|
|
"pending_payment_id": 123,
|
|
"provider": "paypal"
|
|
}
|
|
```
|
|
2. Resume PayPal:
|
|
```json
|
|
{
|
|
"ok": true,
|
|
"mode": "redirect",
|
|
"approve_url": "https://..."
|
|
}
|
|
```
|
|
3. Resume Pakasir:
|
|
```json
|
|
{
|
|
"ok": true,
|
|
"mode": "qris",
|
|
"payment_number": "...",
|
|
"order_id": "DW-...",
|
|
"expired_at": "..."
|
|
}
|
|
```
|
|
|
|
## Pass/Fail Sheet
|
|
| Check | Result | Notes |
|
|
|---|---|---|
|
|
| A. PayPal cooldown lock | | |
|
|
| B. Pakasir cooldown lock | | |
|
|
| C. Resume pending PayPal | | |
|
|
| D. Resume pending Pakasir | | |
|
|
| E. Webhook delay UX | | |
|
|
| F. New checkout after cooldown | | |
|
|
| G. Edge response handling | | |
|
|
|
|
## Exit Criteria
|
|
Release-ready when:
|
|
1. All rows above are `PASS`.
|
|
2. No uncaught JS errors in console.
|
|
3. No unexpected 5xx in network log during flow.
|