"use client" import { useState, useEffect, useRef } from "react" import { useSearchParams } from "next/navigation" import { toast } from "sonner" import { motion } from "motion/react" import { PayingNow } from "@/components/common/pay/paying/paying-now" import { PayingInfo } from "@/components/common/pay/paying/paying-info" import { useUser } from "@/contexts/user-context" import services from "@/lib/services" import { ConfigService } from "@/lib/services" import type { PaymentLink, GetMerchantOrderResponse, UserPayConfig } from "@/lib/services" /** * 支付链接支付页面组件 * 通过 token 查询支付链接信息并完成支付 */ export function PayingOnline() { /* 获取URL参数中的Token */ const searchParams = useSearchParams() const token = searchParams.get('token') const { user } = useUser() /* 组件状态管理 */ const [paymentLink, setPaymentLink] = useState(null) const [orderInfo, setOrderInfo] = useState(null) const [loading, setLoading] = useState(true) const [error, setError] = useState(false) const [paying, setPaying] = useState(false) const [payKey, setPayKey] = useState("") const [currentStep, setCurrentStep] = useState<'method' | 'pay'>('method') const [selectedMethod, setSelectedMethod] = useState('') const [isOpen, setIsOpen] = useState(false) const timeoutRef = useRef(null) const isMountedRef = useRef(true) useEffect(() => { isMountedRef.current = true return () => { isMountedRef.current = false if (timeoutRef.current) { clearTimeout(timeoutRef.current) timeoutRef.current = null } } }, []) /* 获取用户支付配置 */ const [userPayConfigs, setUserPayConfigs] = useState([]) useEffect(() => { const loadConfigs = async () => { try { const configs = await ConfigService.getUserPayConfigs() setUserPayConfigs(configs) } catch (error) { console.error("Failed to load user pay configs:", error) } } loadConfigs() }, []) /* 统一的服务错误处理函数 */ const handleServiceError = (error: unknown, operation: string) => { console.error(`${ operation }失败:`, error) let errorMessage = `${ operation }失败` if (error && typeof error === 'object' && 'message' in error) { errorMessage = String(error.message) } const errorMap: Record = { '不存在': "此积分流转服务不存在或已失效", '未登录': "请先登录后再进行认证", '余额不足': "账户积分不足", '支付密码': "安全密码错误", '不能支付': "不能支付自己创建的积分流转服务", '每日限额': "已达到每日认证限额", } const userMessage = Object.entries(errorMap).find(([key]) => errorMessage.includes(key) )?.[1] || errorMessage toast.error(userMessage, { id: 'payment-error' }) } /* 组件初始化时查询支付链接信息 */ useEffect(() => { if (token) { setError(false) handleQueryPaymentLink(token) } else { setLoading(false) setError(true) } // eslint-disable-next-line react-hooks/exhaustive-deps }, [token, userPayConfigs.length, user?.pay_level]) /* 查询支付链接信息 */ const handleQueryPaymentLink = async (queryToken?: string) => { const targetToken = queryToken || token if (!targetToken) { toast.error("缺少支付链接", { id: 'missing-token' }) return } setLoading(true) setLoading(true) try { const data = await services.merchant.getPaymentLinkByToken(targetToken) setPaymentLink(data) /* 将支付链接信息转换为订单信息格式,以复用PayingInfo和PayingNow组件 */ const mockOrderInfo: GetMerchantOrderResponse = { merchant: { app_name: data.app_name || "商户", redirect_uri: data.redirect_uri || "", }, order: { id: '0', order_no: `LINK-${ data.id }`, order_name: data.product_name, payer_username: user?.username || "", payee_username: "", amount: data.amount, status: "pending", type: "payment", payment_type: "link", remark: data.remark || "", client_id: "", return_url: "", notify_url: "", trade_time: null, created_at: data.created_at, updated_at: data.updated_at, }, user_pay_config: (() => { const currentUserConfig = userPayConfigs.find(c => user?.pay_level !== undefined && c.level === user.pay_level) return currentUserConfig ? { ...currentUserConfig, fee_rate: String(currentUserConfig.fee_rate) } : { id: '0', level: user?.pay_level ?? 0, min_score: 0, max_score: null, daily_limit: null, fee_rate: "0.00", created_at: "", updated_at: "" } })(), } setOrderInfo(mockOrderInfo) setError(false) } catch (error: unknown) { handleServiceError(error, "查询积分流转服务") setPaymentLink(null) setOrderInfo(null) setError(true) } finally { setLoading(false) } } /* 执行支付操作 */ const handlePayOrder = async () => { if (!paymentLink || !token) return if (!payKey.trim()) { toast.error("请输入安全密码") return } if (payKey.length < 6 || payKey.length > 10) { toast.error("安全密码长度必须为6位") return } setPaying(true) try { await services.merchant.payByLink({ token: token, pay_key: payKey, remark: paymentLink.remark || undefined }) toast.success("积分流转服务认证成功!", { id: 'payment-success' }) /* 支付成功后更新订单状态 */ if (orderInfo) { setOrderInfo({ ...orderInfo, order: { ...orderInfo.order, status: 'success' } }) } /* 5秒后跳转到首页或回调地址 */ timeoutRef.current = setTimeout(() => { if (!isMountedRef.current) return const redirectUri = orderInfo?.merchant?.redirect_uri if (redirectUri && redirectUri.trim()) { window.location.href = redirectUri return } window.location.href = '/home' }, 5000) } catch (error: unknown) { handleServiceError(error, "认证") } finally { setPaying(false) } } if (error) { return (
!

出了点问题

您访问的积分流转服务不存在或已失效。请检查链接地址是否正确,对此如有疑问请联系社区技术支持。

) } return (
) }