Files
tiennm99 17491f47f4 feat: SePay VietQR demo playground
SvelteKit 2 + Svelte 5 runes + JS + pnpm + Tailwind v4 (CSS-first @theme) + hand-rolled components (skipped shadcn-svelte after interactive CLI block — brainstormer-approved fallback) + @upstash/redis + adapter-vercel (nodejs20.x runtime).

Server: createOrder mints `${PREFIX}${6 alphanum}` with NX-retry on collision; markPaid preserves TTL via keepTtl; webhook dedup via SET NX (7d ex on payload.id). Auth: case-insensitive scheme parse + timingSafeEqual on key bytes. Code extraction prefers payload.code, falls back to regex on payload.content.

UI: /pay is a single route with view derived from order.status. Awaiting screen: $effect-owned polling with AbortController + immediate first fetch (handles webhook-before-poll race) + 15-min countdown + reduced-motion respect. Dev simulator double-gated on `dev` flag AND `DEV_SIMULATE_TOKEN` header so it stays inert on Vercel preview URLs.

Plan + brainstormer red-team notes preserved under plans/.
2026-05-24 15:24:15 +07:00
..
2026-05-24 15:24:15 +07:00