小程序内嵌复用H5并拉起微信支付解决(替代)方案

笔者更新于2019年7月30号:以下文章内容已不适用,微信已校验完全下单wxappid和支付wxappid必须是同一个wxappid, 所以以下文章仅供参考,已经不是替代方案了,看来之前确实是漏洞。

自从小程序出来后,你肯定有这样的想法。小程序内部分页面好想复用以前的H5,重复的去开发浪费了大量的时间和精力。 但是内嵌在小程序中的H5不支持拉起微信支付。也就是说小程序内,小程序嵌入的H5内只能调用小程序支付。

于是呢,我就想到了这么一个办法。有些山寨,并且不官方(官方当然是希望你直接在小程序内完成一切,下单到支付),但是却可以解决问题。O(∩_∩)O~~☁️❤️


解决方案

我们可以用小程序的 web view 能力嵌入 H5, 嵌入后,在 H5 中进行支付下单,得到参数如 : timeStamp, nouncestr, signType,paySign 等等参数。然后再通过 wx.miniProgram.navigateTo 跳转到一个小程序页面,在这个页面进行调用 wx.requestPayment 进行拉起支付。拉起支付后,可以再跳到小程序结果页。

如果你担心通过 navigateTo 的 url 传参有不安全的问题,可以自己对参数进行加解密。

亲测是可以行得通的。

你也可以直接支付完成,调到你自己的小程序的支付结果页等工作。在小程序的支付结果页中,你还可以设置按钮,再来引导用户是进入小程序首页,还是刚刚你跳转的H5的页面等等。


遇到的问题

我想把下单的参数以 JSON.stringfy(obj) 的形式传过去,发现参数一直很奇怪的被截断。看到其他有的开发者也遇到了类似的问题。

也就是说下面这种方式是有问题的,以为是特殊字符导致的,但是发现 encode 以后还是被截断。我觉得有可能是小程序本身的问题。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// H5 内
wx.miniProgram.navigateTo({
url: `/pages/wxpay/wxpay?info=${JSON.stringify(obj)}`
})

// 小程序内
Page({
onLoad(options) {
// 因为被截断了,所以这里 JSON.parse 报错
const data = JSON.parse(options.info)
const obj = {
'timeStamp': data.time,
'nonceStr': data.nounce,
'package': data.package,
'signType': 'MD5',
'paySign': data.sign,
};

wx.requestPayment({
...obj,
success(res) {
console.log('success', res)
},
fail(res) {
console.log('fail', res)
}
})
}
})

后来老老实实的用多个参数穿参sign=xxx&signature=xxx&noncestr=xxx,发现 package 中的=后面的部分也被截断了。 encodeURI, encodeURIComponent 都没用。

这里没有想清楚。看了文档和查了资料也没弄清楚小程序在这里面做了什么事情。先放放,把方案跑不跑的通解决。

所以干脆就把 prepay_id= xxx 后面的 xxx 单独取出来。后面调用 requestPayment 再拼上。


最终代码

最后我测试通过的代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// H5 内
wx.miniProgram.navigateTo({
url: "/pages/wxpay/wxpay?time=" + info.wx_time + "&nounce=" + info.wx_noncenum + "&package="+info.wx_package.split("=")[1] + "&sign=" + info.wx_sign
})

// 小程序内
Page({
onLoad(options) {
const obj = {
'timeStamp': options.time,
'nonceStr': options.nounce,
'package': "prepay_id=" + options.package,
'signType': 'MD5',
'paySign': options.sign,
};

wx.requestPayment({
...obj,
success(res) {
console.log('success', res)
},
fail(res) {
console.log('fail', res)
}
})
}
})

总结

相较于正常的直接在订单页下订单,这里多了一步,就是从H5跳过来后,还要拉起小程序的一个支付页,单独拉起支付框。

体验当然是没有完全在小程序中,不嵌入H5好的。如果是要快速迭代开发的话,这也是一种方法。

总之知道了这是一种替代的解决方案,或者说一种没有办法的办法。📚🌲还是很开心的。

最后欢迎来到微信->钱包入口的Qb充值入口来充各种游戏币,Qb, 包月服务哦。有的时候还有优惠。