diff --git a/apps/edr-passenger-web/portal/src/app/go/page.tsx b/apps/edr-passenger-web/portal/src/app/go/page.tsx index 255b3980a..d9f6f583f 100644 --- a/apps/edr-passenger-web/portal/src/app/go/page.tsx +++ b/apps/edr-passenger-web/portal/src/app/go/page.tsx @@ -2,9 +2,25 @@ import { Suspense, useEffect, useMemo } from "react"; import { useSearchParams } from "next/navigation"; -import { Loader2, ShieldAlert, ExternalLink } from "lucide-react"; - +/** + * /go — payment redirect bounce page for D-Money web checkout. + * + * The redirect is done CLIENT-SIDE on purpose: the navigation must originate + * from the loaded https://edrpassenger.triaplc.com/go document so the browser + * sends `Referer: https://edrpassenger.triaplc.com` to D-Money. D-Money only + * whitelists that origin, so a server-side 307 (whose referrer on the redirect + * hop is browser-dependent and can be stripped) must NOT be used here. + * + * It fires immediately (no delay) and paints a bare white full-screen cover + * above the sticky header (z-[60]) — no portal chrome, no text on the happy + * path. A short message shows only when the link is missing/untrusted. + * + * `?url=` MUST be percent-encoded by the caller (Uri.encodeComponent() in the + * Flutter app / encodeURIComponent() on web); otherwise the query parser + * truncates the D-Money URL at its first `&` and merch_code/sign are lost. + * See scripts/test-go-redirect.mjs. + */ const ALLOWED_HOSTS = ( process.env.NEXT_PUBLIC_DMONEY_ALLOWED_HOSTS ?? "d-money.dj" @@ -29,8 +45,6 @@ function isTrustedDMoneyUrl(raw: string | null): raw is string { ); } -const REDIRECT_DELAY_MS = 1000; - function RedirectView() { const searchParams = useSearchParams(); const raw = searchParams.get("url"); @@ -38,63 +52,27 @@ function RedirectView() { useEffect(() => { if (!target) return; - const timer = setTimeout(() => { - - window.location.replace(target); - }, REDIRECT_DELAY_MS); - return () => clearTimeout(timer); + // Navigate from this document so the D-Money request carries + // Referer: https://edrpassenger.triaplc.com (the origin D-Money whitelists). + window.location.replace(target); }, [target]); - if (!target) { - return ( -
-
- -
-

- Can't continue -

-

- This link is missing a valid D-Money checkout address or points to an - untrusted destination. Please start the payment again from the app. -

-
- ); - } - return ( -
-
- -
-

- Redirecting to D-Money -

-

- Taking you to the secure D-Money checkout to complete your payment… -

- - - Continue to D-Money - - +
+ {!target && ( +

+ This payment link is invalid or has expired. Please start the payment + again from the app. +

+ )}
); } export default function GoPage() { return ( -
- - } - > - - -
+ }> + + ); }