Files
dewemoji/billing-cooldown-runtime-checklist.md

3.6 KiB

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:
{
  "error": "pending_cooldown",
  "retry_after": 87,
  "pending_payment_id": 123,
  "provider": "paypal"
}
  1. Resume PayPal:
{
  "ok": true,
  "mode": "redirect",
  "approve_url": "https://..."
}
  1. 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:

  1. All rows above are PASS.
  2. No uncaught JS errors in console.
  3. No unexpected 5xx in network log during flow.