refactor(payment): share launch flow
This commit is contained in:
@@ -0,0 +1,49 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
|
||||
import { shouldShowEzpayConfirmation } from "../use-payment-launch-flow";
|
||||
|
||||
describe("shouldShowEzpayConfirmation", () => {
|
||||
it("shows confirmation for Ezpay in non-production builds", () => {
|
||||
expect(
|
||||
shouldShowEzpayConfirmation({
|
||||
currentOrderId: "order-1",
|
||||
isProduction: false,
|
||||
payParams: { provider: "ezpay" },
|
||||
paymentUrl: "https://pay.example/checkout",
|
||||
}),
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it("does not show confirmation in production", () => {
|
||||
expect(
|
||||
shouldShowEzpayConfirmation({
|
||||
currentOrderId: "order-1",
|
||||
isProduction: true,
|
||||
payParams: { provider: "ezpay" },
|
||||
paymentUrl: "https://pay.example/checkout",
|
||||
}),
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it("does not show confirmation without an order id", () => {
|
||||
expect(
|
||||
shouldShowEzpayConfirmation({
|
||||
currentOrderId: null,
|
||||
isProduction: false,
|
||||
payParams: { provider: "ezpay" },
|
||||
paymentUrl: "https://pay.example/checkout",
|
||||
}),
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it("does not show confirmation for non-Ezpay providers", () => {
|
||||
expect(
|
||||
shouldShowEzpayConfirmation({
|
||||
currentOrderId: "order-1",
|
||||
isProduction: false,
|
||||
payParams: { provider: "stripe" },
|
||||
paymentUrl: "https://pay.example/checkout",
|
||||
}),
|
||||
).toBe(false);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,208 @@
|
||||
"use client";
|
||||
|
||||
import { type Dispatch, useEffect, useRef, useState } from "react";
|
||||
|
||||
import {
|
||||
getPaymentUrl,
|
||||
getStripeClientSecret,
|
||||
isEzpayPayment,
|
||||
launchEzpayRedirect,
|
||||
} from "@/lib/payment/payment_launch";
|
||||
import type {
|
||||
PendingPaymentReturnTo,
|
||||
PendingPaymentSubscriptionType,
|
||||
} from "@/lib/payment/pending_payment_order";
|
||||
import type {
|
||||
PaymentContextState,
|
||||
} from "@/stores/payment/payment-context";
|
||||
import type { PaymentEvent } from "@/stores/payment/payment-events";
|
||||
import { AppEnvUtil, Logger } from "@/utils";
|
||||
|
||||
const UNSUPPORTED_PAYMENT_PARAMS_MESSAGE =
|
||||
"Payment parameters did not include a supported URL or Stripe client secret.";
|
||||
|
||||
export interface ShouldShowEzpayConfirmationInput {
|
||||
currentOrderId: string | null;
|
||||
isProduction: boolean;
|
||||
payParams: Record<string, unknown> | null;
|
||||
paymentUrl: string | null;
|
||||
}
|
||||
|
||||
export interface UsePaymentLaunchFlowInput {
|
||||
log: Logger;
|
||||
logScope: string;
|
||||
payment: PaymentContextState;
|
||||
paymentDispatch: Dispatch<PaymentEvent>;
|
||||
returnTo?: PendingPaymentReturnTo;
|
||||
subscriptionType: PendingPaymentSubscriptionType;
|
||||
}
|
||||
|
||||
export interface PaymentLaunchFlow {
|
||||
ezpayPaymentUrl: string | null;
|
||||
handleEzpayCancel: () => void;
|
||||
handleEzpayConfirm: () => void;
|
||||
handleStripeClose: () => void;
|
||||
handleStripeConfirmed: () => void;
|
||||
isConfirmingEzpay: boolean;
|
||||
resetLaunchState: () => void;
|
||||
shouldShowEzpayConfirmDialog: boolean;
|
||||
shouldShowStripeDialog: boolean;
|
||||
stripeClientSecret: string | null;
|
||||
}
|
||||
|
||||
export function shouldShowEzpayConfirmation({
|
||||
currentOrderId,
|
||||
isProduction,
|
||||
payParams,
|
||||
paymentUrl,
|
||||
}: ShouldShowEzpayConfirmationInput): boolean {
|
||||
return Boolean(
|
||||
!isProduction &&
|
||||
payParams &&
|
||||
isEzpayPayment(payParams) &&
|
||||
paymentUrl &&
|
||||
currentOrderId,
|
||||
);
|
||||
}
|
||||
|
||||
export function usePaymentLaunchFlow({
|
||||
log,
|
||||
logScope,
|
||||
payment,
|
||||
paymentDispatch,
|
||||
returnTo,
|
||||
subscriptionType,
|
||||
}: UsePaymentLaunchFlowInput): PaymentLaunchFlow {
|
||||
const launchedNonceRef = useRef(0);
|
||||
const [hiddenStripeClientSecret, setHiddenStripeClientSecret] = useState<
|
||||
string | null
|
||||
>(null);
|
||||
const [isConfirmingEzpay, setIsConfirmingEzpay] = useState(false);
|
||||
const stripeClientSecret = payment.payParams
|
||||
? getStripeClientSecret(payment.payParams)
|
||||
: null;
|
||||
const ezpayPaymentUrl = payment.payParams
|
||||
? getPaymentUrl(payment.payParams)
|
||||
: null;
|
||||
|
||||
useEffect(() => {
|
||||
if (!payment.payParams || payment.launchNonce <= launchedNonceRef.current) {
|
||||
return;
|
||||
}
|
||||
|
||||
launchedNonceRef.current = payment.launchNonce;
|
||||
const clientSecret = getStripeClientSecret(payment.payParams);
|
||||
if (clientSecret) return;
|
||||
|
||||
const paymentUrl = getPaymentUrl(payment.payParams);
|
||||
if (paymentUrl) {
|
||||
const isEzpay = isEzpayPayment(payment.payParams);
|
||||
|
||||
if (!AppEnvUtil.isProduction() && isEzpay) {
|
||||
log.debug(`[${logScope}] ezpay confirmation required`, {
|
||||
orderId: payment.currentOrderId,
|
||||
paymentUrl,
|
||||
subscriptionType,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (isEzpay) {
|
||||
void launchEzpayRedirect({
|
||||
orderId: payment.currentOrderId,
|
||||
paymentUrl,
|
||||
subscriptionType,
|
||||
...(returnTo ? { returnTo } : {}),
|
||||
onFailed: (errorMessage) =>
|
||||
paymentDispatch({ type: "PaymentLaunchFailed", errorMessage }),
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
window.location.href = paymentUrl;
|
||||
return;
|
||||
}
|
||||
|
||||
paymentDispatch({
|
||||
type: "PaymentLaunchFailed",
|
||||
errorMessage: UNSUPPORTED_PAYMENT_PARAMS_MESSAGE,
|
||||
});
|
||||
}, [
|
||||
log,
|
||||
logScope,
|
||||
payment.currentOrderId,
|
||||
payment.launchNonce,
|
||||
payment.payParams,
|
||||
paymentDispatch,
|
||||
returnTo,
|
||||
subscriptionType,
|
||||
]);
|
||||
|
||||
const shouldShowStripeDialog =
|
||||
stripeClientSecret !== null &&
|
||||
stripeClientSecret !== hiddenStripeClientSecret &&
|
||||
!payment.isPaid;
|
||||
const shouldShowEzpayConfirmDialog = shouldShowEzpayConfirmation({
|
||||
currentOrderId: payment.currentOrderId,
|
||||
isProduction: AppEnvUtil.isProduction(),
|
||||
payParams: payment.payParams,
|
||||
paymentUrl: ezpayPaymentUrl,
|
||||
});
|
||||
|
||||
function resetLaunchState(): void {
|
||||
setIsConfirmingEzpay(false);
|
||||
setHiddenStripeClientSecret(null);
|
||||
}
|
||||
|
||||
function handleStripeClose(): void {
|
||||
if (stripeClientSecret) {
|
||||
setHiddenStripeClientSecret(stripeClientSecret);
|
||||
}
|
||||
if (payment.orderStatus !== "paid") {
|
||||
paymentDispatch({ type: "PaymentReset" });
|
||||
}
|
||||
}
|
||||
|
||||
function handleStripeConfirmed(): void {
|
||||
if (stripeClientSecret) {
|
||||
setHiddenStripeClientSecret(stripeClientSecret);
|
||||
}
|
||||
}
|
||||
|
||||
function handleEzpayConfirm(): void {
|
||||
if (!payment.currentOrderId || !ezpayPaymentUrl) return;
|
||||
setIsConfirmingEzpay(true);
|
||||
void launchEzpayRedirect({
|
||||
orderId: payment.currentOrderId,
|
||||
paymentUrl: ezpayPaymentUrl,
|
||||
subscriptionType,
|
||||
...(returnTo ? { returnTo } : {}),
|
||||
onFailed: (errorMessage) => {
|
||||
setIsConfirmingEzpay(false);
|
||||
paymentDispatch({ type: "PaymentLaunchFailed", errorMessage });
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
function handleEzpayCancel(): void {
|
||||
log.debug(`[${logScope}] ezpay confirmation cancelled`, {
|
||||
orderId: payment.currentOrderId,
|
||||
subscriptionType,
|
||||
});
|
||||
setIsConfirmingEzpay(false);
|
||||
paymentDispatch({ type: "PaymentReset" });
|
||||
}
|
||||
|
||||
return {
|
||||
ezpayPaymentUrl,
|
||||
handleEzpayCancel,
|
||||
handleEzpayConfirm,
|
||||
handleStripeClose,
|
||||
handleStripeConfirmed,
|
||||
isConfirmingEzpay,
|
||||
resetLaunchState,
|
||||
shouldShowEzpayConfirmDialog,
|
||||
shouldShowStripeDialog,
|
||||
stripeClientSecret,
|
||||
};
|
||||
}
|
||||
@@ -4,19 +4,12 @@
|
||||
*
|
||||
* 包装 `SubscriptionCtaButton` —— 通过 payment 状态机创建后端订单并拉起支付。
|
||||
*/
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
|
||||
import {
|
||||
getPaymentUrl,
|
||||
getStripeClientSecret,
|
||||
isEzpayPayment,
|
||||
launchEzpayRedirect,
|
||||
} from "@/lib/payment/payment_launch";
|
||||
import { usePaymentLaunchFlow } from "@/app/_hooks/use-payment-launch-flow";
|
||||
import {
|
||||
usePaymentDispatch,
|
||||
usePaymentState,
|
||||
} from "@/stores/payment/payment-context";
|
||||
import { AppEnvUtil, Logger } from "@/utils";
|
||||
import { Logger } from "@/utils";
|
||||
|
||||
import { StripePaymentDialog } from "./stripe-payment-dialog";
|
||||
import dialogStyles from "./stripe-payment-dialog.module.css";
|
||||
@@ -39,65 +32,14 @@ export function SubscriptionCheckoutButton({
|
||||
}: SubscriptionCheckoutButtonProps) {
|
||||
const payment = usePaymentState();
|
||||
const paymentDispatch = usePaymentDispatch();
|
||||
const launchedNonceRef = useRef(0);
|
||||
const [hiddenStripeClientSecret, setHiddenStripeClientSecret] = useState<
|
||||
string | null
|
||||
>(null);
|
||||
const [isConfirmingEzpay, setIsConfirmingEzpay] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (!payment.payParams || payment.launchNonce <= launchedNonceRef.current) {
|
||||
return;
|
||||
}
|
||||
|
||||
launchedNonceRef.current = payment.launchNonce;
|
||||
const clientSecret = getStripeClientSecret(payment.payParams);
|
||||
if (clientSecret) {
|
||||
return;
|
||||
}
|
||||
|
||||
const paymentUrl = getPaymentUrl(payment.payParams);
|
||||
if (paymentUrl) {
|
||||
const isEzpay = isEzpayPayment(payment.payParams);
|
||||
|
||||
if (!AppEnvUtil.isProduction() && isEzpay) {
|
||||
log.debug("[subscription-checkout] ezpay confirmation required", {
|
||||
orderId: payment.currentOrderId,
|
||||
paymentUrl,
|
||||
subscriptionType,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (isEzpay) {
|
||||
void launchEzpayRedirect({
|
||||
orderId: payment.currentOrderId,
|
||||
paymentUrl,
|
||||
subscriptionType,
|
||||
returnTo: returnTo ?? undefined,
|
||||
onFailed: (errorMessage) =>
|
||||
paymentDispatch({ type: "PaymentLaunchFailed", errorMessage }),
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
window.location.href = paymentUrl;
|
||||
return;
|
||||
}
|
||||
|
||||
paymentDispatch({
|
||||
type: "PaymentLaunchFailed",
|
||||
errorMessage:
|
||||
"Payment parameters did not include a supported URL or Stripe client secret.",
|
||||
});
|
||||
}, [
|
||||
payment.currentOrderId,
|
||||
payment.launchNonce,
|
||||
payment.payParams,
|
||||
const paymentLaunch = usePaymentLaunchFlow({
|
||||
log,
|
||||
logScope: "subscription-checkout",
|
||||
payment,
|
||||
paymentDispatch,
|
||||
returnTo,
|
||||
returnTo: returnTo ?? undefined,
|
||||
subscriptionType,
|
||||
]);
|
||||
});
|
||||
|
||||
const isLoading =
|
||||
payment.isCreatingOrder ||
|
||||
@@ -118,69 +60,10 @@ export function SubscriptionCheckoutButton({
|
||||
|
||||
const handleClick = () => {
|
||||
if (disabled || isLoading) return;
|
||||
setIsConfirmingEzpay(false);
|
||||
setHiddenStripeClientSecret(null);
|
||||
paymentLaunch.resetLaunchState();
|
||||
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;
|
||||
const shouldShowEzpayConfirmDialog =
|
||||
!AppEnvUtil.isProduction() &&
|
||||
payment.payParams &&
|
||||
isEzpayPayment(payment.payParams) &&
|
||||
ezpayPaymentUrl &&
|
||||
payment.currentOrderId
|
||||
? true
|
||||
: false;
|
||||
|
||||
const handleEzpayConfirm = () => {
|
||||
if (!payment.currentOrderId || !ezpayPaymentUrl) return;
|
||||
setIsConfirmingEzpay(true);
|
||||
void launchEzpayRedirect({
|
||||
orderId: payment.currentOrderId,
|
||||
paymentUrl: ezpayPaymentUrl,
|
||||
subscriptionType,
|
||||
returnTo: returnTo ?? undefined,
|
||||
onFailed: (errorMessage) => {
|
||||
setIsConfirmingEzpay(false);
|
||||
paymentDispatch({ type: "PaymentLaunchFailed", errorMessage });
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const handleEzpayCancel = () => {
|
||||
log.debug("[subscription-checkout] ezpay confirmation cancelled", {
|
||||
orderId: payment.currentOrderId,
|
||||
subscriptionType,
|
||||
});
|
||||
setIsConfirmingEzpay(false);
|
||||
paymentDispatch({ type: "PaymentReset" });
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<SubscriptionCtaButton
|
||||
@@ -205,19 +88,19 @@ export function SubscriptionCheckoutButton({
|
||||
{payment.errorMessage}
|
||||
</p>
|
||||
) : null}
|
||||
{shouldShowEzpayConfirmDialog ? (
|
||||
{paymentLaunch.shouldShowEzpayConfirmDialog ? (
|
||||
<EzpayRedirectConfirmDialog
|
||||
orderId={payment.currentOrderId ?? ""}
|
||||
isConfirming={isConfirmingEzpay}
|
||||
onCancel={handleEzpayCancel}
|
||||
onConfirm={handleEzpayConfirm}
|
||||
isConfirming={paymentLaunch.isConfirmingEzpay}
|
||||
onCancel={paymentLaunch.handleEzpayCancel}
|
||||
onConfirm={paymentLaunch.handleEzpayConfirm}
|
||||
/>
|
||||
) : null}
|
||||
{shouldShowStripeDialog ? (
|
||||
{paymentLaunch.shouldShowStripeDialog && paymentLaunch.stripeClientSecret ? (
|
||||
<StripePaymentDialog
|
||||
clientSecret={stripeClientSecret}
|
||||
onClose={handleStripeClose}
|
||||
onConfirmed={handleStripeConfirmed}
|
||||
clientSecret={paymentLaunch.stripeClientSecret}
|
||||
onClose={paymentLaunch.handleStripeClose}
|
||||
onConfirmed={paymentLaunch.handleStripeConfirmed}
|
||||
/>
|
||||
) : null}
|
||||
</>
|
||||
|
||||
@@ -1,19 +1,12 @@
|
||||
"use client";
|
||||
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
|
||||
import {
|
||||
getPaymentUrl,
|
||||
getStripeClientSecret,
|
||||
isEzpayPayment,
|
||||
launchEzpayRedirect,
|
||||
} from "@/lib/payment/payment_launch";
|
||||
import { usePaymentLaunchFlow } from "@/app/_hooks/use-payment-launch-flow";
|
||||
import { ROUTES } from "@/router/routes";
|
||||
import {
|
||||
usePaymentDispatch,
|
||||
usePaymentState,
|
||||
} from "@/stores/payment/payment-context";
|
||||
import { AppEnvUtil, Logger } from "@/utils";
|
||||
import { Logger } from "@/utils";
|
||||
|
||||
import { StripePaymentDialog } from "../subscription/components/stripe-payment-dialog";
|
||||
import dialogStyles from "../subscription/components/stripe-payment-dialog.module.css";
|
||||
@@ -34,80 +27,16 @@ export function TipCheckoutButton({
|
||||
}: TipCheckoutButtonProps) {
|
||||
const payment = usePaymentState();
|
||||
const paymentDispatch = usePaymentDispatch();
|
||||
const launchedNonceRef = useRef(0);
|
||||
const [hiddenStripeClientSecret, setHiddenStripeClientSecret] = useState<
|
||||
string | null
|
||||
>(null);
|
||||
const [isConfirmingEzpay, setIsConfirmingEzpay] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (!payment.payParams || payment.launchNonce <= launchedNonceRef.current) {
|
||||
return;
|
||||
}
|
||||
|
||||
launchedNonceRef.current = payment.launchNonce;
|
||||
const clientSecret = getStripeClientSecret(payment.payParams);
|
||||
if (clientSecret) return;
|
||||
|
||||
const paymentUrl = getPaymentUrl(payment.payParams);
|
||||
if (paymentUrl) {
|
||||
const isEzpay = isEzpayPayment(payment.payParams);
|
||||
|
||||
if (!AppEnvUtil.isProduction() && isEzpay) {
|
||||
log.debug("[tip-checkout] ezpay confirmation required", {
|
||||
orderId: payment.currentOrderId,
|
||||
paymentUrl,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (isEzpay) {
|
||||
void launchEzpayRedirect({
|
||||
orderId: payment.currentOrderId,
|
||||
paymentUrl,
|
||||
subscriptionType: "tip",
|
||||
onFailed: (errorMessage) =>
|
||||
paymentDispatch({ type: "PaymentLaunchFailed", errorMessage }),
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
window.location.href = paymentUrl;
|
||||
return;
|
||||
}
|
||||
|
||||
paymentDispatch({
|
||||
type: "PaymentLaunchFailed",
|
||||
errorMessage:
|
||||
"Payment parameters did not include a supported URL or Stripe client secret.",
|
||||
});
|
||||
}, [
|
||||
payment.currentOrderId,
|
||||
payment.launchNonce,
|
||||
payment.payParams,
|
||||
const paymentLaunch = usePaymentLaunchFlow({
|
||||
log,
|
||||
logScope: "tip-checkout",
|
||||
payment,
|
||||
paymentDispatch,
|
||||
]);
|
||||
subscriptionType: "tip",
|
||||
});
|
||||
|
||||
const isLoading =
|
||||
isAuthLoading || payment.isCreatingOrder || payment.isPollingOrder;
|
||||
const stripeClientSecret = payment.payParams
|
||||
? getStripeClientSecret(payment.payParams)
|
||||
: null;
|
||||
const shouldShowStripeDialog =
|
||||
stripeClientSecret !== null &&
|
||||
stripeClientSecret !== hiddenStripeClientSecret &&
|
||||
!payment.isPaid;
|
||||
const ezpayPaymentUrl = payment.payParams
|
||||
? getPaymentUrl(payment.payParams)
|
||||
: null;
|
||||
const shouldShowEzpayConfirmDialog =
|
||||
!AppEnvUtil.isProduction() &&
|
||||
payment.payParams &&
|
||||
isEzpayPayment(payment.payParams) &&
|
||||
ezpayPaymentUrl &&
|
||||
payment.currentOrderId
|
||||
? true
|
||||
: false;
|
||||
const label = payment.isPollingOrder
|
||||
? "Processing payment..."
|
||||
: payment.isCreatingOrder
|
||||
@@ -116,43 +45,6 @@ export function TipCheckoutButton({
|
||||
? "Thanks for the coffee"
|
||||
: "Order and Buy";
|
||||
|
||||
const handleStripeClose = () => {
|
||||
if (stripeClientSecret) {
|
||||
setHiddenStripeClientSecret(stripeClientSecret);
|
||||
}
|
||||
if (payment.orderStatus !== "paid") {
|
||||
paymentDispatch({ type: "PaymentReset" });
|
||||
}
|
||||
};
|
||||
|
||||
const handleStripeConfirmed = () => {
|
||||
if (stripeClientSecret) {
|
||||
setHiddenStripeClientSecret(stripeClientSecret);
|
||||
}
|
||||
};
|
||||
|
||||
const handleEzpayConfirm = () => {
|
||||
if (!payment.currentOrderId || !ezpayPaymentUrl) return;
|
||||
setIsConfirmingEzpay(true);
|
||||
void launchEzpayRedirect({
|
||||
orderId: payment.currentOrderId,
|
||||
paymentUrl: ezpayPaymentUrl,
|
||||
subscriptionType: "tip",
|
||||
onFailed: (errorMessage) => {
|
||||
setIsConfirmingEzpay(false);
|
||||
paymentDispatch({ type: "PaymentLaunchFailed", errorMessage });
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const handleEzpayCancel = () => {
|
||||
log.debug("[tip-checkout] ezpay confirmation cancelled", {
|
||||
orderId: payment.currentOrderId,
|
||||
});
|
||||
setIsConfirmingEzpay(false);
|
||||
paymentDispatch({ type: "PaymentReset" });
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<button
|
||||
@@ -168,20 +60,20 @@ export function TipCheckoutButton({
|
||||
{payment.errorMessage}
|
||||
</p>
|
||||
) : null}
|
||||
{shouldShowEzpayConfirmDialog ? (
|
||||
{paymentLaunch.shouldShowEzpayConfirmDialog ? (
|
||||
<EzpayRedirectConfirmDialog
|
||||
orderId={payment.currentOrderId ?? ""}
|
||||
isConfirming={isConfirmingEzpay}
|
||||
onCancel={handleEzpayCancel}
|
||||
onConfirm={handleEzpayConfirm}
|
||||
isConfirming={paymentLaunch.isConfirmingEzpay}
|
||||
onCancel={paymentLaunch.handleEzpayCancel}
|
||||
onConfirm={paymentLaunch.handleEzpayConfirm}
|
||||
/>
|
||||
) : null}
|
||||
{shouldShowStripeDialog ? (
|
||||
{paymentLaunch.shouldShowStripeDialog && paymentLaunch.stripeClientSecret ? (
|
||||
<StripePaymentDialog
|
||||
clientSecret={stripeClientSecret}
|
||||
clientSecret={paymentLaunch.stripeClientSecret}
|
||||
returnPath={ROUTES.tip}
|
||||
onClose={handleStripeClose}
|
||||
onConfirmed={handleStripeConfirmed}
|
||||
onClose={paymentLaunch.handleStripeClose}
|
||||
onConfirmed={paymentLaunch.handleStripeConfirmed}
|
||||
/>
|
||||
) : null}
|
||||
</>
|
||||
|
||||
Reference in New Issue
Block a user