微信小程序获取不到unionid还有小程序无法解析JSON字符串的问题
2018-02-08 12:05
1106 查看
一、背景
这边在开发小程序的时候,发现使用wx.login给出的code去请求微信服务器的时候,有时候能取到unionid,有时会取不到unionid。这就造成很多业务上的不便,因为我们在用户第一次授权进来的时候,都是通过unionid来确定这是哪个用户,是否需要注册等。二、原因
如果开发者拥有多个移动应用、网站应用、和公众帐号(包括小程序),可通过 unionid 来区分用户的唯一性,因为只要是同一个微信开放平台帐号下的移动应用、网站应用和公众帐号(包括小程序),用户的 unionid 是唯一的。换句话说,同一用户,对同一个微信开放平台下的不同应用,unionid 是相同的。同一个微信开放平台下的相同主体的 App、公众号、小程序,如果用户已经关注公众号,或者曾经登录过App或公众号,则用户打开小程序时,开发者可以直接通过 wx.login 获取到该用户UnionID,无须用户再次授权。(解读:用户如果没有登录过app,也没有登录过公众号,也没有关注过公众号的情况下,小程序中通过 wx.login 是获取不到 unionid的)
那就很明确了,可能是在用户没有关注公众号的情况下,他们第一次进入小程序,此时使用wx.login是无法获取到unionid的。因此才会造成错误。
三、解决方案
1、微信官方文档大家先看下微信关于wx.getUserInfo的解释,在这个文档上,我们可以知道,通过getUserInfo获取到的encryptedData 还有iv是微信给出的加密数据,我们可以通过解密等方法,获取到用户的unionid。
加密解密算法点这里
2、重写wx.login方法
// 登录 wx.login({ success: res => { // 发送 res.code 到后台换取 openId, sessionKey, unionId this.globalData.code = res.code; if (this.globalData.code) { //发起网络请求 wx.getUserInfo({ success: res => { // 可以将 res 发送给后台解码出 unionId var encryptedData = res.encryptedData; var iv = res.iv; wx.request({ url: 'https://你的后台接口', data: { code: this.globalData.code, encryptedData:encryptedData, iv:iv }, method: "POST", dataType:'json', success: res => { var data = res.data; data = data.replace(/\ufeff/g, "");//重点 var jj = JSON.parse(data); console.log(jj); if (jj.code == 200) { console.log(jj.data.token); this.globalData.token = jj.data.token; if (this.tokenCallback) { this.tokenCallback(jj.data.token); } wx.setStorage({ key: "token", data: jj.data.token }) } } }) // 由于 getUserInfo 是网络请求,可能会在 Page.onLoad 之后才返回 // 所以此处加入 callback 以防止这种情况 if (this.userInfoReadyCallback) { this.userInfoReadyCallback(res) } } }) } else { console.log('获取用户登录态失败!' + res.errMsg) } } });
解释:
1、这里是先获取code,因为后面要通过code来获取session_key,这部分参考加密解密算法,就能知道都需要什么参数了。
2、把获取到的code放入到全局的code变量中。之所以这么做是因为我用wx.login获取到code之后,发现在wx.getUserInfo方法中无法直接使用,因此就放到全局变量中。
3、请求我们的https接口,后台部分加上自己的逻辑即可。
3、后台部分
1)引入微信官方给出的php加密文件,里面包含,demo.php,wxBizDataCrypt.php,还有一个errorCode.php文件。
2)我这里是放到laravel框架的app/Libs/PHP文件下了,所以引入的代码:
require_once base_path() . '/app/Libs/PHP/wxBizDataCrypt.php';
3)获取unionid的关键代码
//实例化加密算法类 $pc = new \WXBizDataCrypt(env('xcx_appid'), $session_key); $errCode = $pc->decryptData($encryptedData, $iv, $data ); if ($errCode == 0) { //微信返回的是字符串,我们这里把它变成JSON对象 $data = json_decode($data); //获取到unionid $unionid = $data->unionId; } else { return MyResponse::error(40002,'获取unionid失败'); }
4、按照以上的步骤,就能获取到用户的unionid了
四、碰到的问题
1、返回的JSON字符串,微信不能正常获取//以下是我返回的数据 {"code":200,"detail":"success","data":{"token":"0911678b4579457xxxxxa89d0"}}
这部分数据微信小程序不能识别它,也不能通过res.code等方法来获取。我们采用JSON.parse(),结果报错,说明这段代码也不是标准的json字符串
2、原因
百度之后,看到一个博主说的很好,这种情况是因为BOOM头的原因。
如图:
通过微信开发工具调试模式下Network看到返回的东西前面有两个小红点,鼠标放上去弹出\ufeff,搜索之,非法字符?
3、去掉boom头代码
//替换掉boom头,转换为空 var data = res.data; data= data.replace(/\ufeff/g,"");//重点 var jj = JSON.parse(data); console.log(JJ)
打印之后,我们就发现,已经变成json对象了。此时我们就可以进行正常的取值了。
{code: 200, detail: "success", data: {…}}
参考链接:https://www.jianshu.com/p/ad8a0664d642
参考链接:http://blog.csdn.net/weixin_40024174/article/details/78905288
整体来说,我个人觉得小程序的bug挺多的。有时候出问题,过个几分钟自己就好了。。。我也是很无奈。加油吧。
end
相关文章推荐
- 关于微信小程序获取unionid的问题
- 详解微信小程序 登录获取unionid
- 微信小程序开发之真机测试 地图定位 map API 无法获取当前位置的问题
- 部分小程序无法获取UnionId原因
- 微信小程序java实现AES解密并获取unionId
- 微信小程序-获取用户session_key,openid,unionid - 后端为nodejs
- 微信小程序:wx.navigateTo中url无法跳转问题(app.json中配置的tabBar与wx.navigateTo中url引用相同页面导致)
- 原创:微信小程序java实现AES解密并获取unionId
- linux服务器wget无法成功解析域名及程序获取外网数据不稳定问题
- 微信小程序 --- e.currentTarget.dataset.id 获取不到值
- 微信小程序开发之真机测试 地图定位 map API 无法获取当前位置的问题
- 微信小程序:wx.request之post请求后端无法获取数据的问题
- 微信小程序开发之真机测试 地图定位 map API 无法获取当前位置的问题
- 原创:微信小程序java实现AES解密并获取unionId
- 解决微信小程序中Date.parse()获取时间戳iOS无法获取的问题
- 原创:微信小程序java实现AES解密并获取unionId
- 解决微信小程序中在其他页面无法使用app.js中获取的userInfo或openid的问题
- 解决mysql5.7及以下版本无法解析json字符串的问题