diff --git a/src/app/subscription/page.tsx b/src/app/subscription/page.tsx index a6a87c44..6ccd066f 100644 --- a/src/app/subscription/page.tsx +++ b/src/app/subscription/page.tsx @@ -1,12 +1,32 @@ import { Suspense } from "react"; +import { MobileShell } from "@/app/_components/core"; + import { SubscriptionPageClient } from "./subscription-page-client"; -import { SubscriptionScreen } from "./subscription-screen"; export default function SubscriptionPage() { return ( - }> + }> ); } + +function SubscriptionFallback() { + return ( + +
+ Loading subscription... +
+
+ ); +} diff --git a/src/app/subscription/return/page.tsx b/src/app/subscription/return/page.tsx index 2f2bf3f0..e1a0f5b7 100644 --- a/src/app/subscription/return/page.tsx +++ b/src/app/subscription/return/page.tsx @@ -10,8 +10,11 @@ import { ROUTES } from "@/router/routes"; type ReturnStatus = "loading" | "missing"; function buildSubscriptionUrl(subscriptionType: "vip" | "voice"): string { - if (subscriptionType === "voice") return `${ROUTES.subscription}?type=voice`; - return `${ROUTES.subscription}?type=vip`; + const params = new URLSearchParams({ + type: subscriptionType, + paymentReturn: "1", + }); + return `${ROUTES.subscription}?${params.toString()}`; } export default function SubscriptionReturnPage() { diff --git a/src/app/subscription/subscription-page-client.tsx b/src/app/subscription/subscription-page-client.tsx index 4aab8c03..944406eb 100644 --- a/src/app/subscription/subscription-page-client.tsx +++ b/src/app/subscription/subscription-page-client.tsx @@ -14,6 +14,12 @@ function toSubscriptionType(value: string | null): SubscriptionType { export function SubscriptionPageClient() { const searchParams = useSearchParams(); const subscriptionType = toSubscriptionType(searchParams.get("type")); + const shouldResumePendingOrder = searchParams.get("paymentReturn") === "1"; - return ; + return ( + + ); } diff --git a/src/app/subscription/subscription-screen.tsx b/src/app/subscription/subscription-screen.tsx index 4fe084d1..e5db9782 100644 --- a/src/app/subscription/subscription-screen.tsx +++ b/src/app/subscription/subscription-screen.tsx @@ -113,10 +113,12 @@ function toPlanView( export interface SubscriptionScreenProps { subscriptionType?: SubscriptionType; + shouldResumePendingOrder?: boolean; } export function SubscriptionScreen({ subscriptionType = "vip", + shouldResumePendingOrder = false, }: SubscriptionScreenProps) { const user = useUserState(); const userDispatch = useUserDispatch(); @@ -139,15 +141,31 @@ export function SubscriptionScreen({ }, [payment.currentOrderId, payment.isPaid, userDispatch]); useEffect(() => { - if (payment.status !== "ready") return; + const canInspectPendingOrder = + payment.status === "ready" || + (!shouldResumePendingOrder && + (payment.isPollingOrder || payment.isPaid || payment.status === "failed")); + if (!canInspectPendingOrder) return; let cancelled = false; - const resumePendingOrder = async () => { + const handlePendingOrder = async () => { const result = await PendingPaymentOrderStorage.getPendingOrderForType( subscriptionType, ); if (cancelled || !result.success || result.data === null) return; + + if (!shouldResumePendingOrder) { + await PendingPaymentOrderStorage.clearPendingOrder(); + if ( + payment.currentOrderId === result.data.orderId && + (payment.isPollingOrder || payment.isPaid || payment.status === "failed") + ) { + paymentDispatch({ type: "PaymentReset" }); + } + return; + } + if (payment.currentOrderId === result.data.orderId) return; if (resumedPendingOrderRef.current === result.data.orderId) return; @@ -158,11 +176,19 @@ export function SubscriptionScreen({ }); }; - void resumePendingOrder(); + void handlePendingOrder(); return () => { cancelled = true; }; - }, [payment.currentOrderId, payment.status, paymentDispatch, subscriptionType]); + }, [ + payment.currentOrderId, + payment.isPaid, + payment.isPollingOrder, + payment.status, + paymentDispatch, + shouldResumePendingOrder, + subscriptionType, + ]); useEffect(() => { if (!payment.currentOrderId) return;