2025-06-18 19:05:38 +08:00
|
|
|
|
import {StaticImageData} from 'next/image'
|
|
|
|
|
|
import {useEffect, useState} from 'react'
|
|
|
|
|
|
import zod from 'zod'
|
|
|
|
|
|
import wechat from '@/components/composites/purchase/_assets/wechat.svg'
|
|
|
|
|
|
import alipay from '@/components/composites/purchase/_assets/alipay.svg'
|
|
|
|
|
|
|
|
|
|
|
|
// 支付方法枚举
|
|
|
|
|
|
export const PaymentMethod = {
|
|
|
|
|
|
Alipay: 1,
|
|
|
|
|
|
WeChat: 2,
|
|
|
|
|
|
Sft: 3,
|
|
|
|
|
|
SftAlipay: 4,
|
|
|
|
|
|
SftWeChat: 5,
|
|
|
|
|
|
} as const
|
|
|
|
|
|
|
|
|
|
|
|
// 平台枚举
|
|
|
|
|
|
export const Platform = {
|
|
|
|
|
|
Desktop: 1,
|
|
|
|
|
|
Mobile: 2,
|
|
|
|
|
|
} as const
|
|
|
|
|
|
|
2025-06-22 14:42:21 +08:00
|
|
|
|
// 支付状态枚举
|
|
|
|
|
|
export const PaymentStatus = {
|
|
|
|
|
|
Pending: 0,
|
|
|
|
|
|
Completed: 1,
|
|
|
|
|
|
Cancelled: 2, // 同步修改
|
|
|
|
|
|
Refunded: 3,
|
|
|
|
|
|
} as const
|
|
|
|
|
|
|
2025-06-18 19:05:38 +08:00
|
|
|
|
// 定义类型
|
|
|
|
|
|
export type PaymentMethod = typeof PaymentMethod[keyof typeof PaymentMethod]
|
|
|
|
|
|
export type Platform = typeof Platform[keyof typeof Platform]
|
2025-06-22 14:42:21 +08:00
|
|
|
|
export type PaymentStatus = typeof PaymentStatus[keyof typeof PaymentStatus]
|
2025-06-18 19:05:38 +08:00
|
|
|
|
|
|
|
|
|
|
// 支付方法配置类型
|
|
|
|
|
|
export type PaymentMethodConfig = {
|
|
|
|
|
|
name: string
|
|
|
|
|
|
icon: StaticImageData | null
|
|
|
|
|
|
formValue: string
|
|
|
|
|
|
availablePlatforms: Platform[]
|
2025-06-22 14:42:21 +08:00
|
|
|
|
getActualMethod: (platform: Platform) => PaymentMethod
|
2025-06-18 19:05:38 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 支付方法配置
|
2025-06-22 14:42:21 +08:00
|
|
|
|
export const PAYMENT_METHODS: Record<string, PaymentMethodConfig> = {
|
|
|
|
|
|
alipay: {
|
2025-06-18 19:05:38 +08:00
|
|
|
|
name: '支付宝',
|
|
|
|
|
|
icon: alipay,
|
|
|
|
|
|
formValue: 'alipay',
|
2025-06-22 14:42:21 +08:00
|
|
|
|
availablePlatforms: [Platform.Desktop, Platform.Mobile],
|
|
|
|
|
|
getActualMethod: platform =>
|
|
|
|
|
|
platform === Platform.Desktop ? PaymentMethod.Sft : PaymentMethod.SftAlipay,
|
2025-06-18 19:05:38 +08:00
|
|
|
|
},
|
2025-06-22 14:42:21 +08:00
|
|
|
|
wechat: {
|
2025-06-18 19:05:38 +08:00
|
|
|
|
name: '微信支付',
|
|
|
|
|
|
icon: wechat,
|
|
|
|
|
|
formValue: 'wechat',
|
2025-06-22 14:42:21 +08:00
|
|
|
|
availablePlatforms: [Platform.Desktop, Platform.Mobile],
|
|
|
|
|
|
getActualMethod: platform =>
|
|
|
|
|
|
platform === Platform.Desktop ? PaymentMethod.Sft : PaymentMethod.SftWeChat,
|
2025-06-18 19:05:38 +08:00
|
|
|
|
},
|
2025-06-22 14:42:21 +08:00
|
|
|
|
sft: {
|
2025-06-18 19:05:38 +08:00
|
|
|
|
name: '商福通',
|
|
|
|
|
|
icon: null,
|
|
|
|
|
|
formValue: 'sft',
|
|
|
|
|
|
availablePlatforms: [],
|
2025-06-22 14:42:21 +08:00
|
|
|
|
getActualMethod: () => PaymentMethod.Sft,
|
2025-06-18 19:05:38 +08:00
|
|
|
|
},
|
|
|
|
|
|
} as const
|
|
|
|
|
|
|
2025-06-22 14:42:21 +08:00
|
|
|
|
// 交易信息类型
|
|
|
|
|
|
export interface Trade {
|
|
|
|
|
|
inner_no: string
|
|
|
|
|
|
method: PaymentMethod
|
|
|
|
|
|
pay_url: string
|
|
|
|
|
|
status?: PaymentStatus
|
|
|
|
|
|
amount?: number
|
|
|
|
|
|
created_at?: string
|
|
|
|
|
|
expired_at?: string
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 支付请求参数类型
|
|
|
|
|
|
export type PaymentRequest = {
|
|
|
|
|
|
amount: string
|
|
|
|
|
|
platform: Platform
|
|
|
|
|
|
method: PaymentMethod
|
|
|
|
|
|
product_id?: string
|
|
|
|
|
|
product_name?: string
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 支付结果类型
|
|
|
|
|
|
export type PaymentResult = {
|
|
|
|
|
|
success: boolean
|
|
|
|
|
|
trade_no: string
|
|
|
|
|
|
message?: string
|
|
|
|
|
|
payment_time?: string
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-06-18 19:05:38 +08:00
|
|
|
|
// 设备检测Hook
|
|
|
|
|
|
export const usePlatformType = (): Platform => {
|
2025-06-22 14:42:21 +08:00
|
|
|
|
// 在SSR环境下返回默认值
|
|
|
|
|
|
const [platform, setPlatform] = useState<Platform>(() => {
|
|
|
|
|
|
if (typeof window === 'undefined') return Platform.Desktop
|
|
|
|
|
|
return window.matchMedia('(max-width: 768px)').matches
|
|
|
|
|
|
? Platform.Mobile
|
|
|
|
|
|
: Platform.Desktop
|
|
|
|
|
|
})
|
2025-06-18 19:05:38 +08:00
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
2025-06-22 14:42:21 +08:00
|
|
|
|
// 确保在客户端执行
|
|
|
|
|
|
if (typeof window === 'undefined') return
|
|
|
|
|
|
|
2025-06-18 19:05:38 +08:00
|
|
|
|
const checkPlatform = () => {
|
|
|
|
|
|
const isMobile = window.matchMedia('(max-width: 768px)').matches
|
|
|
|
|
|
setPlatform(isMobile ? Platform.Mobile : Platform.Desktop)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const mediaQuery = window.matchMedia('(max-width: 768px)')
|
|
|
|
|
|
mediaQuery.addEventListener('change', checkPlatform)
|
2025-06-22 14:42:21 +08:00
|
|
|
|
|
|
|
|
|
|
return () => {
|
|
|
|
|
|
mediaQuery.removeEventListener('change', checkPlatform)
|
|
|
|
|
|
}
|
2025-06-18 19:05:38 +08:00
|
|
|
|
}, [])
|
|
|
|
|
|
|
|
|
|
|
|
return platform
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 支付表单验证schema
|
|
|
|
|
|
export const paymentSchema = zod.object({
|
|
|
|
|
|
method: zod.enum(['alipay', 'wechat', 'sft', 'sftAlipay', 'sftWeChat']),
|
|
|
|
|
|
amount: zod.number().min(1, '充值金额必须大于 0'),
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
export type PaymentSchema = zod.infer<typeof paymentSchema>
|
2025-06-22 14:42:21 +08:00
|
|
|
|
// 新增函数:根据PaymentMethod获取展示信息
|
|
|
|
|
|
export const getPaymentMethodInfo = (method: PaymentMethod) => {
|
|
|
|
|
|
const found = Object.values(PAYMENT_METHODS).find(
|
|
|
|
|
|
config => config.getActualMethod(Platform.Mobile) === method,
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
return found
|
|
|
|
|
|
? {icon: found.icon, name: found.name}
|
|
|
|
|
|
: {icon: null, name: '未知支付方式'}
|
2025-06-18 19:05:38 +08:00
|
|
|
|
}
|