test: harden payment result resume flow
This commit is contained in:
@@ -94,6 +94,7 @@ import { ref, computed, onMounted } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import OrderStatusBadge from '@/components/payment/OrderStatusBadge.vue'
|
||||
import { PAYMENT_RECOVERY_STORAGE_KEY, readPaymentRecoverySnapshot } from '@/components/payment/paymentFlow'
|
||||
import { usePaymentStore } from '@/stores/payment'
|
||||
import { paymentAPI } from '@/api/payment'
|
||||
import type { PaymentOrder } from '@/types/payment'
|
||||
@@ -129,46 +130,46 @@ const feeAmount = computed(() => {
|
||||
})
|
||||
|
||||
const isSuccess = computed(() => {
|
||||
// Always prioritize actual order status from backend
|
||||
if (order.value) {
|
||||
return SUCCESS_STATUSES.has(order.value.status)
|
||||
}
|
||||
// Fallback only when order not loaded
|
||||
if (route.query.status === 'success') return true
|
||||
if (route.query.trade_status === 'TRADE_SUCCESS') return true
|
||||
return false
|
||||
return !!order.value && SUCCESS_STATUSES.has(order.value.status)
|
||||
})
|
||||
|
||||
/** Extract numeric order ID from out_trade_no like "sub2_46" → 46 */
|
||||
function parseOutTradeNo(outTradeNo: string): number {
|
||||
const match = outTradeNo.match(/_(\d+)$/)
|
||||
return match ? Number(match[1]) : 0
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
// Try order_id first (internal navigation from QRCode/Stripe pages)
|
||||
const resumeToken = typeof route.query.resume_token === 'string'
|
||||
? route.query.resume_token
|
||||
: ''
|
||||
let orderId = Number(route.query.order_id) || 0
|
||||
const outTradeNo = String(route.query.out_trade_no || '')
|
||||
|
||||
// Fallback: EasyPay return URL with out_trade_no
|
||||
if (!orderId && outTradeNo) {
|
||||
orderId = parseOutTradeNo(outTradeNo)
|
||||
// Store return info for display when order lookup fails
|
||||
if (!orderId && resumeToken && typeof window !== 'undefined') {
|
||||
const restored = readPaymentRecoverySnapshot(
|
||||
window.localStorage.getItem(PAYMENT_RECOVERY_STORAGE_KEY),
|
||||
{ resumeToken },
|
||||
)
|
||||
if (restored?.orderId) {
|
||||
orderId = restored.orderId
|
||||
}
|
||||
}
|
||||
|
||||
if (orderId) {
|
||||
try {
|
||||
order.value = await paymentStore.pollOrderStatus(orderId)
|
||||
} catch (_err: unknown) {
|
||||
// Order lookup failed, will try legacy fallback below when possible.
|
||||
}
|
||||
}
|
||||
|
||||
if (!order.value && outTradeNo) {
|
||||
returnInfo.value = {
|
||||
outTradeNo,
|
||||
money: String(route.query.money || ''),
|
||||
type: String(route.query.type || ''),
|
||||
tradeStatus: String(route.query.trade_status || ''),
|
||||
}
|
||||
}
|
||||
|
||||
// Verify payment via public endpoint (works without login)
|
||||
if (outTradeNo) {
|
||||
try {
|
||||
const result = await paymentAPI.verifyOrderPublic(outTradeNo)
|
||||
order.value = result.data
|
||||
} catch (_err: unknown) {
|
||||
// Public verify failed, try authenticated endpoint if logged in
|
||||
try {
|
||||
const result = await paymentAPI.verifyOrder(outTradeNo)
|
||||
order.value = result.data
|
||||
@@ -176,12 +177,11 @@ onMounted(async () => {
|
||||
}
|
||||
}
|
||||
|
||||
// Normal order lookup by ID (if verify didn't load the order)
|
||||
if (!order.value && orderId) {
|
||||
try {
|
||||
order.value = await paymentStore.pollOrderStatus(orderId)
|
||||
} catch (_err: unknown) {
|
||||
// Order lookup failed, will show returnInfo fallback
|
||||
// Order lookup failed, will show returnInfo fallback.
|
||||
}
|
||||
}
|
||||
loading.value = false
|
||||
|
||||
Reference in New Issue
Block a user