"use client"; /** * 订阅 checkout 触发按钮 * * 包装 `SubscriptionCtaButton` —— 通过 payment 状态机创建后端订单并拉起支付。 */ import { useState } from "react"; import { usePaymentLaunchFlow } from "@/app/_hooks/use-payment-launch-flow"; import { PaymentLaunchDialogs } from "@/app/_components/payment/payment-launch-dialogs"; import { ExternalBrowserCheckoutButton } from "@/app/_components/payment/external-browser-checkout-button"; import { DEFAULT_CHARACTER_SLUG } from "@/data/constants/character"; import type { SubscriptionReturnTo } from "@/lib/navigation/subscription_exit"; import { hasAutomaticRenewalAcknowledgement, rememberAutomaticRenewalAcknowledgement, } from "@/lib/payment/automatic_renewal_acknowledgement"; import { usePaymentDispatch, usePaymentState, } from "@/stores/payment/payment-context"; import { Logger } from "@/utils/logger"; import { SubscriptionCtaButton } from "./subscription-cta-button"; import { SubscriptionRenewalConfirmationDialog } from "./subscription-renewal-confirmation-dialog"; import type { VipOfferPlanView } from "./subscription-vip-offer-section"; const log = new Logger("SubscriptionCheckoutButton"); export interface SubscriptionCheckoutButtonProps { /** 是否可用(未选套餐、缺少角色来源或支付处理中为 false) */ disabled?: boolean; subscriptionType: "vip" | "topup"; returnTo?: SubscriptionReturnTo; sourceCharacterSlug?: string; renewalPlan?: VipOfferPlanView | null; renewalConsentSubjectId?: string | null; } export function SubscriptionCheckoutButton({ disabled = false, subscriptionType, returnTo = null, sourceCharacterSlug = DEFAULT_CHARACTER_SLUG, renewalPlan = null, renewalConsentSubjectId = null, }: SubscriptionCheckoutButtonProps) { const [showRenewalConfirmation, setShowRenewalConfirmation] = useState(false); const payment = usePaymentState(); const paymentDispatch = usePaymentDispatch(); const paymentLaunch = usePaymentLaunchFlow({ log, logScope: "subscription-checkout", payment, paymentDispatch, returnTo: returnTo ?? undefined, characterSlug: sourceCharacterSlug, subscriptionType, }); const isResumingQris = paymentLaunch.hasHiddenQrisPayment; const isLoading = payment.isCreatingOrder || (payment.isPollingOrder && !isResumingQris); const readyLabel = "Pay and Top Up"; const label = isResumingQris ? "Resume QRIS payment" : payment.isPollingOrder ? "Processing payment..." : payment.isCreatingOrder ? "Creating order..." : readyLabel; const startCheckout = () => { if (disabled || isLoading) return; paymentLaunch.resetLaunchState(); paymentDispatch({ type: "PaymentCreateOrderSubmitted" }); }; const handleClick = () => { if (isResumingQris) { paymentLaunch.handleQrisResume(); return; } if (disabled || isLoading) return; if ( payment.payChannel === "stripe" && payment.autoRenew && renewalPlan !== null && !hasAutomaticRenewalAcknowledgement(renewalConsentSubjectId) ) { setShowRenewalConfirmation(true); return; } startCheckout(); }; const handleRenewalConfirm = () => { rememberAutomaticRenewalAcknowledgement(renewalConsentSubjectId); setShowRenewalConfirmation(false); startCheckout(); }; return ( <> {label} {payment.payChannel === "stripe" && payment.selectedPlanId ? ( ) : null} {payment.errorMessage ? (

{payment.errorMessage}

) : null} setShowRenewalConfirmation(false)} onConfirm={handleRenewalConfirm} /> ); }