// xuchao: 支付层 —— 支付逻辑全部隔离在这里 // 一期为模拟支付(开发模式),后端微信预下单接口就绪后只改本文件: // - devMode=true 模拟支付成功(订单在测试环境真实生成为"待支付"状态) // - devMode=false 调后端微信预下单接口,再用微信内置桥接唤起微信支付 import config from '@/common/config.js' // xuchao: 判断是否在微信浏览器内(正式支付只能在微信里唤起) const isWechatBrowser = () => { // #ifdef H5 return /micromessenger/i.test(navigator.userAgent) // #endif } // xuchao: 发起支付 // vm: 页面的 this(用于调接口) // orderId: 订单号(createTicketsOrder 返回值) // onSuccess / onFail: 支付结果回调 const pay = (vm, { orderId, onSuccess, onFail }) => { if (config.devMode) { // 开发模式:模拟支付成功 uni.showLoading({ title: '支付中...' }) setTimeout(() => { uni.hideLoading() onSuccess && onSuccess({ mock: true }) }, 800) return } // 正式流程:微信 JSAPI 支付 const openId = uni.getStorageSync('openId') if (!openId) { uni.showToast({ icon: 'none', title: '缺少登录身份,请重新进入' }) onFail && onFail({ errMsg: 'no openId' }) return } console.log('[pay] prepay orderId=' + orderId + ' openId=' + openId) vm.$u.api.prepayWx({ orderId, openId, type: 1 }).then(res => { if (!res) return const p = res.data || {} console.log('[pay] prepay resp', p) // 后端返回微信支付所需参数后,用此桥接唤起支付(微信浏览器内置,无需额外引入) // appId 优先取后端返回值,为空时用 config.wxAppid 兜底 const invokePay = () => { WeixinJSBridge.invoke('getBrandWCPayRequest', { appId: p.appId || config.wxAppid, timeStamp: String(p.timeStamp), nonceStr: p.nonceStr || p.nonce, package: p.packageValue || p.pack || p['package'], signType: p.signType || 'RSA', paySign: p.paySign }, bridgeRes => { if (bridgeRes.err_msg === 'get_brand_wcpay_request:ok') { onSuccess && onSuccess(bridgeRes) } else { onFail && onFail(bridgeRes) } }) } // 非微信环境 prepay 已拿到参数,唤起桥接这一步才提示需在微信中完成 if (!isWechatBrowser()) { uni.showToast({ icon: 'none', title: '请在微信中打开完成支付' }) onFail && onFail({ errMsg: 'not wechat browser' }) return } // 桥接可能未就绪(冷启动进页立刻支付),挂 WeixinJSBridgeReady 事件等它就绪 if (typeof WeixinJSBridge === 'undefined') { document.addEventListener('WeixinJSBridgeReady', invokePay, false) } else { invokePay() } }).catch(() => { onFail && onFail({ errMsg: 'prepay error' }) }) } export default { pay, isWechatBrowser }