forked from 77media/video-flow
修复 使用新窗口重定向到支付页,防止拦截
This commit is contained in:
parent
d4bb1e7713
commit
7fefdc1b0d
52
app/pay-redirect/page.tsx
Normal file
52
app/pay-redirect/page.tsx
Normal file
@ -0,0 +1,52 @@
|
||||
"use client";
|
||||
|
||||
import React from "react";
|
||||
|
||||
export default function PayRedirectPage() {
|
||||
const [status, setStatus] = React.useState<string>("等待安全收银台跳转...");
|
||||
const [error, setError] = React.useState<string>("");
|
||||
|
||||
React.useEffect(() => {
|
||||
const handleMessage = (event: MessageEvent) => {
|
||||
try {
|
||||
if (event.origin !== window.location.origin) return;
|
||||
const data = event.data || {};
|
||||
if (data?.type === "redirect-to-payment" && typeof data?.url === "string") {
|
||||
setStatus("即将跳转到 Stripe 收银台...");
|
||||
window.location.href = data.url as string;
|
||||
} else if (data?.type === "redirect-error") {
|
||||
setError(typeof data?.message === "string" ? data.message : "创建支付失败,请关闭此页重试");
|
||||
}
|
||||
} catch {
|
||||
setError("处理跳转信息时发生错误,请关闭此页重试");
|
||||
}
|
||||
};
|
||||
|
||||
window.addEventListener("message", handleMessage);
|
||||
// 超时兜底:若 15 秒内未收到跳转指令,提示用户
|
||||
const timeoutId = window.setTimeout(() => {
|
||||
setStatus("");
|
||||
setError("未收到跳转指令,可能网络异常或页面被拦截。请返回重试。");
|
||||
}, 15000);
|
||||
|
||||
return () => {
|
||||
window.removeEventListener("message", handleMessage);
|
||||
window.clearTimeout(timeoutId);
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div data-alt="pay-redirect-page" className="min-h-screen w-full flex items-center justify-center bg-black text-white">
|
||||
<div data-alt="pay-redirect-card" className="max-w-md w-full p-6 rounded-xl border border-white/10 bg-white/5 backdrop-blur">
|
||||
<h1 className="text-lg font-semibold mb-2">正在准备跳转</h1>
|
||||
{status && <p className="text-sm text-white/80 mb-2">{status}</p>}
|
||||
{error && <p className="text-sm text-red-300">{error}</p>}
|
||||
{!error && (
|
||||
<p className="text-xs text-white/60 mt-2">如长时间未跳转,请返回原页重试或检查网络。</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -84,39 +84,53 @@ function HomeModule5() {
|
||||
}, [plans, billingType]);
|
||||
|
||||
const handleSubscribe = async (planName: string) => {
|
||||
setLoadingPlan(planName); // 设置加载状态
|
||||
setLoadingPlan(planName);
|
||||
|
||||
// 先同步打开同域重定向页,避免拦截
|
||||
const redirectWindow = window.open('/pay-redirect', '_blank');
|
||||
if (!redirectWindow) {
|
||||
setLoadingPlan(null);
|
||||
throw new Error('Unable to open redirect window, please check popup settings');
|
||||
}
|
||||
|
||||
try {
|
||||
const { createCheckoutSession, redirectToCheckout } = await import(
|
||||
"@/lib/stripe"
|
||||
);
|
||||
const { createCheckoutSession } = await import("@/lib/stripe");
|
||||
|
||||
// 从localStorage获取当前用户信息
|
||||
const User = JSON.parse(localStorage.getItem("currentUser") || "{}");
|
||||
|
||||
if (!User.id) {
|
||||
throw new Error("Unable to obtain user ID, please log in again");
|
||||
}
|
||||
|
||||
// 1. 创建Checkout Session
|
||||
const result = await createCheckoutSession({
|
||||
user_id: String(User.id),
|
||||
plan_name: planName,
|
||||
billing_cycle: billingType,
|
||||
});
|
||||
|
||||
if (!result.successful || !result.data) {
|
||||
if (!result.successful || !result.data?.checkout_url) {
|
||||
throw new Error("create checkout session failed");
|
||||
}
|
||||
|
||||
// 通知当前窗口等待支付(显示loading模态框)
|
||||
window.postMessage({
|
||||
type: "waiting-payment",
|
||||
paymentType: "subscription"
|
||||
}, "*");
|
||||
// 在新标签页中打开Stripe支付页面,保持当前定价页面不变
|
||||
window.open(result.data.checkout_url, '_blank');
|
||||
window.postMessage({
|
||||
type: 'waiting-payment',
|
||||
paymentType: 'subscription',
|
||||
}, '*');
|
||||
|
||||
// 通过 postMessage 通知新页面执行重定向
|
||||
redirectWindow.postMessage({
|
||||
type: 'redirect-to-payment',
|
||||
url: result.data.checkout_url,
|
||||
}, window.location.origin);
|
||||
} catch (error) {
|
||||
setLoadingPlan(null); // 出错时清除加载状态
|
||||
// 通知新页错误信息
|
||||
try {
|
||||
redirectWindow.postMessage({
|
||||
type: 'redirect-error',
|
||||
message: 'Failed to create checkout session',
|
||||
}, window.location.origin);
|
||||
} catch {}
|
||||
setLoadingPlan(null);
|
||||
throw new Error("create checkout session failed, please try again later");
|
||||
}
|
||||
};
|
||||
|
||||
@ -76,7 +76,7 @@ export default function CallbackModal({
|
||||
})
|
||||
} else {
|
||||
// pending状态,继续等待
|
||||
setTimeout(fetchPaymentStatus, 2000)
|
||||
setTimeout(fetchPaymentStatus, 5000)
|
||||
}
|
||||
} else {
|
||||
throw new Error(response.message || 'Failed to get payment status')
|
||||
|
||||
@ -81,7 +81,7 @@ export function TopBar({ collapsed, isDesktop=true }: { collapsed: boolean, isDe
|
||||
}
|
||||
};
|
||||
|
||||
// 处理Token购买
|
||||
// 处理Token购买(同域新页 + postMessage 方式重定向)
|
||||
const handleBuyTokens = async (tokenAmount: number) => {
|
||||
if (!currentUser?.id) {
|
||||
console.error("用户未登录");
|
||||
@ -93,6 +93,13 @@ export function TopBar({ collapsed, isDesktop=true }: { collapsed: boolean, isDe
|
||||
return;
|
||||
}
|
||||
|
||||
// 先同步打开同域新页面,避免被拦截
|
||||
const redirectWindow = window.open("/pay-redirect", "_blank");
|
||||
if (!redirectWindow) {
|
||||
console.error("无法打开支付重定向页面,可能被浏览器拦截");
|
||||
return;
|
||||
}
|
||||
|
||||
setIsBuyingTokens(true);
|
||||
try {
|
||||
const response = await buyTokens({
|
||||
@ -102,17 +109,32 @@ export function TopBar({ collapsed, isDesktop=true }: { collapsed: boolean, isDe
|
||||
|
||||
if (response.successful && response.data?.checkout_url) {
|
||||
// 通知当前窗口等待支付,标识为Token购买
|
||||
window.postMessage({
|
||||
type: "waiting-payment",
|
||||
paymentType: "token"
|
||||
window.postMessage({
|
||||
type: "waiting-payment",
|
||||
paymentType: "token"
|
||||
}, "*");
|
||||
// 在新标签页中打开Stripe支付页面
|
||||
window.open(response.data.checkout_url, '_blank');
|
||||
|
||||
// 通过 postMessage 通知新页面进行重定向
|
||||
redirectWindow.postMessage({
|
||||
type: "redirect-to-payment",
|
||||
url: response.data.checkout_url
|
||||
}, window.location.origin);
|
||||
} else {
|
||||
console.error("创建Token购买失败:", response.message);
|
||||
// 通知新页显示错误
|
||||
redirectWindow.postMessage({
|
||||
type: "redirect-error",
|
||||
message: response.message || "创建支付失败"
|
||||
}, window.location.origin);
|
||||
}
|
||||
} catch (error) {
|
||||
} catch (error: unknown) {
|
||||
console.error("Token购买失败:", error);
|
||||
try {
|
||||
redirectWindow.postMessage({
|
||||
type: "redirect-error",
|
||||
message: "网络或服务异常,请关闭此页重试"
|
||||
}, window.location.origin);
|
||||
} catch {}
|
||||
} finally {
|
||||
setIsBuyingTokens(false);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user