uni-app跨端开发之生成小程序码和调试scene参数爬坑指南
摘要:生成微信小程序码的前提条件是小程序必须要上线,相信很多开发者光是看到这一条就已经震惊到了。而且小程序码中的scene最多可以携带32个字符,关键是难调试。另外,虽然前端也可以自己生成微信小程序码,但有坑......
前段时间,公司的小程序中有一个分享小程序码邀请好友的功能。前前后后也踩过不少坑,然后就有了这篇笔记。如果看官正在因生成微信小程序码或调试scene参数而苦恼,不妨继续往下看看,或许这篇文章能够帮助到您哟。
1、如何生成微信小程序码
在微官方文档中,一共提供了三种生成小程序码的API接口,场景和限制各不相同。如下表格:
API | 解释 | 携带参数 |
---|---|---|
wxacode.createQRCode访问文档 | 获取小程序二维码,适用于需要的码数量较少的业务场景。永久有效,有数量限制 | path,最大长度 128 字节 |
wxacode.get访问文档 | 获取小程序码,适用于需要的码数量较少的业务场景。永久有效,有数量限制 | path,最大长度 128 字节 |
wxacode.getUnlimited访问文档 | 获取小程序码,适用于需要的码数量极多的业务场景。永久有效,数量暂无限制。 | scene, 最大32个可见字符 |
wxacode.getUnlimited
。然后,一系列的坑就随之而来。若看官在项目中使用的是前两种接口,可以不用继续往下看了。
1.1、前端生成 VS 后端生成
在刚开始的时候,我使用的是前端生成的方式。事实证明,这种方式是错误的,尽管前端也可以成功生成小程序码。在小程序中直接访问文档中给出的接口地址https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=
,
结果返回的错误码为41030
。查看文档得知,此错误码表示小程序未发布。再查看官方的文档,发现明确指出path
必须是已经发布的小程序存在的页面(否则报错)。如图:path必须是已经发布的小程序存在的页面.png
不发布又生成不了小程序码,发布的话相当于发布的版本中生成小程序码的功能不能使用,简直是个流氓!后来又拖了好久,某日,我决定发版并测试下小程序码。
发版很顺利,大概在提交后40分钟左右的时候,微信上来消息说发版通过了。我当时激活的不得了,立即在本地环境上跑了下小程序,点击分享按钮发现没反应。查看请求,一切正常且请求返回的是一张图片,当时一脸黑人问号...... 如图:getwxacodeunlimit接口成功返回小程序码但前端无法渲染.png
1.2、返回二进制图片数据后如何显示到页面上?
什么鬼?你直接给我图片,我怎么显示到页面上???
后来才知道,原来请求时需要设置responseType: 'arraybuffer'
,此时接口在成功时会返回图片的二进制数据。然后前端这边再通过uni.arrayBufferToBase64(arrayBuffer)
即可将二进制图片转换成base64,最终成功显示在页面上。如图:解析二进制图片时需要设置arraybuffer和arrayBufferToBase64.png
到目前为止,整个生成小程序码的操作全靠前端完成。为了防止生成小程序码失败,我还给项目镀金,添加了一个刷新的功能。就是当生成失败时,用户可以点击小程序码占位区进行手动生成。效果如图:手动刷新小程序码.gif
2、让人头大的scene
2.1、拼接scene参数
由于受接口getUnlimited
的限制,page
只能是纯路径,而想要携带参数只能放到scene
中。这个方案看似还不错,至少解决了携带参数的问题。但携带参数长度有限制,且需要根据情况进行转码。好在我们分享的参数不需要转码,直接拼接即可。当时我们的代码是这样的:this.scene = '?invite=' + res.data.key /* 邀请码中携带的参数 */
2.2、扫码后解析scene参数
按照正常流程,上一步生成了带参数的小程序码。当用户长按识别了小程序码或通过扫码进入小程序时,我们在指定的path
页面中需要解析scene参数。若不解析的话,我们就无法做到数据统计,也就无法在该用户的邀请记录中清晰的展示邀请了哪些用户。如图:分享小程序码后可以查看邀请记录.png
在页面生命周期中,onLoad
可以获取到当前地址中携带的参数。所以,解析scene的操作要在onLoad函数中进行。由于我们的小程序中多处用到了分享功能且path
也不同,所以我把解析scene
的代码封装成了一个方法。大致代码如下:
- /* 将url中的参数转成对象{key:value}的形式,方便读取 */
- function urlParams (scene) {
- const str = decodeURIComponent(scene).replace('?', '&')
- let strArr = str.split('&')
- strArr = strArr.filter(item => item)
- const result = {}
- strArr.filter(item => {
- const key = item.split('=')
- result[key[0]] = key[1]
- })
- return result
- }
调用的话也非常简单,示例代码如下:
- import { urlParams, } from '@/common/util' /* 先引入方法 */
- onLoad (options) {
- if (Object.keys(options).length) {
- const { invite, scene } = options
- if (scene) { /* 扫码进来 */
- const sceneObj = urlParams(scene)
- if (sceneObj.invite) {
- this.invite = sceneObj.invite /* 邀请码 */
- }
- }
- /* 正常情况,包括H5端、APP端 */
- if (invite) {
- this.invite = invite
- }
- ...... /* 其他代码 */
- }
- }
这样,当用户扫码进时我们就能成功的解析出小程序码中携带的参数了。然后需要上报就上报,该干嘛干嘛,一切看似都很美好。但这只是我们假设的顺利场景,并没有经过真正的校验。
2.3、解析scene
如何校验呢?虽然我们本地是可以成功的生成了小程序码,但当你分享给同事后,同事识别小程序码进入时会直接进入到了线上版本。划重点哈,是跳转到了线上版本。前面已经说了,我们线上版本中对应的path
页面还没有添加解析scene
的代码哈。
那怎么解决这个问题呢?最笨的方法就是:把本地的小程序打包发版,然后再测。而这个方法的弊端也很明显,如果我们在封装urlParams
函数时考虑不周或者是上报接口还不确定,再或者scene中有字符需要转码而忘记了转码,那就会导致我们面临不停发版来改bug的困境!再想想去年的自己,真是被自己给蠢哭了!
那有没有更好的解决方案呢?
2.3.1、开发者工具中选择二维码编译
答案是有的。在微信小程序开发者工具中,我们可以通过上传二维码实现本地解析。如图:在微信开发者工具中通过二维码编译可直接调试携带参数scene.png通过上图可以看到,成功的解析并在login.vue
文件中的onLoad
函数中第115行监听到了scene
。本地调试比起线上发版,是不是非常便利呀!
2.3.2、开发者工具中构造scene编译
除此之外,我们也可以通过在本地直接构造scene
参数来模拟扫码访问,节省调试时间。相关代码结构如下:scene=encodeURIComponent(参数)
如图:在开发者工具中手动构造scene.png
现在,我们已经可以在本地肆无忌惮的构造scene
和解析scene
,再也不用靠发版来调试了,简直爽歪歪!那事情是不是就已经结束了呢?显然没有。毕竟我们的项目最终还是要上线的,那再发一版到线上测试下效果吧!
3、发版后不显示小程序码?
通过HBuilder X将项目进行打包,打包完毕后继续上线。由于每次审核需要一些时间,看官可以先去干点别的。
大约又过了40来分钟,微信上再次提醒审核通过了。我依旧是迫不及待的对分享小程序码进行了测试,结果翻车了!小程序码不显示!!即使我通过手动刷新也不显示!!!此时的我一脸懵逼!明明测试版没问题呀,怎么到线上就翻车啥都不显示呢?而且开启调试后,接口也不报错!这回我彻底懵逼了......
如果看官也遇到了此问题,想必看官跟艺灵的做法是一样的,即:生成二维码的操作由前端完成。其实这个操作是错误的,尽管微信官方并没有特殊强调必须要由后端生成。
3.1、必须小程序码由后端生成
既然需要后端生成,那就让后端老哥写个接口呗。我把要携带的scene
参数和要访问的path
参数传递给他的接口,他拿去请求接口生成小程序码并返回给我,我这边再使用uni.arrayBufferToBase64()
对返回数据进行解析即可。
这里需要注意的是,我们在请求后端接口的时候同样需要在请求中带上arraybuffer: true
,若看官使用的是原生的uni.request
或wx.request
的话,需要添加responseType: 'arraybuffer',
才能成功的解析二进制图片,否则解析不成功哦!
四、代码演示
由于项目代码比较复杂,这里只简单做下展示。
- /* 获取小程序码 */
- handleGetXcxQrcode () {
- const data = {
- scene: this.scene, /* url中携带的参数 */
- page: 'pages/user/login' /* 扫码后跳转的访问页面 */
- }
- uni.request({
- url: '后端生成小程序码后暴露给前端的API地址',
- data: data,
- responseType: 'arraybuffer', /* 必须 */
- success: (result) => {
- const res = result.data
- uni.hideLoading()
- if (res.errcode === 41030) {
- setTimeout(() => {
- uni.showToast({ title: '请先发布小程序', icon: 'none' })
- }, 0)
- } else if (res.errcode === 45009) {
- setTimeout(() => {
- uni.showToast({ title: '调用频繁', icon: 'none' })
- }, 0)
- } else {
- const url = 'data:image/png;base64,' + uni.arrayBufferToBase64(res)
- if (uni.arrayBufferToBase64(res)) {
- this.wxQrcode = url
- }
- }
- }
- })
- },
4.1、源码下载
如果您想查看完整源码,可以猛戳下方的链接进行访问。
- 网址: 戳我前往github查看源码
五、最后
最后来总结下生成微信小程序码需要注意的事项:
1、必须由后端提供小程序码,前端虽也能直接生成,但线上版本无法生成;
2、在请求中需要添加responseType: 'arraybuffer',
参数;
3、在请求成功后前端无法直接显示图片,需要使用uni.arrayBufferToBase64(res)
将 ArrayBuffer
对象转成 Base64
字符串;
4、通过微信开发者工具中提供的二维码编译和编译模式,我们可以在本地构造和解析小程序码,无需频繁发版。
转载声明:
若亲想转载本文到其它平台,请务必保留本文出处!
本文链接:http://www.yilingsj.com/xwzj/2020-12-26/uni-app-wxacode-getUnlimited.html