微信小程序内嵌H5页面,完成微信支付闭环

前言

本文介绍如何在小程序中内嵌H5,并完成微信支付的整个流程闭环。我们知道微信H5支付是通过生成特定的支付链接,并跳转到这个链接去完成支付操作的。但在微信小程序中对于内嵌的页面域名具有白名单限制,如果支付链接是第三方的无法做加白处理。

这个时候我们就得换个思路了,该怎么解决呢?咱们往下看。

实现过程

小程序入口

在微信小程序中新建一个页面,使用web-view组件作为内嵌H5的入口,由于后续支付需要用到appId以及openId信息,因此需要对url做带参做处理

1
2
// page.wxml
<web-view src="{{url}}"></web-view>

url处理逻辑:

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
30
31
32
Page({
data: {
url: ''
},
onLoad: function (options) {
wx.showLoading()
wx.login({
success: res => {
const code = res.code
api.getUserOpenId({
code
}, data => {
const openId = data.bean
const params = {
wxAppletId: 'your appId',
wxAppletOpenId: openId,
...options // 小程序启动路径的参数
}
this.setData({
url: this.stringifyUrlArgs('your h5 url', params)
})
wx.hideLoading()
})
}
})
},
stringifyUrlArgs(url, params) => {
url += (/\?/).test(url) ? '&' : '?'
url += Object.keys(params).map(key => `${key}=${params[key]}`).join('&')
return url
}
})

在页面onload的时候,调用APIwx.login获取code,传递给后端换取该用户的openId,然后将appId、openId、以及启动路径参数拼接到你的H5 url 后面。这个url可以是个短链,方便后续修改不需要重新提交小程序代码审核,缩短发版的时间。只需要去修改该短链对应的H5链接即可。

H5 页面处理

当我们在小程序入口处理好url后,会通过web-view组件进行访问H5链接,这个时候链接上携带了支付所必需的参数,我们上面提到如果这时候H5页面仍然还是调用生成H5支付链接的方式的话,会有页面白名单限制,导致第三方支付链接页面无法访问的情况。

这个时候我们可以绕开这个点,竟然是在小程序内部,我们可不可以使用小程序支付呢?答案当然是可以!

处理的过程:

H5页面请求后端支付接口获取微信小程序支付所必须的参数,这个时候appId和openId都是必要的,其他的信息则根据具体需求而定。

1
2
3
4
5
6
7
8
// 微信小程序支付参数
interface appletPayParams {
timeStamp: 'string', // 时间戳,从 1970 年 1 月 1 日 00:00:00 至今的秒数,即当前的时间
nonceStr: 'string', // 随机字符串,长度为32个字符以下
package: 'string', // 统一下单接口返回的 prepay_id 参数值,提交格式如:prepay_id=***
signType?: 'string', // 签名算法,应与后台下单时的值一致
paySign: 'string' // 签名,具体见微信支付文档
}

由于H5是内嵌在小程序的web-view里面,当成功从后端获取到支付所需的参数后,需要通过web-view 跳到内部小程序的方式,跳转到对应的小程序支付页面进行支付操作,这个时候得使用wx.miniProgram.redirectTo进行处理,将获取到的支付参数encodeURIComponent一下再拼接到链接上。注意url是一个相对路径,如下:

1
wx.miniProgram.redirectTo({ url: `../insure-pay/insure-pay?payData=${encodeURIComponent(JSON.stringify(bean.applet))}` })

小程序支付页

新建一个支付页面,当从web-view内嵌H5页面跳转到支付页的时候,处理支付的逻辑处理,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Page({
onLoad: function (options) {
const payData = decodeURIComponent(options.payData) // 支付参数
let pageSuccessUrl = '../pay-success/pay-success' // 成功页
let pageFailUrl = './insure-repay/insure-repay' // 失败页,重新支付
wx.requestPayment({
...JSON.parse(payData),
success(res) {
wx.redirectTo({
url: pageSuccessUrl,
})
},
fail(err) {
console.log(err)
wx.redirectTo({
url: `${pageFailUrl}?payData=${options.payData}`,
})
}
})
}
})

进入到支付页,会通过wx.requestPayment调起支付,将链接上的参数decodeURIComponent出来,传入API中,可通过回调函数success和fail监听成功和失败,并跳转到不同的处理页面。

总结

大致的流程可以总结为一下几点:

  • 在微信小程序建立一个入口页面,通过web-view内嵌H5,在这个页面onload的时候获取用户的openId以及appId并携带到H5链接上
  • 在H5中获取链接携带的appId和openId,请求后端获取小程序支付所需的参数,并通过wx.miniProgram.redirectTo,从web-view重定向到小程序支付页。
  • 在小程序支付页获取链接上携带的支付参数,通过wx.requestPaymen唤起支付,并处理成功和失败的逻辑。