140 lines
4.1 KiB
TypeScript
140 lines
4.1 KiB
TypeScript
import apiManager from '../../utils/api'
|
|
import logger from '../../utils/logger'
|
|
|
|
Page({
|
|
data: {
|
|
products: [] as Array<any>,
|
|
userPoints: 0,
|
|
displayUserPoints: '0',
|
|
vipLevel: 0
|
|
},
|
|
async onLoad(options: Record<string, string>) {
|
|
logger.info('Coupon page loaded')
|
|
try {
|
|
const list = await apiManager.getProductList()
|
|
const products = (list || []).map((p: any) => ({
|
|
...p,
|
|
amountYuan: ((p.amount_cents || 0) / 100).toFixed(2)
|
|
}))
|
|
const ptsStr = options?.points || '0'
|
|
const lvlStr = options?.vipLevel || '0'
|
|
const ptsNum = Number(ptsStr) || 0
|
|
const lvlNum = Number(lvlStr) || 0
|
|
const fmt = (n: number) => {
|
|
const s = Math.floor(n).toString()
|
|
return s.replace(/\B(?=(\d{3})+(?!\d))/g, ',')
|
|
}
|
|
this.setData({
|
|
products,
|
|
userPoints: ptsNum,
|
|
displayUserPoints: fmt(ptsNum),
|
|
vipLevel: lvlNum
|
|
})
|
|
} catch (err) {
|
|
logger.error('加载产品列表失败', err)
|
|
wx.showToast({ title: '加载失败', icon: 'none' })
|
|
}
|
|
},
|
|
async handleCouponTap(e: any) {
|
|
try {
|
|
const productId = e?.currentTarget?.dataset?.id
|
|
if (!productId) {
|
|
wx.showToast({ title: '商品信息错误', icon: 'none' })
|
|
return
|
|
}
|
|
|
|
const order = await apiManager.createJsapiOrder(productId)
|
|
const prepayId = order?.prepay_id
|
|
const outTradeNo = order?.out_trade_no
|
|
if (!prepayId) {
|
|
wx.showToast({ title: '下单失败', icon: 'none' })
|
|
return
|
|
}
|
|
|
|
const pkg = `prepay_id=${prepayId}`
|
|
const timeStamp = order?.timeStamp
|
|
const nonceStr = order?.nonceStr
|
|
const paySign = order?.paySign
|
|
const signType = order?.signType || 'RSA'
|
|
|
|
if (timeStamp && nonceStr && paySign) {
|
|
wx.requestPayment({
|
|
timeStamp,
|
|
nonceStr,
|
|
package: pkg,
|
|
signType,
|
|
paySign,
|
|
success: async () => {
|
|
if (outTradeNo) {
|
|
await this.queryPaymentWithRetry(outTradeNo)
|
|
} else {
|
|
wx.showToast({ title: '支付成功', icon: 'success' })
|
|
}
|
|
},
|
|
fail: async (err) => {
|
|
logger.error('支付失败', err)
|
|
if (outTradeNo) {
|
|
await this.queryPaymentWithRetry(outTradeNo)
|
|
} else {
|
|
wx.showToast({ title: '支付失败', icon: 'none' })
|
|
}
|
|
}
|
|
})
|
|
} else {
|
|
wx.showToast({ title: '缺少支付签名参数', icon: 'none' })
|
|
}
|
|
} catch (error) {
|
|
logger.error('发起支付失败', error)
|
|
wx.showToast({ title: '发起支付失败', icon: 'none' })
|
|
}
|
|
}
|
|
,
|
|
async queryPaymentWithRetry(outTradeNo: string, maxAttempts: number = 5) {
|
|
let attempt = 0
|
|
while (attempt < maxAttempts) {
|
|
try {
|
|
const res = await apiManager.getWxpayOrder(outTradeNo)
|
|
const state = res?.trade_state || ''
|
|
if (state === 'SUCCESS') {
|
|
wx.showToast({ title: '支付成功', icon: 'success' })
|
|
this.goBackToProfile()
|
|
return
|
|
}
|
|
if (state === 'USERPAYING' || state === 'NOTPAY' || state === 'PROCESSING') {
|
|
wx.showToast({ title: '支付处理中', icon: 'none' })
|
|
await new Promise(r => setTimeout(r, 800))
|
|
attempt++
|
|
continue
|
|
}
|
|
wx.showToast({ title: '支付失败', icon: 'none' })
|
|
return
|
|
} catch (err) {
|
|
await new Promise(r => setTimeout(r, 800))
|
|
attempt++
|
|
}
|
|
}
|
|
wx.showToast({ title: '查询超时,请稍后重试', icon: 'none' })
|
|
}
|
|
,
|
|
goBackToProfile() {
|
|
try {
|
|
const pages = getCurrentPages()
|
|
let delta = 0
|
|
for (let i = pages.length - 1; i >= 0; i--) {
|
|
const route = pages[i]?.route || ''
|
|
if (route.endsWith('pages/profile/profile')) {
|
|
delta = pages.length - 1 - i
|
|
break
|
|
}
|
|
}
|
|
if (delta > 0) {
|
|
wx.navigateBack({ delta })
|
|
} else {
|
|
wx.reLaunch({ url: '/pages/profile/profile' })
|
|
}
|
|
} catch (e) {
|
|
wx.reLaunch({ url: '/pages/profile/profile' })
|
|
}
|
|
}
|
|
})
|