// 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() } } })