App端支付回调收不到是因为uni.onPaymentComplete仅支持小程序,App需原生层主动通知JS;iOS用uni.postMessage,Android用自定义广播或Activity回传,且须配置原生插件与微信/支付宝相关参数。
App端完成支付后,原生层并不会自动调用JS层的回调函数,uni.onPaymentComplete 它只对微信小程序有效,App端完全不支持。这个平台能力缺失,正是最容易被误判为“逻辑写错”的根本原因,并不是代码出了问题。
实际处理时,必须由原生层主动通知JS:iOS使用uni.postMessage,Android使用uni.getEnv并结合自定义广播或Activity结果回传。由于uni-app官方SDK默认不开放这些通道,需要自行补充。
manifest.json中选中了「使用原生插件」,否则iOS侧的uni.postMessage调用将静默失败uni.requestPayment调起支付宝/微信,build时一定要确认已勾选对应原生支付插件,例如Alipay、Wechat,否则success回调始终不会进入uni.onThemeChange或uni.onShow监听支付返回,因为App从后台重新进入前台时,页面生命周期可能已经重置,进而丢失状态不要等待“回调”,需要把跳转处理提前放到uni.requestPayment的success回调中。这个回调在App端会于支付调起成功时立即触发,并不表示用户已经完成付款,但它是唯一能够稳定获取的时机。
之后由服务端主动通知(Webhook),并以客户端轮询作为兜底。前端跳转时应携带订单号,进入页面后立即查询一次支付状态,避免白屏等待。
uni.requestPayment的success里立即uni.navigateTo({ url: '/pages/order/detail?order_id=' + orderId })
onLoad中立刻发起uni.request({ url: '/api/pay/status?order_id=' + orderId })查状态status: 'success' | 'pending' | 'failed',不能只返回HTTP 200便结束Android环境下微信支付回调失败,有90%的情况是没有配置AndroidManifest.xml中的WXPayEntryActivity,或者包名/签名与微信开放平台注册的信息不一致。
uni-app打包时,相关内容会由原生插件生成;但只要手动修改过android/app/src/main/AndroidManifest.xml或升级插件版本,关键声明就很容易被覆盖。
AndroidManifest.xml内存在<activity android:name=".wxapi.WXPayEntryActivity"节点,并且exported="true"
build.gradle中的applicationId是否与微信开放平台填写的内容一致,注意:不是package,而是applicationId)errCode:-1
keytool -list -v -keystore xxx.jks -alias xxx取得MD5,再去除冒号、转换为小写,且不能带空格iOS App完成支付时会唤起微信/支付宝App,随后借助Universal Links或URL Scheme返回你的App。然而uni-app的onShow未必可以捕捉这次唤回,尤其用户中途切换过其他App时,系统可能遗失启动参数。
更稳定的处理方式是:调起支付前,先将订单ID写入uni.setStorageSync('pending_order_id', orderId),等页面onShow时读取并查询状态,完成查询后马上uni.removeStorageSync清理。
uni.getStorage异步读取后再作判断,应同步读取以规避竞态pending_order_id存在并不等于支付成功,必须向服务端查询onShow不会触发,只能通过服务端推送唤醒,并需额外接入APNs支付状态对一致性要求很高,因此业务结果必须始终以服务端为准。客户端的各种“本地判断”只能作为改善体验的临时措施,不能负责保证业务正确性。