"use client"; import { useCallback, useEffect, useState } from "react"; import Link from "next/link"; import PocketBase from "pocketbase"; import { getPayEnv, getDeviceFromEnv } from "@/app/lib/payEnv"; import { getPaymentConfig } from "@/config/services.config"; import { formatRestoreDateShort } from "@/config/promo.config"; import { usePayStatusPoll } from "@/app/lib/usePayStatusPoll"; import { ThemeToggle } from "@/app/components/ThemeToggle"; import styles from "./home.module.css"; const PB_URL = process.env.NEXT_PUBLIC_POCKETBASE_URL || "https://pocketbase.hackrobot.cn"; /** 临时:预览支付成功后的界面,本地调试用,上线前改回 false */ const FORCE_VIP_PREVIEW = false; /** 微信内支付渠道:zpay | xorpay */ const WECHAT_PAY_PROVIDER: "zpay" | "xorpay" = "xorpay"; function redirectToPayZpay(params: { user_id: string; return_url: string; total_fee: number; type: string; channel: "alipay" | "wxpay"; device: "pc" | "h5" | "wechat"; }) { const form = document.createElement("form"); form.method = "POST"; form.action = "/api/pay"; form.target = "_self"; form.style.display = "none"; const fields: [string, string][] = [ ["user_id", params.user_id], ["return_url", params.return_url], ["total_fee", String(params.total_fee)], ["type", params.type], ["channel", params.channel], ["device", params.device], ["provider", "zpay"], ["html", "1"], ]; fields.forEach(([k, v]) => { const input = document.createElement("input"); input.type = "hidden"; input.name = k; input.value = v; form.appendChild(input); }); document.body.appendChild(form); form.submit(); } async function redirectToPayZpayH5(params: { user_id: string; return_url: string; total_fee: number; type: string; channel: "alipay" | "wxpay"; }): Promise { const res = await fetch("/api/pay", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ ...params, device: "h5", provider: "zpay", html: "0", }), }); const data = await res.json().catch(() => ({})); if (!data?.ok || !data?.params || !data?.payUrl) { alert(data?.error || "支付发起失败"); return null; } const orderId = data?.order_id?.trim() || null; if (data?.redirect_url) { window.open(data.redirect_url, "_blank"); return orderId; } const form = document.createElement("form"); form.method = "POST"; form.action = data.payUrl; form.target = "_blank"; form.style.display = "none"; for (const [k, v] of Object.entries(data.params as Record)) { if (v == null) continue; const input = document.createElement("input"); input.type = "hidden"; input.name = k; input.value = String(v); form.appendChild(input); } document.body.appendChild(form); form.submit(); document.body.removeChild(form); return orderId; } async function payWechatXorpay(params: { user_id: string; return_url: string; total_fee: number; type: string; channel: "alipay" | "wxpay"; }) { const res = await fetch("/api/pay", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ ...params, total_fee: params.total_fee, device: "wechat", provider: "xorpay", html: "0", }), }); const data = await res.json().catch(() => ({})); if (!data?.ok || !data?.params || !data?.payUrl) { alert(data?.error || "支付发起失败"); return; } const form = document.createElement("form"); form.method = "POST"; form.action = data.payUrl; form.target = "_self"; form.style.display = "none"; for (const [k, v] of Object.entries(data.params as Record)) { if (v == null) continue; const input = document.createElement("input"); input.type = "hidden"; input.name = k; input.value = String(v); form.appendChild(input); } document.body.appendChild(form); form.submit(); } function getStorage(key: string): string | null { if (typeof window === "undefined") return null; return localStorage.getItem(key); } function setStorage(key: string, value: string): void { if (typeof window === "undefined") return; localStorage.setItem(key, value); } function removeStorage(key: string): void { if (typeof window === "undefined") return; localStorage.removeItem(key); } const FEATURES = [ { icon: "🚀", title: "业务方向", desc: "无人直播、RPA 自动化、Web 开发,找到你的变现路径", }, { icon: "⚙️", title: "技术杠杆", desc: "云手机、PVE 虚拟化、服务器集群,低成本放大收益", }, { icon: "🌐", title: "海外平台", desc: "YouTube、TikTok、SaaS 运营实战,出海掘金", }, ]; const UNLOCK_ITEMS = [ { icon: "📖", title: "电子书", desc: "地理套利·自动化", href: "/ebook" }, { icon: "🎬", title: "视频教程", desc: "云手机·无人直播", href: "/cloudphone" }, { icon: "👥", title: "私密社群", desc: "抱团出海", href: null }, { icon: "🛒", title: "商店", desc: "设备自助", href: null }, { icon: "💬", title: "即时问答", desc: "技术咨询", href: "https://chatwoot.hackrobot.cn/livechat?user_id=hackrobot" }, { icon: "🎪", title: "线下沙龙", desc: "面交·对接", href: null }, ]; export default function Home() { const [paidType, setPaidType] = useState(null); const [userName, setUserName] = useState(null); const [loading, setLoading] = useState(true); const [payPendingOrderId, setPayPendingOrderId] = useState(null); const savePaidType = useCallback((type: string | null) => { if (type) setStorage("paidType", type); else removeStorage("paidType"); setPaidType(type); }, []); const saveUserName = useCallback((name: string) => { setStorage("userName", name); setUserName(name); }, []); const getOrCreateUserId = useCallback(() => { let userId = getStorage("userId"); if (userId?.startsWith("{") && userId.includes("data")) { try { const parsed = JSON.parse(userId) as { data?: string }; if (parsed?.data) { userId = parsed.data; setStorage("userId", userId); } } catch { userId = null; } } if (!userId) { userId = `user${Date.now()}`; setStorage("userId", userId); } return userId; }, []); const checkPaymentFromPB = useCallback(async (userId: string) => { try { const pb = new PocketBase(PB_URL); const records = await pb.collection("payments").getList(1, 1, { filter: `user_id = "${userId}"`, sort: "-created", }); if (records.items.length > 0) { const latestType = records.items[0].type as string; const dbUserId = records.items[0].user_id as string; savePaidType(latestType); saveUserName(dbUserId); return latestType; } else { savePaidType(null); return null; } } catch (err) { console.error("查询 PocketBase 失败:", err); return getStorage("paidType"); } }, [savePaidType, saveUserName]); const clearAllStorage = useCallback(() => { try { if (typeof window === "undefined") return; const keys = ["userId", "paidType", "userName"]; keys.forEach((k) => { try { localStorage.removeItem(k); } catch { /* ignore */ } }); try { for (let i = localStorage.length - 1; i >= 0; i--) { const key = localStorage.key(i); if (key) localStorage.removeItem(key); } } catch { /* ignore */ } try { sessionStorage.clear(); } catch { /* ignore */ } setPaidType(null); setUserName(null); setLoading(false); const path = window.location.pathname || "/"; window.location.replace(path); } catch (error) { console.error("清空存储失败:", error); } }, []); const handlePay = useCallback(async () => { const userId = getOrCreateUserId(); const returnUrl = `${window.location.origin}/paid`; const env = getPayEnv(); const device = getDeviceFromEnv(env); const totalFee = getPaymentConfig().defaultAmount ?? 8800; const base = { user_id: userId, return_url: returnUrl, total_fee: totalFee, type: "vip", channel: "wxpay" as const }; if (device === "wechat" && WECHAT_PAY_PROVIDER === "xorpay") { payWechatXorpay(base); } else if (device === "h5") { const orderId = await redirectToPayZpayH5(base); if (orderId) setPayPendingOrderId(orderId); } else { redirectToPayZpay({ ...base, device }); } }, [getOrCreateUserId]); const handleCopyUsername = useCallback(() => { const name = userName || ""; if (typeof navigator !== "undefined" && navigator.clipboard) { navigator.clipboard.writeText(name); alert("账号已复制"); } }, [userName]); const env = getPayEnv(); const device = getDeviceFromEnv(env); const isH5 = device === "h5"; usePayStatusPoll( (orderId) => { let uid = getStorage("userId"); if (!uid && orderId?.includes("_order_")) { const prefix = orderId.split("_order_")[0]; const parts = prefix.split("_"); if (parts.length >= 2) uid = parts.slice(0, -1).join("_"); } if (uid) saveUserName(uid); savePaidType("vip"); if (isH5) setPayPendingOrderId(null); window.location.reload(); }, () => { if (isH5) setPayPendingOrderId(null); }, isH5 ? payPendingOrderId : undefined ); useEffect(() => { const urlParams = new URLSearchParams(window.location.search); if (urlParams.get("type")?.trim() === "clean") { clearAllStorage(); return; } if (urlParams.get("paid") === "1") { savePaidType("vip"); saveUserName(getStorage("userId") || ""); } const init = async () => { getOrCreateUserId(); const localType = getStorage("paidType"); const localUserName = getStorage("userName"); if (localType && localUserName) { setPaidType(localType); setUserName(localUserName); setLoading(false); return; } const userId = getStorage("userId"); if (userId) { await checkPaymentFromPB(userId); } setLoading(false); }; init(); }, [clearAllStorage, getOrCreateUserId, checkPaymentFromPB, savePaidType, saveUserName]); useEffect(() => { const syncFromStorage = () => { const localType = getStorage("paidType"); const localUserName = getStorage("userName"); if (localType && localUserName && !paidType) { setPaidType(localType); setUserName(localUserName); } }; const onVisible = () => syncFromStorage(); const onPageShow = (e: PageTransitionEvent) => { if (e.persisted) syncFromStorage(); }; if (typeof document !== "undefined" && document.addEventListener) { document.addEventListener("visibilitychange", onVisible); window.addEventListener("pageshow", onPageShow); return () => { document.removeEventListener("visibilitychange", onVisible); window.removeEventListener("pageshow", onPageShow); }; } }, [paidType]); if (loading) { return (

加载中...

); } if (FORCE_VIP_PREVIEW || paidType === "vip") { return (
🌍 异度星球

欢迎加入异度星球

您已解锁全部 VIP 权益

星球地址 qun.hackrobot.cn
账号 {getStorage("userName") || (FORCE_VIP_PREVIEW ? "preview" : "")}
密码 123456
进入星球 →

打开网页后,请点击「左上角头像」打开侧面栏

); } return (
🌍 异度星球

🎒 数字游民进阶社群 · 私密资源

异度星球

解锁电子书、视频教程、即时问答 · 抱团出海,技术杠杆

{FEATURES.map((f, i) => (
{f.icon}

{f.title}

{f.desc}

))}

🔓 解锁 VIP

一次付费·全部解锁

{UNLOCK_ITEMS.map((item, i) => (
{item.icon} {item.title} {item.desc}
))}

限时特惠 · {formatRestoreDateShort()}恢复原价

阶梯定价 · 数字交付 · 不支持退款

🚫 不适合躺赚、现金流紧张

); }