app端支付成功后无法触发uni.onpaymentcomplete,需在uni.requestpayment的success回调中立即跳转并轮询查状态,android用广播/activity回传、ios用uni.postmessage,且须正确配置原生插件。

App端支付成功后点返回键直接退出或跳错页,不是你路由写错了,是没处理原生层与JS层的通信断层——uni.onPaymentComplete在App里根本不会触发,必须靠你自己搭桥。
App端支付成功页为什么收不到回调
因为uni.onPaymentComplete只在小程序生效,App端调起微信/支付宝后,原生SDK完成支付,但不会主动通知JS层。你写的uni.onPaymentComplete监听永远进不去,这不是bug,是设计如此。
- Android侧:微信/支付宝SDK支付完成后,需通过自定义广播或Activity结果回传,但uni-app默认不暴露这些通道
- iOS侧:得用
uni.postMessage,但前提是manifest.json里勾选了「使用原生插件」,否则调用静默失败 - build时没勾选对应原生支付插件(如
Wechat、Alipay),uni.requestPayment的success回调都进不去
支付成功页的返回逻辑必须前置到success回调
uni.requestPayment的success回调在App端含义是“支付调起成功”,不是“用户已付款”。但它是你唯一能稳稳拿到的时机,所有跳转和状态检查必须从这里开始。
- 立即跳转订单详情页:
uni.navigateTo({ url: '/pages/order/detail?order_id=' + orderId }) - 不要等“支付完成回调”,那个在App里不存在;也不要依赖
uni.onShow或onUnload,页面可能已被销毁 - 订单页
onLoad里立刻查支付状态:uni.request({ url: '/api/pay/status?order_id=' + orderId }) - 服务端接口必须返回明确状态字段,比如
{ status: 'success' | 'pending' | 'failed' },不能只靠HTTP 200
如何拦截返回键并跳转指定页(非默认上一页)
用户在支付成功页点左上角返回或物理返回键,你想让它跳首页/订单列表,而不是退到上一个空白页或闪退,就得用onBackPress,但必须写对位置和逻辑。
- 只能写在
pages/xxx.vue的export default对象里,组件里写无效 - 必须
return true才拦截,默认行为会立刻执行;return false或不返回等同于没拦截 - 加判断过滤
options.from !== 'backbutton',避免自己调uni.navigateBack()时也触发,造成死循环 - 示例写法:
onBackPress(options) {<br> if (options.from !== 'backbutton') return false;<br> uni.switchTab({ url: '/pages/index/index' });<br> return true;<br>}
轮询查支付状态时容易卡住或重复请求
前端轮询不是简单设个setInterval就完事,没控制好会发一堆无效请求,或者用户早付完了还在刷。
- 建议用
setTimeout递归代替setInterval,每次查完再决定是否下一次 - 设置最大重试次数(比如5次)和超时时间(比如30秒),避免无限等待
- 查到
status: 'success'后,立刻clearTimeout并跳转成功页;查到'failed'就提示失败并禁用按钮 - 别在轮询期间允许用户重复点击“重新支付”,要用
submiting变量锁住操作
真正难的不是写几行uni.navigateBack,而是理清原生层、JS层、服务端三者之间谁该在哪一步做什么事——App端支付流程里,JS永远是被动接收方,得靠你提前埋好钩子、设好兜底机制,不然用户点一下返回键,你就彻底失去上下文了。











