序
最近,公司发布一款新产品,需要在 iOS App 上集成微信 H5 支付(嗯,我知道微信官方建议我们不要在APP环境下使用H5支付)。用到的关键步骤如下,参考文档微信支付-H5支付
- 由我们后台向微信支付发起统一下单请求
- 统一下单接口返回支付相关参数给商户后台,拼接成支付跳转url,商户通过此 url 去访问微信支付中间页
- 中间页会生成一个“weixin://wap/pay?” + 参数 这样一个scheme去调起微信客户端走到下单页面。
补充说明:
跳转url(mweb_url)示例: "https://wx.tenpay.com/cgi-bin/mmpayweb-bin/checkmweb?prepay_id=wx201711302016180757ed93760351075895&package=2940730744"
scheme 示例: "weixin://wap/pay?prepayid%3Dwx201711302016180757ed93760351075895&package=2940730744&noncestr=1512044179&sign=df7fb3081e1eec19e5e3640ea97d31c3"
那么问题来了
再次声明,此处所说的问题在H5环境下并不是问题。我们讨论的是iOS上的App环境下使用微信H5支付的跳转问题
以 唯品会 为例:在非 safari 浏览器下(比如 chrome 浏览器)打开唯品会 M站,走到提交微信支付订单,网页调起微信支付,尽管你设置了 redirect_url(回跳地址)并且关闭 safari,但是取消支付或者支付完成之后微信还是会跳回 safari 浏览器打开你的回调页面,而不是跳转至 chrome。这个时候就尴尬了,你得自己切换回到 chrome。如果我是用户,我至少会有点懵逼。
以 手机京东 为例:操作步骤同上,但是取消支付或者完成支付之后,不会跳回 safari,而是关闭支付页面,继续留在微信。虽然没有直接回到 chrome,但是这总比突然去打开 safari 更让人容易接受。
以上情况属于:
- 特殊的运行环境:iOS上的原生App或者非safari浏览器(UC浏览器也不会跳回safari)
- 指定的支付环境:微信H5支付
- 奇怪的回跳逻辑:有的会打开safari,而有的并不会
我们的期望肯定是能回跳到发起微信支付的 App 是最好的,不过在这之前需要先弄清楚为什么会出现这样的回跳逻辑差异。
分析差异
支付流程
首先得分析两个M站的微信支付流程吧,上面提到过关键步骤就是:
普通的支付流程:后台发起统一下单请求 –> 微信支付接口返回给你相关参数 –> 根据参数去拼接一个 mweb_url 的地址,你需要做的就是 location.href = mweb_url –> 这个页面里会生成一个 微信 scheme 地址,调起微信客户端支付。这是普通商户的,也是唯品会的H5支付流程。
通过抓包得来的 mweb_url 地址页面的关键 js 内容如下,微信 scheme 会在这个页面自动生成:
1 | <script type="text/javascript"> |
不过,京东并不是这么做的。
京东的微信支付流程:进入下单页面选择微信支付 –> 前端发起 GET 请求后台 –> 京东后台直接返回了微信 scheme 地址,(是直接返回了,而不是通过访问拼接的mweb_url地址做跳转,这一步普通商户也可以做到,但是可能也还是有差异的) –> 根据此地址在当前支付页面 append 一个 A 标签,塞进此地址,自动触发点击事件 –> 调起微信支付,M站的支付页面经过5秒的延时会弹出一个mask弹窗来触发查询支付订单操作。
微信 scheme
唯品会的:
weixin://wap/pay?prepayid=wx20171204195948d0d40803800224970868&package=121328958&noncestr=1512388788&sign=545a16c77fd27d98a3eaf23751ec6104
手机京东的:
weixin://wap/pay?appid=wxae3e8056daea8727&noncestr=24bfde45b5790f04b1d096565157f6a4&package=WAP&prepayid=wx201712041702047d0d37c44f0850922294×tamp=1512378124&sign=89BE2251D47BF1EEB48CA3C8D62A1967
京东多了 appid,timestamp 参数,并且京东的 package 参数指定为 WAP,这是通过多次抓包得到的验证,package是固定的并且目测所有不发生回跳safari的都固定为WAP。appid 是微信分配的公众账号 ID,这个值每个商户是都有的,所以我们想当然的就这样去模仿京东的微信 scheme,但是到了微信下单页面,我们看到了这个报错:
分析结论
很显然这么做是行不通的,既然让你提供 appid 参数,肯定会做出相应验证。所以由此说明微信团队应该是有白名单的。
于是相继测试了许多大站的M站微信 H5 支付,目测 京东,美团,猫眼电影,大众点评,饿了么 都在白名单列。其他的类似唯品会,蘑菇街,聚美优品,一号店,去哪儿,途牛,携程都会回跳至 safari。
不算完美的解决办法
目前针对这种情况,我们是无能为力的,自己开发的 iOS App 如果走的是微信H5支付,比如 web app,只能通过在safari 打开的回跳地址中自行添加自己应用的 scheme 地址调起应用,看过大多数 web app 都是这么做的。
尾
虽然折腾了这么多,去看各大站的微信 H5 支付流程,去抓包微信跳转的 mweb_url 地址和微信 scheme 地址做对比和测试,去改后台请求微信支付接口的参数等等,这些都行不通,但是至少弄明白原来微信H5支付还有这种操作,希望能为一些开发者解惑。