From 958139d1499db3015d893c8148790d515901255e Mon Sep 17 00:00:00 2001 From: Mrx <18278715334@163.com> Date: Mon, 8 Jun 2026 15:28:53 +0800 Subject: [PATCH] f --- src/pages/finance/Wallet.vue | 101 +++++++++++++++++----- src/pages/finance/WalletProcessing.vue | 112 ++++++++++++++++++++----- 2 files changed, 173 insertions(+), 40 deletions(-) diff --git a/src/pages/finance/Wallet.vue b/src/pages/finance/Wallet.vue index 9aeb3f6..1ae67fd 100644 --- a/src/pages/finance/Wallet.vue +++ b/src/pages/finance/Wallet.vue @@ -429,6 +429,7 @@ :close-on-click-modal="false" :close-on-press-escape="false" class="qr-code-dialog" + @close="handleQrCodeDialogClose" >
@@ -437,6 +438,7 @@

请使用微信扫描上方二维码完成支付

支付金额:¥{{ formatPrice(wechatForm.amount) }}

正在确认支付状态,请稍候...

+

关闭窗口后将继续确认支付结果,请勿重复支付

关闭
@@ -476,6 +478,11 @@ const showQrCodeDialog = ref(false) const qrCodeCanvas = ref(null) const currentWechatOrderNo = ref(null) const isCheckingPayment = ref(false) +const wechatPaymentResolved = ref(false) +const skipQrCloseRedirect = ref(false) +const wechatDialogPollCount = ref(0) +const WECHAT_POLL_INTERVAL_MS = 5000 +const WECHAT_DIALOG_MAX_POLL_COUNT = 12 // 弹窗内最多轮询12次(约1分钟),之后跳转处理页 let wechatOrderPollTimer = null // 钱包信息 @@ -993,26 +1000,78 @@ const showQrCode = async (codeUrl) => { } } -// 关闭二维码弹窗 +// 关闭二维码弹窗(用户主动关闭,跳转处理页继续轮询) const closeQrCodeDialog = () => { - stopWechatOrderPolling() showQrCodeDialog.value = false +} + +const handleQrCodeDialogClose = () => { + if (wechatPaymentResolved.value) { + wechatPaymentResolved.value = false + stopWechatOrderPolling() + currentWechatOrderNo.value = null + isCheckingPayment.value = false + wechatDialogPollCount.value = 0 + return + } + + if (skipQrCloseRedirect.value) { + skipQrCloseRedirect.value = false + isCheckingPayment.value = false + wechatDialogPollCount.value = 0 + return + } + + const orderNo = currentWechatOrderNo.value + const orderAmount = wechatForm.amount + stopWechatOrderPolling() currentWechatOrderNo.value = null isCheckingPayment.value = false + wechatDialogPollCount.value = 0 + + if (orderNo) { + router.push({ + path: '/finance/wallet/processing', + query: { + out_trade_no: orderNo, + amount: orderAmount, + payment_type: 'wechat', + }, + }) + } +} + +const redirectToWechatProcessingPage = () => { + const orderNo = currentWechatOrderNo.value + const orderAmount = wechatForm.amount + if (!orderNo) return + + stopWechatOrderPolling() + skipQrCloseRedirect.value = true + currentWechatOrderNo.value = null + wechatDialogPollCount.value = 0 + showQrCodeDialog.value = false + isCheckingPayment.value = false + router.push({ + path: '/finance/wallet/processing', + query: { + out_trade_no: orderNo, + amount: orderAmount, + payment_type: 'wechat', + }, + }) } // 开始轮询微信订单状态 const startWechatOrderPolling = () => { - // 清除之前的定时器 stopWechatOrderPolling() - - // 立即检查一次 + wechatDialogPollCount.value = 0 checkWechatOrderStatus() - // 每3秒轮询一次 wechatOrderPollTimer = setInterval(() => { + wechatDialogPollCount.value++ checkWechatOrderStatus() - }, 3000) + }, WECHAT_POLL_INTERVAL_MS) } // 停止轮询 @@ -1029,47 +1088,49 @@ const checkWechatOrderStatus = async () => { return } + if (wechatDialogPollCount.value >= WECHAT_DIALOG_MAX_POLL_COUNT) { + redirectToWechatProcessingPage() + return + } + try { isCheckingPayment.value = true - const response = await callProtectedAPI(financeApi.getWechatOrderStatus, { + const response = await financeApi.getWechatOrderStatus({ out_trade_no: currentWechatOrderNo.value }) - if (!response || !response.data) { + if (!response?.data) { isCheckingPayment.value = false return } const orderStatus = response.data.status - // 订单状态:pending, success, failed, closed if (orderStatus === 'success') { - // 支付成功 + wechatPaymentResolved.value = true stopWechatOrderPolling() isCheckingPayment.value = false - closeQrCodeDialog() + showQrCodeDialog.value = false ElMessage.success('充值成功!') - - // 刷新钱包余额 await loadWalletInfo() - - // 重置表单 wechatForm.amount = '' selectedPresetAmount.value = null + currentWechatOrderNo.value = null + wechatDialogPollCount.value = 0 } else if (orderStatus === 'failed' || orderStatus === 'closed') { - // 支付失败或关闭 + wechatPaymentResolved.value = true stopWechatOrderPolling() isCheckingPayment.value = false + showQrCodeDialog.value = false ElMessage.error('支付失败,请重新支付') - closeQrCodeDialog() + currentWechatOrderNo.value = null + wechatDialogPollCount.value = 0 } else { - // pending 状态继续轮询 isCheckingPayment.value = false } } catch (error) { console.error('查询微信订单状态失败:', error) isCheckingPayment.value = false - // 不显示错误,继续轮询 } } diff --git a/src/pages/finance/WalletProcessing.vue b/src/pages/finance/WalletProcessing.vue index 1e255f2..1392f83 100644 --- a/src/pages/finance/WalletProcessing.vue +++ b/src/pages/finance/WalletProcessing.vue @@ -119,7 +119,7 @@ {{ orderInfo.out_trade_no }}
- 支付宝交易号: + {{ tradeNoLabel }}: {{ orderInfo.trade_no || '暂无' }}
@@ -245,6 +245,57 @@
+ +
+
+ + + +
+

仍在确认支付结果

+

+ 若您已完成支付,余额通常会在几分钟内到账,请稍后刷新钱包查看。 +

+ +
+
+
+ 订单号: + {{ orderInfo.out_trade_no }} +
+
+ 金额: + ¥{{ orderInfo.amount }} +
+
+
+ +
+ + +
+
+
@@ -291,12 +342,16 @@ export default { const orderStatus = ref('processing') const isProcessing = ref(true) const pollCount = ref(0) - const maxPollCount = ref(30) // 最多轮询30次 + const maxPollCount = ref(36) // 最多轮询36次(约3分钟) + const pollIntervalMs = 5000 // 每5秒查询一次,避免过于频繁 const pollInterval = ref(null) // 获取URL参数 const outTradeNo = route.query.out_trade_no const amount = route.query.amount + const paymentType = route.query.payment_type === 'wechat' ? 'wechat' : 'alipay' + const isWechatPay = computed(() => paymentType === 'wechat') + const tradeNoLabel = computed(() => (isWechatPay.value ? '微信交易号' : '支付宝交易号')) // 初始化订单信息 orderInfo.value = { @@ -304,6 +359,15 @@ export default { amount: amount, } + const normalizeOrderData = (data) => { + if (!data) return data + return { + ...data, + amount: data.amount ?? amount, + trade_no: data.trade_no || data.transaction_id || null, + } + } + // 格式化时间 const formatTime = (timeStr) => { if (!timeStr) return '暂无' @@ -313,41 +377,45 @@ export default { // 查询订单状态 const queryOrderStatus = async () => { try { - const response = await financeApi.getAlipayOrderStatus({ out_trade_no: outTradeNo }) - orderInfo.value = response.data - // 根据状态更新页面 + const response = isWechatPay.value + ? await financeApi.getWechatOrderStatus({ out_trade_no: outTradeNo }) + : await financeApi.getAlipayOrderStatus({ out_trade_no: outTradeNo }) + + if (!response?.data) return + + orderInfo.value = normalizeOrderData(response.data) + if (response.data.status === 'success') { orderStatus.value = 'success' isProcessing.value = false stopPolling() - } else if (response.data.status === 'failed') { + } else if (response.data.status === 'failed' || response.data.status === 'closed') { orderStatus.value = 'failed' isProcessing.value = false stopPolling() - } else if (response.data.status === 'pending') { - // 继续轮询,轮询次数在setInterval中已经增加 - if (pollCount.value >= maxPollCount.value) { - // 超过最大轮询次数,停止轮询 - stopPolling() - // 可以显示超时提示 - } + } else if (pollCount.value >= maxPollCount.value) { + orderStatus.value = 'timeout' + isProcessing.value = false + stopPolling() } } catch (error) { console.error('查询订单状态失败:', error) - // 查询失败时继续轮询,不要停止 + if (pollCount.value >= maxPollCount.value) { + orderStatus.value = 'timeout' + isProcessing.value = false + stopPolling() + } } } // 开始轮询 const startPolling = () => { - // 立即查询一次 queryOrderStatus() - // 每3秒查询一次 pollInterval.value = setInterval(() => { - pollCount.value++ // 增加轮询次数 + pollCount.value++ queryOrderStatus() - }, 3000) + }, pollIntervalMs) } // 停止轮询 @@ -368,10 +436,13 @@ export default { } const retryPayment = () => { - // 重新创建支付订单 router.push({ path: '/finance/wallet', - query: { retry: 'true', amount: amount }, + query: { + retry: 'true', + amount: amount, + method: isWechatPay.value ? 'wechat' : 'alipay', + }, }) } @@ -404,6 +475,7 @@ export default { isProcessing, pollCount, maxPollCount, + tradeNoLabel, formatTime, goToWallet, goToRechargeRecords,