mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-26 18:42:49 +00:00
fix( dmoney ): make D-Money /go redirect
This commit is contained in:
@@ -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 (
|
||||
<div className="w-full max-w-sm text-center">
|
||||
<div className="mx-auto mb-5 flex h-16 w-16 items-center justify-center rounded-full bg-red-100">
|
||||
<ShieldAlert className="h-8 w-8 text-red-600" />
|
||||
</div>
|
||||
<h1 className="mb-2 text-xl font-bold text-gray-900">
|
||||
Can't continue
|
||||
</h1>
|
||||
<p className="text-sm text-gray-500">
|
||||
This link is missing a valid D-Money checkout address or points to an
|
||||
untrusted destination. Please start the payment again from the app.
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="w-full max-w-sm text-center">
|
||||
<div className="mx-auto mb-5 flex h-16 w-16 items-center justify-center rounded-full bg-primary/10">
|
||||
<Loader2 className="h-8 w-8 animate-spin text-primary" />
|
||||
</div>
|
||||
<h1 className="mb-2 text-xl font-bold text-gray-900">
|
||||
Redirecting to D-Money
|
||||
</h1>
|
||||
<p className="text-sm text-gray-500">
|
||||
Taking you to the secure D-Money checkout to complete your payment…
|
||||
</p>
|
||||
|
||||
<a
|
||||
href={target}
|
||||
className="mt-6 inline-flex items-center justify-center gap-2 text-sm font-medium text-primary hover:underline"
|
||||
>
|
||||
Continue to D-Money
|
||||
<ExternalLink className="h-4 w-4" />
|
||||
</a>
|
||||
<div className="fixed inset-0 z-[100] flex items-center justify-center bg-white px-6 text-center">
|
||||
{!target && (
|
||||
<p className="text-sm text-gray-500">
|
||||
This payment link is invalid or has expired. Please start the payment
|
||||
again from the app.
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default function GoPage() {
|
||||
return (
|
||||
<div className="fixed inset-0 z-50 flex items-center justify-center bg-white px-4">
|
||||
<Suspense
|
||||
fallback={
|
||||
<Loader2 className="h-8 w-8 animate-spin text-primary" aria-label="Loading" />
|
||||
}
|
||||
>
|
||||
<RedirectView />
|
||||
</Suspense>
|
||||
</div>
|
||||
<Suspense fallback={<div className="fixed inset-0 z-[100] bg-white" />}>
|
||||
<RedirectView />
|
||||
</Suspense>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user