背景
由于 PC/macOS 平台「头像昵称填写能力」存在兼容性问题,对于来自低于2.27.1版本的访问,小程序通过 wx.getUserProfile 接口将正常返回用户头像昵称,插件通过 wx.getUserInfo 接口将正常返回用户头像昵称。
考虑到近期开发者对小程序用户头像昵称获取规则调整的相关反馈,平台将接口回收的截止时间由2022年10月25日延期至2022年11月8日24时。
调整后,wx.getUserProfile用户昵称将返回'微信用户',头像返回未知头像。
小程序用户头像昵称规则调整公告
由于上述调整的存在, 我发现自己数据库多了不少,**'微信用户'**的账号存在。
(nickName=微信用户, avatarUrl=https://thirdwx.qlogo.cn/mmopen/vi_32/POgEwh4mIHO4nibH0KlMECNjjGxQUq24ZEaGT4poC6icRiccVGKSyXwibcPq4BWmiaIGuG1icwxaQX6grC9VemZoJ8rg/132, gender=0, country=, province=, city=, language=), code=0e1abNFa1dBwRG0lnoJa18qT0i2abNFk)
接下来,一步步带领大家如何解决这个问题。
隐私设置
在解决微信授权登录,先要解决隐私设置问题。 这个非常重要, 如果您已经设置则忽略这部分。
如果不先解决隐私设置问题, 就会出现如下报错。
//如果你的接口出现如下信信息,该如何处理呢?
# {errMsg: “getUserProfile:fail api scope is not
declared in the privacy agreement“, errno: 112}
接下来,按步骤一步步说明如何解锁隐私设置
- 微信小程序后台,设置->服务内容声明->用户隐私保护指引->去完善(点击)
- 点击页面中的->增加信息类型
- 勾选你需要的增加的信息类型(其实就是你需要使用的开放接口)
常用就是用户授权, 文件上传下载等接口。
- 说明你使用这些接口的用途, 请参考如下总结。
为了分辨用户,开发者将在获取你的明示同意后,收集你的微信昵称、头像。
为了显示距离,开发者将在获取你的明示同意后,收集你的位置信息。
开发者收集你的地址,用于获取位置信息。
开发者收集你的发票信息,用于维护消费功能。
为了用户互动,开发者将在获取你的明示同意后,收集你的微信运动步数。
为了通过语音与其他用户交流互动,开发者将在获取你的明示同意后,访问你的麦克风。
开发者收集你选中的照片或视频信息,用于提前上传减少上传时间。
为了上传图片或者视频,开发者将在获取你的明示同意后,访问你的摄像头。
为了登录或者注册,开发者将在获取你的明示同意后,收集你的手机号。
开发者使用你的通讯录(仅写入)权限,用于方便用户联系信息。
开发者收集你的设备信息,用于保障你正常使用网络服务。
开发者收集你的身份证号码,用于实名认证后才能继续使用的相关网络服务。
开发者收集你的订单信息,用于方便获取订单信息。
开发者收集你的发布内容,用于用户互动。
开发者收集你的所关注账号,用于用户互动。
开发者收集你的操作日志,用于运营维护。
为了保存图片或者上传图片,开发者将在获取你的明示同意后,使用你的相册(仅写入)权限。
为了用户互动,开发者将在获取你的明示同意后,收集你的车牌号。
开发者访问你的蓝牙,用于设备连接。
开发者使用你的日历(仅写入)权限,用于用户日历日程提醒。
开发者收集你的邮箱,用于在必要时和用户联系。
开发者收集你选中的文件,用于提前上传减少上传时间。
- 完成上述步骤后,就会进入审核状态。 完成审核后, 还有非常重要的一步就是发布你的小程序。
如上,需要勾选采集用户隐私。 审核通过就表示您的授权接口可以使用了!!!
微信授权流程
这个是微信授权流程,采用的就是授权码方式。 简单说,就是应用先从开放平台获取一个code。
相当于告诉平台我是谁,然后客户端将code+appId+appsecrte同时传给服务器端,拿到用户信息。
这个是采用了oauth2授权码模式,更多内容可以访问,阮一峰大佬的理解OAuth 2.0
官方给出的解决方案
根据上面标红的字体说明,官方的意图就是只提供openid和unionid, 不暴露用户头像昵称数据。
基于此才会在新版的接口中返回"微信用户"的信息。
- 针对这个问题,官方提供的解决方案如下。
以上解决方案,表达的意思是新版用户授权的接口中, 官方只会给你提供unionid和openid.
至于用户的昵称和头像,开发者可以提供功能,以用户的意志去完成修改和更新。
tips: 建议授权接口生成用户名和昵称,采用系统默认的方式。
具体代码实现
- uniapp代码
var that = this;
let code = '';
wx.login({
success: (res) => {
code = res.code
}
});
uni.getUserProfile({
desc:'登录',
lang: 'zh_CN',
success:(res)=>{
console.log( 'wx.getUserProfile=>用户允许了授权' );
var data ={
"userInfo": res.userInfo,
"code": code
};
tui.request(url.login.wxAuth, "POST", data, false, false, false).then((res) => {
//请求后处理交给用户你自己了
}).catch((res) => {
tui.toast(res.message);
});
},
fail:(err)=>{
console.log("--login error--"+ JSON.stringify(err));
tui.toast(err);
}
})
- springboot代码
//controller
@ApiOperation(value = "/newWxLogin", notes = "新版微信登录授权接口")
@PostMapping("newWxLogin")
public Result<?> newWxLogin(@RequestBody NewWxLoginReq newWxLoginReq) {
log.info("newWxLogin:{}", newWxLoginReq);
ValidatorUtils.validateEntity(newWxLoginReq);
//获取用户的openId
String openIdUrl = String.format(WxConstant.CODE_SESSION_URL, appId, appSecret, newWxLoginReq.getCode());
String result1 = HttpRequest.get(openIdUrl).execute().body();
log.info("newWxLogin.result1:{}", result1);
JSONObject jsonObject = JSONObject.parseObject(result1);
Assert.isTrue(StringUtils.isNoneBlank(jsonObject.getString(ERROR_CODE)), jsonObject.getString(ERROR_MSG));
String openId = jsonObject.getString("openid");
return userService.newWxLogin(openId, newWxLoginReq.getUserInfo());
}
//service核心代码
public int insertNewWechatUser(WxUserReq wxUserReq, String roleCode) {
User user = new User();
String simpleUUID = IdUtil.simpleUUID();
user.setId(simpleUUID);
user.setThirdId(wxUserReq.getOpenId());
user.setThirdType("wechat");
//重点就是一下代码, 头像和昵称随机生成
String avatar = "http://cdn.zengzhang.vip/test/avatar/avatar" + RandomUtil.randomInt(20) + ".png";
user.setAvatar(avatar);
user.setUsername(generateUserName());
user.setSex(wxUserReq.getGender().byteValue());
user.setStatus(Byte.parseByte("1"));
user.setUserIdentity(Byte.parseByte("1"));
user.setCreateTime(LocalDateTime.now());
String salt = oConvertUtils.randomGen(8);
user.setSalt(salt);
user.setDelFlag(Byte.parseByte("0"));
user.setRealname(filterEmoji(wxUserReq.getNickName()));
String passwordEncode = PasswordUtil.encrypt(wxUserReq.getNickName(), PASSWORD, salt);
user.setPassword(passwordEncode);
save(user);
//关联用户角色
userRoleService.insertUserRole(roleCode, simpleUUID);
return 1;
}
最终实践效果
扫描下面这个小程序码,在线体验一下
请关注JeecgFlow微信公众号, 了解更多精彩内容。