-
-
Payment unavailable
-
- Stripe publishable key is not configured for this build.
-
-
-
-
+ if (!stripePromise) {
+ return (
+
+
+
+
Payment unavailable
+
+ Stripe publishable key is not configured for this build.
+
+
+
+
+
-
- ) : (
+ );
+ }
+
+ return (
);
-
- if (typeof document === "undefined") return null;
-
- return createPortal(dialog, document.body);
}
function StripePaymentForm({
diff --git a/src/app/subscription/components/subscription-checkout-button.tsx b/src/app/subscription/components/subscription-checkout-button.tsx
index b71d3c27..9995260c 100644
--- a/src/app/subscription/components/subscription-checkout-button.tsx
+++ b/src/app/subscription/components/subscription-checkout-button.tsx
@@ -13,7 +13,6 @@ import {
} from "@/stores/payment/payment-context";
import { AppEnvUtil, Logger, Result } from "@/utils";
-import { StripePaymentDialog } from "./stripe-payment-dialog";
import dialogStyles from "./stripe-payment-dialog.module.css";
import { SubscriptionCtaButton } from "./subscription-cta-button";
import styles from "./subscription-cta-button.module.css";
@@ -35,9 +34,6 @@ export function SubscriptionCheckoutButton({
const payment = usePaymentState();
const paymentDispatch = usePaymentDispatch();
const launchedNonceRef = useRef(0);
- const [hiddenStripeClientSecret, setHiddenStripeClientSecret] = useState<
- string | null
- >(null);
const [isConfirmingEzpay, setIsConfirmingEzpay] = useState(false);
useEffect(() => {
@@ -98,7 +94,7 @@ export function SubscriptionCheckoutButton({
payment.isCreatingOrder ||
payment.isPollingOrder;
const readyLabel =
- subscriptionType === "topup" ? "Pay and Top Up" : "Pay and Activiate";
+ subscriptionType === "topup" ? "Pay and Top Up" : "Pay and Activate";
const agreementLabel =
subscriptionType === "topup"
? "Confirm the agreement and Top Up"
@@ -114,32 +110,9 @@ export function SubscriptionCheckoutButton({
const handleClick = () => {
if (disabled || isLoading) return;
setIsConfirmingEzpay(false);
- setHiddenStripeClientSecret(null);
paymentDispatch({ type: "PaymentCreateOrderSubmitted" });
};
- const handleStripeClose = () => {
- if (stripeClientSecret) {
- setHiddenStripeClientSecret(stripeClientSecret);
- }
- if (payment.orderStatus !== "paid") {
- paymentDispatch({ type: "PaymentReset" });
- }
- };
-
- const handleStripeConfirmed = () => {
- if (stripeClientSecret) {
- setHiddenStripeClientSecret(stripeClientSecret);
- }
- };
-
- const stripeClientSecret = payment.payParams
- ? getStripeClientSecret(payment.payParams)
- : null;
- const shouldShowStripeDialog =
- stripeClientSecret !== null &&
- stripeClientSecret !== hiddenStripeClientSecret &&
- !payment.isPaid;
const ezpayPaymentUrl = payment.payParams
? getPaymentUrl(payment.payParams)
: null;
@@ -208,13 +181,6 @@ export function SubscriptionCheckoutButton({
onConfirm={handleEzpayConfirm}
/>
) : null}
- {shouldShowStripeDialog ? (
-
- ) : null}
>
);
}
@@ -366,7 +332,7 @@ function EzpayRedirectConfirmDialog({
);
}
-function getStripeClientSecret(
+export function getStripeClientSecret(
payParams: Record
,
): string | null {
const provider = payParams.provider;
diff --git a/src/app/subscription/subscription-screen.tsx b/src/app/subscription/subscription-screen.tsx
index ca9ef45f..ef77f69a 100644
--- a/src/app/subscription/subscription-screen.tsx
+++ b/src/app/subscription/subscription-screen.tsx
@@ -13,12 +13,14 @@ import { useUserDispatch } from "@/stores/user/user-context";
import { ROUTES } from "@/router/routes";
import {
+ getStripeClientSecret,
SubscriptionBackLink,
SubscriptionCheckoutButton,
SubscriptionCoinsOfferSection,
SubscriptionPaymentMethod,
SubscriptionPaymentSuccessDialog,
SubscriptionVipOfferSection,
+ StripePaymentDialog,
} from "./components";
import styles from "./components/subscription-screen.module.css";
import {
@@ -49,6 +51,9 @@ export function SubscriptionScreen({
const refreshedPaidOrderRef = useRef(null);
const resumedPendingOrderRef = useRef(null);
const successDialogShownOrderRef = useRef(null);
+ const [hiddenStripeDialogKey, setHiddenStripeDialogKey] = useState<
+ string | null
+ >(null);
const [showPaymentSuccessDialog, setShowPaymentSuccessDialog] =
useState(false);
const canSubscribeVip = subscriptionType === "vip";
@@ -156,6 +161,16 @@ export function SubscriptionScreen({
payment.isPollingOrder;
const canActivate =
selectedPlan !== null && payment.agreed && !isPaymentBusy;
+ const stripeClientSecret = payment.payParams
+ ? getStripeClientSecret(payment.payParams)
+ : null;
+ const stripeDialogKey = stripeClientSecret
+ ? `${payment.launchNonce}:${stripeClientSecret}`
+ : null;
+ const shouldShowStripeDialog =
+ stripeClientSecret !== null &&
+ stripeDialogKey !== hiddenStripeDialogKey &&
+ !payment.isPaid;
const finishPaymentSuccessClose = () => {
setShowPaymentSuccessDialog(false);
@@ -169,6 +184,21 @@ export function SubscriptionScreen({
finishPaymentSuccessClose();
};
+ const handleStripeClose = () => {
+ if (stripeDialogKey) {
+ setHiddenStripeDialogKey(stripeDialogKey);
+ }
+ if (payment.orderStatus !== "paid") {
+ paymentDispatch({ type: "PaymentReset" });
+ }
+ };
+
+ const handleStripeConfirmed = () => {
+ if (stripeDialogKey) {
+ setHiddenStripeDialogKey(stripeDialogKey);
+ }
+ };
+
useEffect(() => {
if (canSubscribeVip) {
const firstVipPlanId = vipOfferPlans[0]?.id ?? "";
@@ -212,16 +242,28 @@ export function SubscriptionScreen({
]);
return (
-
-
-
+ <>
+
+
+
-
- {canSubscribeVip ? (
-
+ {canSubscribeVip ? (
+
+ paymentDispatch({
+ type: "PaymentPlanSelected",
+ planId,
+ })
+ }
+ />
+ ) : null}
+
paymentDispatch({
@@ -230,80 +272,78 @@ export function SubscriptionScreen({
})
}
/>
- ) : null}
-
- paymentDispatch({
- type: "PaymentPlanSelected",
- planId,
- })
- }
- />
-
+
-
-
- paymentDispatch({
- type: "PaymentPayChannelChanged",
- payChannel,
- })
- }
- />
-
+
+
+ paymentDispatch({
+ type: "PaymentPayChannelChanged",
+ payChannel,
+ })
+ }
+ />
+
-
-
+
+
+
+
+
+
+
-
-
-
-