背景
最近上线了一个新的需求,就是支付版本的升级;何为升级?那就是在原有的基础上扩展添加了不同版本的支付功能;既保持了原有正常的功能,又扩展了一些第三方的支付版本;
先说说,为什么要升级,原有的版本会有什么弊端,升级之后支持了哪些或者扩展了哪些?
起初的支付,是通过后端获取到对应的参数,然后进行api
唤起支付面板进行支付,不过这样有一个弊端就是微信支付会有限制额度的说法,如果支付金额过大,那么可能会支付不了;
年前上线了商家商户端
小程序,又赶上支付版本的升级,接着俩者就结合在一起了;本来拿到该需求很快就该上手开发的,但是由于其他需求版本,开始时间延迟了;所以到后面的开发时间也就压缩了,一周的开发时间,到周五上线的;
那么研究了一下这个流程,其实也没什么难度,就是一些细节是比较多的;对于参数的加解密,数据的加解密等等是比较麻烦的;
其中第三方接口会有加解密的一个过程,这个加解密最后丢给了后端,直接拿接口获取,加解密放在前端的话细节太多,有点浪费时间了;
思路
接下来大致说下实现的思路:
vue
开发一个H5
中转页面,而这个页面也会是之后所有支付的页面,包括扫码支付,下单支付等等;
- 中转页面兼容参数,数据兼容,
query
参数兼容;因为在后台在生成链接渲染在前端页面上,手机扫码去支付会有url
参数解析异常的问题,针对该问题进行优化兼容;
- 对于预支付返回的支付参数是不统一的,那就只能存在缓存或者
query
参数,对该对应的字段进行加密;
- 根据后台配置的商家支付版本判断,是否需要原生微信支付或者是跳转小程序支付;
那么大致流程图如下:

细节
不过刚开始有一个问题,那么vue
如何跳转小程序呢?
看了看微信官方的开发文档, 直接看到了开放标签
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| <wx-open-launch-weapp id="launch-btn" appid="wx12345678" path="pages/home/index?user=123&action=abc" > <script type="text/wxtag-template"> <style>.btn { padding: 12px }</style> <button class="btn">打开小程序</button> </script> </wx-open-launch-weapp> <script> var btn = document.getElementById('launch-btn'); btn.addEventListener('launch', function (e) { console.log('success'); }); btn.addEventListener('error', function (e) { console.log('fail', e.detail); }); </script>
|
不过使用该开放标签,首先需要设置对应的wx.config
, 将对应的开放标签配置好
, 格式如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| wx.config({ debug: true, appId: '', timestamp: , nonceStr: '', signature: '', jsApiList: [], openTagList: [] })
wx.ready(function () { });
wx.error(function (res) { });
|
不过要说明一点,就是只有config:ok
的时候才会渲染对应的按钮去打开小程序;这里需要一些兼容问题;但是很坑的地方就是text/wxtag-template
样式只能写在这个里面,不能写在页面中style
中;下面是项目中用到的部分代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| <div style="position: relative;"> <wx-open-launch-weapp id="launch-btn" style="position: absolute; top: 1.6rem;left:0px;right: 0px;" :username="username" :env-version="wxMpEnvVersion" :path="jumpWxMpPath" > <div is="script" type="text/wxtag-template" style="display: block;"> <div is="style"> .pay-button {position: relative;display: inline-block;boxSizing: border-box;background-color: #07c160;color: #fff;height: 44px;outline: none;border: 1px solid #07c160;border-radius: 4px;width:100%;font-size:14px;} </div> <button class="pay-button" @click="handlerToPay('applet')"> 立即支付 </button> </div> </wx-open-launch-weapp> </div>
|
省下的就交给接口,拿到对应的版本,V1, V2, V3
等等;根据不同的场景使用,
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 33 34 35 36
| wxJsBridge({ 'appId': wxJsBridgeJson.appId, 'timeStamp': wxJsBridgeJson.timeStamp, 'nonceStr': wxJsBridgeJson.nonceStr, 'package': wxJsBridgeJson.package, 'signType': wxJsBridgeJson.signType, 'paySign': wxJsBridgeJson.sign }, () => {})
getUrlQuery() { const { param = '' } = this.$route.query || {} const hasParam = Object.keys(this.$route.query).includes('param') return hasParam ? handlerQueryParams(param) : this.$route.query }
export function handlerQueryParams(url) { const splitArr = url.split(";").filter(item => item !== ""); const query = {}; splitArr.forEach(item => { let hasSq = item.indexOf(":"); if (hasSq !== -1) { let key = item.substr(0, hasSq); let val = item.substr(hasSq + 1, item.length - 1); query[key] = val; } });
return query; }
|
对于不同支付的版本,当然也会有不同的按钮,例如v1
版本的是原生支付,v2
的是开放标签,那么就需要对应的判断了:
1 2 3 4 5 6 7 8 9
| isPayWeapp() { return ['V2', 'V3'].includes(this.version) },
isPayWx() { return ['V1'].includes(this.version) }
|
对于小程序那边的处理,也很简单,就是获取到对应的 query 参数,根据版本进行加解密,获取对应的支付计算等等;
因为涉及相关的第三方就不介绍那么多了;