100 lines
3.4 KiB
JavaScript
100 lines
3.4 KiB
JavaScript
// pages/alipay-webview/alipay-webview.js
|
||
// 支付宝当面付二维码展示页(替代原 web-view 方案,避免 alipay:// scheme 限制)
|
||
// 通用化:支持通过 pollUrl 参数指定轮询接口,兼容 code===0(订单)和 code===200(Czjilu类)双成功码
|
||
// 支付成功后通过 EventChannel 通知原页面刷新状态
|
||
const app = getApp()
|
||
import request from '../../utils/request.js'
|
||
|
||
Page({
|
||
data: {
|
||
qrImage: '',
|
||
orderId: '',
|
||
pollUrl: '/dingdan/fucha', // 默认订单轮询接口
|
||
statusText: '等待支付...',
|
||
showBack: false,
|
||
pollCount: 0,
|
||
maxPollCount: 60,
|
||
isPaid: false
|
||
},
|
||
|
||
onLoad(options) {
|
||
const orderId = options.orderId || ''
|
||
// base64 图片较大,通过 globalData 传递避免 URL 长度限制
|
||
const qrImage = app.globalData.alipayQrImage || ''
|
||
app.globalData.alipayQrImage = ''
|
||
// 允许调用方指定轮询接口(需 URL 编码),未指定则用默认订单接口
|
||
const pollUrl = options.pollUrl ? decodeURIComponent(options.pollUrl) : '/dingdan/fucha'
|
||
this.setData({ qrImage, orderId, pollUrl })
|
||
// 获取 opener 事件通道,用于支付成功后通知原页面刷新状态
|
||
this.openerEventChannel = this.getOpenerEventChannel ? this.getOpenerEventChannel() : null
|
||
this._pollTimer = null
|
||
this._hidden = false
|
||
if (orderId) {
|
||
this.startPolling()
|
||
}
|
||
},
|
||
|
||
startPolling() {
|
||
if (this.data.isPaid) return
|
||
if (this.data.pollCount >= this.data.maxPollCount) {
|
||
this.setData({ statusText: '支付确认超时,如已支付请点击返回', showBack: true })
|
||
return
|
||
}
|
||
this.setData({ pollCount: this.data.pollCount + 1 })
|
||
this.pollOrderStatus()
|
||
},
|
||
|
||
pollOrderStatus() {
|
||
if (this.data.isPaid) return
|
||
request({
|
||
url: this.data.pollUrl,
|
||
method: 'POST',
|
||
data: { dingdanid: this.data.orderId }
|
||
})
|
||
.then(res => {
|
||
if (this.data.isPaid) return
|
||
// 兼容两种成功码:订单接口 code===0,Czjilu类接口 code===200
|
||
if (res.statusCode === 200 && res.data && (res.data.code === 0 || res.data.code === 200)) {
|
||
this.setData({ isPaid: true, statusText: '支付成功!', showBack: true })
|
||
wx.showToast({ title: '支付成功!', icon: 'success', duration: 1500 })
|
||
// 通知原页面刷新状态(原页面通过 wx.navigateTo events 注册 onAlipaySuccess)
|
||
if (this.openerEventChannel && this.openerEventChannel.emit) {
|
||
try {
|
||
this.openerEventChannel.emit('onAlipaySuccess', { orderId: this.data.orderId, data: res.data })
|
||
} catch (e) {}
|
||
}
|
||
} else {
|
||
this.setData({ statusText: '等待支付...' })
|
||
this._pollTimer = setTimeout(() => this.startPolling(), 3000)
|
||
}
|
||
})
|
||
.catch(() => {
|
||
if (!this.data.isPaid) {
|
||
this._pollTimer = setTimeout(() => this.startPolling(), 3000)
|
||
}
|
||
})
|
||
},
|
||
|
||
onBack() {
|
||
wx.navigateBack()
|
||
},
|
||
|
||
onHide() {
|
||
// 切后台时暂停轮询并清理定时器,但不标记为已支付,以便 onShow 恢复
|
||
this._hidden = true
|
||
if (this._pollTimer) {
|
||
clearTimeout(this._pollTimer)
|
||
this._pollTimer = null
|
||
}
|
||
},
|
||
|
||
onShow() {
|
||
// 从后台恢复时,如果未支付且未超时,恢复轮询
|
||
if (this._hidden && !this.data.isPaid && this.data.orderId &&
|
||
this.data.pollCount < this.data.maxPollCount) {
|
||
this._hidden = false
|
||
this.startPolling()
|
||
}
|
||
}
|
||
})
|