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