|
|
@@ -4,7 +4,7 @@
|
|
|
*/
|
|
|
|
|
|
import Taro from '@tarojs/taro'
|
|
|
-import { useEffect, useState } from 'react'
|
|
|
+import { useState } from 'react'
|
|
|
import { View, Text, Button } from '@tarojs/components'
|
|
|
import { useQuery } from '@tanstack/react-query'
|
|
|
import {
|
|
|
@@ -16,12 +16,6 @@ import {
|
|
|
} from '@/utils/payment'
|
|
|
import { paymentClient } from '@/api'
|
|
|
|
|
|
-interface PaymentPageParams {
|
|
|
- orderId: number
|
|
|
- amount: number
|
|
|
- orderNo?: string
|
|
|
-}
|
|
|
-
|
|
|
interface PaymentData {
|
|
|
timeStamp: string
|
|
|
nonceStr: string
|
|
|
@@ -31,39 +25,29 @@ interface PaymentData {
|
|
|
}
|
|
|
|
|
|
const PaymentPage = () => {
|
|
|
- const [params, setParams] = useState<PaymentPageParams | null>(null)
|
|
|
const [paymentStatus, setPaymentStatus] = useState<PaymentStatus>(PaymentStatus.PENDING)
|
|
|
const [isProcessing, setIsProcessing] = useState(false)
|
|
|
const [errorMessage, setErrorMessage] = useState('')
|
|
|
|
|
|
- // 获取页面参数
|
|
|
- useEffect(() => {
|
|
|
- const currentPage = Taro.getCurrentPages().pop()
|
|
|
- if (currentPage?.options) {
|
|
|
- const { orderId, amount, orderNo } = currentPage.options
|
|
|
- if (orderId && amount) {
|
|
|
- setParams({
|
|
|
- orderId: parseInt(orderId),
|
|
|
- amount: parseFloat(amount),
|
|
|
- orderNo
|
|
|
- })
|
|
|
- }
|
|
|
- }
|
|
|
- }, [])
|
|
|
+ // 获取页面参数 - 参照 goods-detail 页面的写法
|
|
|
+ const routerParams = Taro.getCurrentInstance().router?.params
|
|
|
+ const orderId = routerParams?.orderId ? parseInt(routerParams.orderId) : 0
|
|
|
+ const amount = routerParams?.amount ? parseFloat(routerParams.amount) : 0
|
|
|
+ const orderNo = routerParams?.orderNo
|
|
|
|
|
|
|
|
|
// 获取支付参数
|
|
|
const { data: paymentData, isLoading: paymentLoading } = useQuery({
|
|
|
- queryKey: ['payment-params', params?.orderId],
|
|
|
+ queryKey: ['payment-params', orderId],
|
|
|
queryFn: async () => {
|
|
|
- if (!params?.orderId) throw new Error('订单ID无效')
|
|
|
+ if (!orderId) throw new Error('订单ID无效')
|
|
|
|
|
|
// 调用后端API获取微信支付参数
|
|
|
const response = await paymentClient.payment.$post({
|
|
|
json: {
|
|
|
- orderId: params.orderId,
|
|
|
- totalAmount: Math.round(params.amount * 100), // 转换为分
|
|
|
- description: `订单支付 - ${params.orderNo || `ORD${params.orderId}`}`
|
|
|
+ orderId: orderId,
|
|
|
+ totalAmount: Math.round(amount * 100), // 转换为分
|
|
|
+ description: `订单支付 - ${orderNo || `ORD${orderId}`}`
|
|
|
}
|
|
|
})
|
|
|
|
|
|
@@ -84,7 +68,7 @@ const PaymentPage = () => {
|
|
|
|
|
|
return paymentData
|
|
|
},
|
|
|
- enabled: !!params?.orderId && paymentStatus === PaymentStatus.PENDING
|
|
|
+ enabled: !!orderId && paymentStatus === PaymentStatus.PENDING
|
|
|
})
|
|
|
|
|
|
// 支付状态管理
|
|
|
@@ -93,13 +77,13 @@ const PaymentPage = () => {
|
|
|
|
|
|
// 处理支付
|
|
|
const handlePayment = async () => {
|
|
|
- if (!params || !paymentData) {
|
|
|
+ if (!paymentData || !orderId) {
|
|
|
setErrorMessage('支付参数不完整')
|
|
|
return
|
|
|
}
|
|
|
|
|
|
// 检查频率限制
|
|
|
- const rateLimit = rateLimiter.isRateLimited(params.orderId)
|
|
|
+ const rateLimit = rateLimiter.isRateLimited(orderId)
|
|
|
if (rateLimit.limited) {
|
|
|
setErrorMessage(`支付频率过高,请${Math.ceil(rateLimit.remainingTime! / 1000)}秒后重试`)
|
|
|
return
|
|
|
@@ -108,11 +92,11 @@ const PaymentPage = () => {
|
|
|
setIsProcessing(true)
|
|
|
setErrorMessage('')
|
|
|
setPaymentStatus(PaymentStatus.PROCESSING)
|
|
|
- paymentStateManager.setPaymentState(params.orderId, PaymentStatus.PROCESSING)
|
|
|
+ paymentStateManager.setPaymentState(orderId, PaymentStatus.PROCESSING)
|
|
|
|
|
|
try {
|
|
|
// 记录支付尝试
|
|
|
- rateLimiter.recordAttempt(params.orderId)
|
|
|
+ rateLimiter.recordAttempt(orderId)
|
|
|
|
|
|
// 调用微信支付
|
|
|
const paymentResult = await requestWechatPayment(paymentData)
|
|
|
@@ -120,21 +104,21 @@ const PaymentPage = () => {
|
|
|
if (paymentResult.success) {
|
|
|
// 支付成功
|
|
|
setPaymentStatus(PaymentStatus.SUCCESS)
|
|
|
- paymentStateManager.setPaymentState(params.orderId, PaymentStatus.SUCCESS)
|
|
|
+ paymentStateManager.setPaymentState(orderId, PaymentStatus.SUCCESS)
|
|
|
|
|
|
// 清除频率限制记录
|
|
|
- rateLimiter.clearAttempts(params.orderId)
|
|
|
+ rateLimiter.clearAttempts(orderId)
|
|
|
|
|
|
// 跳转到支付成功页面
|
|
|
setTimeout(() => {
|
|
|
Taro.redirectTo({
|
|
|
- url: `/pages/payment-success/index?orderId=${params.orderId}&amount=${params.amount}`
|
|
|
+ url: `/pages/payment-success/index?orderId=${orderId}&amount=${amount}`
|
|
|
})
|
|
|
}, 1500)
|
|
|
} else {
|
|
|
// 支付失败
|
|
|
setPaymentStatus(PaymentStatus.FAILED)
|
|
|
- paymentStateManager.setPaymentState(params.orderId, PaymentStatus.FAILED)
|
|
|
+ paymentStateManager.setPaymentState(orderId, PaymentStatus.FAILED)
|
|
|
|
|
|
if (paymentResult.type === 'cancel') {
|
|
|
setErrorMessage('用户取消支付')
|
|
|
@@ -145,7 +129,7 @@ const PaymentPage = () => {
|
|
|
} catch (error: any) {
|
|
|
console.error('支付处理异常:', error)
|
|
|
setPaymentStatus(PaymentStatus.FAILED)
|
|
|
- paymentStateManager.setPaymentState(params.orderId, PaymentStatus.FAILED)
|
|
|
+ paymentStateManager.setPaymentState(orderId, PaymentStatus.FAILED)
|
|
|
setErrorMessage(error.message || '支付异常')
|
|
|
} finally {
|
|
|
setIsProcessing(false)
|
|
|
@@ -154,7 +138,7 @@ const PaymentPage = () => {
|
|
|
|
|
|
// 重试支付
|
|
|
const handleRetryPayment = async () => {
|
|
|
- if (!params || !paymentData) return
|
|
|
+ if (!paymentData || !orderId) return
|
|
|
|
|
|
setIsProcessing(true)
|
|
|
setErrorMessage('')
|
|
|
@@ -168,12 +152,12 @@ const PaymentPage = () => {
|
|
|
|
|
|
if (retryResult.success) {
|
|
|
setPaymentStatus(PaymentStatus.SUCCESS)
|
|
|
- paymentStateManager.setPaymentState(params.orderId, PaymentStatus.SUCCESS)
|
|
|
+ paymentStateManager.setPaymentState(orderId, PaymentStatus.SUCCESS)
|
|
|
|
|
|
// 跳转到支付成功页面
|
|
|
setTimeout(() => {
|
|
|
Taro.redirectTo({
|
|
|
- url: `/pages/payment-success/index?orderId=${params.orderId}&amount=${params.amount}`
|
|
|
+ url: `/pages/payment-success/index?orderId=${orderId}&amount=${amount}`
|
|
|
})
|
|
|
}, 1500)
|
|
|
} else {
|
|
|
@@ -191,9 +175,9 @@ const PaymentPage = () => {
|
|
|
|
|
|
// 取消支付
|
|
|
const handleCancelPayment = () => {
|
|
|
- if (params?.orderId) {
|
|
|
- paymentStateManager.clearPaymentState(params.orderId)
|
|
|
- rateLimiter.clearAttempts(params.orderId)
|
|
|
+ if (orderId) {
|
|
|
+ paymentStateManager.clearPaymentState(orderId)
|
|
|
+ rateLimiter.clearAttempts(orderId)
|
|
|
}
|
|
|
|
|
|
// 返回上一页
|
|
|
@@ -236,7 +220,7 @@ const PaymentPage = () => {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- if (!params) {
|
|
|
+ if (!orderId || !amount) {
|
|
|
return (
|
|
|
<View className="min-h-screen bg-gray-50 flex flex-col items-center justify-center">
|
|
|
<Text className="text-xl text-red-500 mb-8">参数错误</Text>
|
|
|
@@ -258,11 +242,11 @@ const PaymentPage = () => {
|
|
|
<View className="bg-white rounded-2xl p-6 mb-5">
|
|
|
<View className="flex justify-between items-center mb-4">
|
|
|
<Text className="text-sm text-gray-600">订单号:</Text>
|
|
|
- <Text className="text-sm text-gray-800">{params.orderNo || `ORD${params.orderId}`}</Text>
|
|
|
+ <Text className="text-sm text-gray-800">{orderNo || `ORD${orderId}`}</Text>
|
|
|
</View>
|
|
|
<View className="flex justify-between items-center">
|
|
|
<Text className="text-sm text-gray-600">支付金额:</Text>
|
|
|
- <Text className="text-2xl font-bold text-orange-500">¥{params.amount.toFixed(2)}</Text>
|
|
|
+ <Text className="text-2xl font-bold text-orange-500">¥{amount.toFixed(2)}</Text>
|
|
|
</View>
|
|
|
</View>
|
|
|
|
|
|
@@ -281,7 +265,7 @@ const PaymentPage = () => {
|
|
|
isProcessing ? 'bg-gray-400' : ''
|
|
|
}`}
|
|
|
>
|
|
|
- {isProcessing ? '支付中...' : `确认支付 ¥${params.amount.toFixed(2)}`}
|
|
|
+ {isProcessing ? '支付中...' : `确认支付 ¥${amount.toFixed(2)}`}
|
|
|
</Button>
|
|
|
)}
|
|
|
|