app端扫码支付不能直接用uni.scancode,它仅识别二维码内容,需解析url后调用原生能力唤起微信/支付宝收银台,且须配置白名单、校验签名、后端生成合法链接,并以服务端通知为准校验支付结果。

App端扫码支付不能直接用uni.scanCode
很多人以为调用uni.scanCode扫出二维码就能完成支付,其实不是。这个 API 只负责「识别二维码内容」,它不会自动跳转到支付宝/微信的收银台,更不会触发支付动作。你扫出来的大概率是一串 URL(比如 alipay://... 或 weixin://...),但 App 端默认不支持直接唤起这些协议——尤其在 iOS 上基本被拦截,在 Android 上也依赖原生层注册 intent-filter 或 URL Scheme。
真正能走通的路径是:扫码 → 解析出支付链接 → 调用原生能力打开对应支付客户端。
- iOS 必须提前在
info.plist中声明LSApplicationQueriesSchemes,加入alipay、weixin等白名单,否则uni.openURL会静默失败 - Android 需确保目标 App 已安装,且签名匹配(特别是支付宝对包名+签名双重校验)
-
uni.scanCode返回的result字段可能是 URL、纯文本或 base64,要先做正则判断再分流处理
扫码后怎么正确唤起微信/支付宝收银台
不能直接 uni.openURL('weixin://...') 就完事。微信和支付宝对唤起协议有严格限制:
- 微信:仅支持
weixin://wap/pay?开头的链接,且必须由微信官方生成(通常来自统一下单接口返回的paySign和prepay_id),自己拼的链接会被拒绝 - 支付宝:支持
alipay://platformapi/startapp?saId=10000007&clientVersion=3.7.0.0775&qrPayUrl=...这类格式,但qrPayUrl必须是支付宝网关返回的有效支付链接(含 sign 参数),临时构造的无效 - 所以实际流程是:扫码 → 提取订单号或支付 ID → 调用后端接口(如
/api/pay/confirm?orderNo=xxx)→ 后端查库并调用微信/支付宝 SDK 生成合法唤起链接 → 前端用uni.openURL或原生模块跳转
为什么推荐用原生插件而不是纯 JS 实现
因为系统级协议唤起在不同平台表现差异极大:
- iOS 上
uni.openURL对alipay://的支持不稳定,经常白屏或无响应;必须用plus.runtime.openURL+ 自定义 URL Scheme 拦截才能保证成功率 - Android 上部分厂商 ROM(如华为 EMUI、小米 MIUI)会屏蔽非官方来源的支付协议调用,需要在
AndroidManifest.xml显式配置<intent-filter></intent-filter> - 人脸/指纹等快捷支付通道(如支付宝的“刷脸付”)完全无法通过 H5 或 WebView 触达,只能靠原生 SDK
-
uni-app 官方插件市场里的
alipay-pay、wxpay插件已封装好这些兼容逻辑,比自己写桥接代码少踩 80% 的坑
扫码支付的实际调用链路要分三端协同
前端只是其中一环,漏掉任一环节都会失败:
- 用户扫码 → 前端拿到原始字符串(如
https://qr.alipay.com/xxx)→ 提取xxx作为订单标识 - 前端请求后端接口
POST /api/pay/scan?qrId=xxx→ 后端根据该 ID 查询订单状态,并调用微信/支付宝服务端 SDK 发起预下单(生成prepay_id或pay_url) - 后端返回唤起链接(如
alipay://platformapi/startapp?...)→ 前端用plus.runtime.openURL调起,失败时降级为 web-view 展示付款码 - 支付结果不能依赖前端回调(容易丢失),必须以服务端异步通知(
notify_url)为准,前端轮询或监听 uniCloud 云函数事件做最终确认
最容易被忽略的是:扫码后的订单状态校验必须由后端完成。前端传过来的 qrId 如果没做幂等和时效检查(比如 15 分钟过期),攻击者可以反复重放扫码链接,导致重复扣款。











