2021年2月24日,微信官方团队发布了一个调整通知:《小程序登录、用户信息相关接口调整说明》,公告明确从4月13日起,所有发布的小程序将无法使用 wx.getUserInfo 接口(JS)和 <button open-type="getUserInfo"/> 标签来获取用户信息了。主要信息如下:

  

  实际时间从1个月前(4月2日)起,我们已经陆续接到开发者的反馈,在开发环境已经无法正常使用旧版本的功能,这也意味着从现在开始,要进行小程序的开发必须符合调整后接口的标准。

  虽然文档看上去很负责,经过实际测试,其实修改的地方还是比较简单的,步骤如下:

  第一步:替换原有的 <button open-type="getUserInfo"/> 标签为普通标签,例如:

  

<button bindtap="getUserInfo"> 获取头像昵称 </button>

  在页面的 .js 文件中创建一个对应的方法 getUserInfo(如果以前就有可以直接修改):

getUserInfo: function (e) {
//...
}

  第二步:在 getUserInfo 代码中调用 wx.getUserProfile 接口

getUserProfile(e) {
// 推荐使用wx.getUserProfile获取用户信息,开发者每次通过该接口获取用户个人信息均需用户确认
// 开发者妥善保管用户快速填写的头像昵称,避免重复弹窗
wx.getUserProfile({
desc: '用于完善会员资料', // 声明获取用户个人信息后的用途,后续会展示在弹窗中,请谨慎填写
success: (res) => {
this.setData({
userInfo: res.userInfo,
hasUserInfo: true
})
}
})
}

  完成。

  以下是新接口调用的效果:

      
 未登录状态  授权 完成授权 

  最新的 Demo 已经更新至 Senparc.Weixin SDK 的开源项目库:https://github.com/JeffreySu/WeiXinMPSDK

  小程序文件目录:\src\Senparc.Weixin.WxOpen\src\Senparc.Weixin.WxOpen.AppDemo

  后台程序目录如下:

后台程序目录
框架 解决方案  小程序 Controller 代码 学习新一代 .NET  
.NET Framework 4.5

\Samples\net45-mvc\Senparc.Weixin.MP.Sample.sln

Senparc.Weixin.Sample项目下

Controllers/WxOpenController.cs

 
.NET Core 3.1 \Samples\netcore3.0-mvc\Senparc.Weixin.Sample.NetCore3.vs2019.sln 学习 .NET Core 3.1
.NET 6.0(兼容5.0) \Samples\net6-mvc\Senparc.Weixin.Sample.Net6.sln 学习 .NET 6.0

  在线 Demo:

小程序二维码

  注意点

  1、建议将小程序基础库升级到最新,否则可能导致无法正确解密:

  2、注意 wx.getUserProfile 接口和 wx.login 接口的调用次序,Demo 中为了方便演示各项接口能力,所以进行了如下的嵌套操作:

  

wx.getUserProfile({
desc: '用于完善会员资料',
success: function (userInfoRes) {
//... //调用 wx.login 登录接口
wx.login({
success: function (res) {
//换取openid & session_key
wx.request({
url: wx.getStorageSync('domainName') + '/WxOpen/OnLogin',
method: 'POST',
header: { 'content-type': 'application/x-www-form-urlencoded' },
data: {
code: res.code
},
success:function(json){
var result = json.data;
if(result.success)
{
wx.setStorageSync('sessionId', result.sessionId);
//校验
wx.request({
url: wx.getStorageSync('domainName') + '/WxOpen/CheckWxOpenSignature',
method: 'POST',
header: { 'content-type': 'application/x-www-form-urlencoded' },
data: {
sessionId: result.sessionId,//wx.getStorageSync('sessionId'),
rawData:userInfoRes.rawData,
signature:userInfoRes.signature
},
success:function(json){
console.log(json.data);
}
}); //解密数据(建议放到校验success回调函数中,此处仅为演示)
wx.request({
url: wx.getStorageSync('domainName') + '/WxOpen/DecodeEncryptedData',
method: 'POST',
header: { 'content-type': 'application/x-www-form-urlencoded' },
data: {
'type':"userInfo",
sessionId: result.sessionId,//wx.getStorageSync('sessionId'),
encryptedData: userInfoRes.encryptedData,
iv: userInfoRes.iv
},
success:function(json){
console.log('数据解密:', json.data);
}
}); }else{
console.log('储存session失败!',json);
}
}
})
}
})
}
});

  相关后端代码,如果是新项目,只需要按照之前的实现方式,旧项目不需要修改:

  wx.login 成功后,调用 WxOpenController.cs 中的 OnLogin 方法:

  

 1       /// <summary>
2 /// wx.login登陆成功之后发送的请求
3 /// </summary>
4 /// <param name="code"></param>
5 /// <returns></returns>
6 [HttpPost]
7 public ActionResult OnLogin(string code)
8 {
9 try
10 {
11 var jsonResult = SnsApi.JsCode2Json(WxOpenAppId, WxOpenAppSecret, code);
12 if (jsonResult.errcode == ReturnCode.请求成功)
13 {
14 //Session["WxOpenUser"] = jsonResult;//使用Session保存登陆信息(不推荐)
15 //使用SessionContainer管理登录信息(推荐)
16 var unionId = "";
17 var sessionBag = SessionContainer.UpdateSession(null, jsonResult.openid, jsonResult.session_key, unionId);
18
19 //注意:生产环境下SessionKey属于敏感信息,不能进行传输!
20 return Json(new { success = true, msg = "OK", sessionId = sessionBag.Key, sessionKey = sessionBag.SessionKey });
21 }
22 else
23 {
24 return Json(new { success = false, msg = jsonResult.errmsg });
25 }
26 }
27 catch (Exception ex)
28 {
29 return Json(new { success = false, msg = ex.Message });
30 }
31 }

  OnLogin 方法调用成功后进行签名校验:

 1         /// <summary>
2 /// 检查签名
3 /// </summary>
4 /// <param name="sessionId"></param>
5 /// <param name="rawData"></param>
6 /// <param name="signature"></param>
7 /// <returns></returns>
8 [HttpPost]
9 public ActionResult CheckWxOpenSignature(string sessionId, string rawData, string signature)
10 {
11 try
12 {
13 var checkSuccess = Senparc.Weixin.WxOpen.Helpers.EncryptHelper.CheckSignature(sessionId, rawData, signature);
14 return Json(new { success = checkSuccess, msg = checkSuccess ? "签名校验成功" : "签名校验失败" });
15 }
16 catch (Exception ex)
17 {
18 return Json(new { success = false, msg = ex.Message });
19 }
20 }

  同时进行用户信息解密及水印校验:

 1         /// <summary>
2 /// 数据解密并进行水印校验
3 /// </summary>
4 /// <param name="type"></param>
5 /// <param name="sessionId"></param>
6 /// <param name="encryptedData"></param>
7 /// <param name="iv"></param>
8 /// <returns></returns>
9 [HttpPost]
10 public async Task<IActionResult> DecodeEncryptedData(string type, string sessionId, string encryptedData, string iv)
11 {
12 DecodeEntityBase decodedEntity = null;
13
14 try
15 {
16 switch (type.ToUpper())
17 {
18 case "USERINFO"://wx.getUserInfo()
19 decodedEntity = EncryptHelper.DecodeUserInfoBySessionId(
20 sessionId,
21 encryptedData, iv);
22 break;
23 default:
24 break;
25 }
26 }
27 catch (Exception ex)
28 {
29 WeixinTrace.SendCustomLog("EncryptHelper.DecodeUserInfoBySessionId 方法出错",
30 $@"sessionId: {sessionId}
31 encryptedData: {encryptedData}
32 iv: {iv}
33 sessionKey: { (await SessionContainer.CheckRegisteredAsync(sessionId)
34 ? (await SessionContainer.GetSessionAsync(sessionId)).SessionKey
35 : "未保存sessionId")}
36
37 异常信息:
38 {ex.ToString()}
39 ");
40 }
41
42 //检验水印
43 var checkWatermark = false;
44 if (decodedEntity != null)
45 {
46 checkWatermark = decodedEntity.CheckWatermark(WxOpenAppId);
47
48 //保存用户信息(可选)
49 if (checkWatermark && decodedEntity is DecodedUserInfo decodedUserInfo)
50 {
51 var sessionBag = await SessionContainer.GetSessionAsync(sessionId);
52 if (sessionBag != null)
53 {
54 await SessionContainer.AddDecodedUserInfoAsync(sessionBag, decodedUserInfo);
55 }
56 }
57 }
58
59 //注意:此处仅为演示,敏感信息请勿传递到客户端!
60 return Json(new
61 {
62 success = checkWatermark,
63 //decodedEntity = decodedEntity,
64 msg = $"水印验证:{(checkWatermark ? "通过" : "不通过")}"
65 });
66 }

  上述方法中标红的接口调用、SessionKey管理和解密方法都已经封装在 Senparc.Weixin SDK 中(更多教程),只需要按照 Demo 演示的调用即可。

  调试窗口结果:

  

  注意:

  1、不能在调用 wx.login 等过程的回调函数中,自动调用 wx.getUserProfile 来触发授权行为,因为 wx.getUserProfile 只能由用户手动触发。否则,系统会抛出异常:

 error msg: getUserProfile:fail can only be invoked by user TAP gesture

  关于这两个方法的同时使用问题也可以参考:《wx.getUserProfile不能和wx.login一起使用?》(PS:并非所有都是正解)

  2、虽然官方提示需要使用2.10.4以上基础库,但是实测发现,2.10.4及之后的几个版本,虽然可以使用wx.getUserProfile,但在用户信息解密(wx.login)上面都有缺陷,导致无法正常解密,因此,建议直接升级到最新的版本(见上图)。升级基础库后,后端代码不需要修改。

  下一篇我们将介绍微信公众号模板消息下线后,如何使用“订阅消息”进行开发。

[重要更新]微信小程序登录、用户信息相关接口调整:使用 wx.getUserProfile 取代 wx.getUserInfo的更多相关文章

  1. 微信小程序 获取用户信息并保存登录状态

    微信小程序 获取用户信息并保存登录状态:http://www.360doc.com/content/18/0124/11/9200790_724662071.shtml

  2. Laravel wxxcx 微信小程序获取用户信息

    wxxcx 是Laravel5微信小程序登录获取用户信息扩展 部署 12345678 # 安装$ composer require iwanli/wxxcx# 注册服务# 在 /config/app. ...

  3. 微信小程序授权登录以及用户信息相关接口调整导致授权框不弹出

    前言:4月8号升级了小程序业务后提交了版本并上线.突然一个同事说体验版的点击"登录"按钮无效.当时觉得应该不会呀,这几天一直用手机调试,每天也在不停的登录授权,弹框一直有的呀.然后 ...

  4. 微信小程序获取用户信息,解密encryptedData 包括敏感数据在内的完整用户信息的加密数据

    package com.iups.wx.wxservice; import java.io.UnsupportedEncodingException; import java.security.Alg ...

  5. 微信小程序 获取用户信息 encryptData解密 C#版本

    最近学习小程序开发,需要对encryptData解密,获取用户信息,官方源码没有C#版本,网上的资料比较杂,有的使用还有问题,下面贴一下自己亲试可以使用的一个源码 1.code 换取 session_ ...

  6. 微信小程序获取用户信息

    App({ appData: { userInfo:{ user_portraitUrl: "", user_nick: "", user_gender: 0, ...

  7. 微信小程序-获取用户信息(getUserInfo)

    当小程序抹杀掉这个接口的时候,多少人心凉了.. 作为一个初级web前端开发,我是更加懵逼,小程序员跑路了... 当时以及现在用的办法就是: 1.增加一个登陆或授权页 2.上线以后自动获取 3.增加一个 ...

  8. 微信小程序获取用户信息“授权失败”场景的处理

    很多的时候我们在处理小程序功能的时候需要用户获取用户信息,但是呢为了信息安全,用户不授权导致授权失败场景:但是小程序第二次不在启动授权信息弹层,为了用户体验,可以用以下方式处理: function i ...

  9. 微信小程序 获取用户信息授权

    login.wxml界面 获取用户授权可以用微信提供的接口 wx.authorize, 但是获取用户信息的授权用这个接口不会弹出授权窗口 <button class="submit-b ...

随机推荐

  1. 第42天学习打卡(Class类 Class类的常用方法 内存分析 类的加载过程 类加载器 反射操作泛型 反射操作注解)

    Class类 对象照镜子后得到的信息:某个类的属性.方法和构造器.某个类到底实现了哪些接口.对于每个类而言,JRE都为其保留一个不变的Class类型的对象.一个Class对象包含了特定某个结构(cla ...

  2. 弹性盒布局详解(display: flex;)

    弹性盒布局详解 弹性盒介绍 弹性盒的CSS属性 开启弹性盒 弹性容器的CSS属性 flex-direction设置弹性元素在弹性容器中的排列方向 主轴与侧轴(副轴) flex-wrap设置弹性容器空间 ...

  3. 检查字符串是否包含另一串字符串(c++)

    在c++中检查字符串是否包含另一串字符串,这个本来是我做过的一个算法题,不过最近刚好有个需求让我想到了这个题,就在此记录一下! 使用std::string::findfunction string s ...

  4. MySQL 表的约束与数据库设计

    DQL 查询语句 排序 # 单列排序 * 只按某一个字段进行排序,单列排序 # 组合排序 * 同时对多个字段进行排序,如果第1个字段相等,则按照第2个字段排序,依次类推 * 语法: # 具体操作 * ...

  5. 趣谈 DHCP 协议,有点意思。

    计算机网络我也连载了很多篇了,大家可以在我的公众号「程序员cxuan」 或者我的 github 系统学习. 计算机网络第一篇,聊一聊网络基础 :计算机网络基础知识总结 计算机网络第二篇,聊一聊 TCP ...

  6. slickgrid ( nsunleo-slickgrid ) 5 增加子件

    slickgrid ( nsunleo-slickgrid ) 5 增加子件 上次把单元格切换的问题解决了,这次要最做的事情就是给slickgrid的treegird增加子件,我们先选中某一条记录,然 ...

  7. BuaacodingT651 我知道你不知道圣诞节做什么 题解(逻辑)

    题目链接 我知道你不知道圣诞节做什么 解题思路 第一句话:x,y不都为质数. 第二句话:对于xy=t,存在唯一一种x+y使得x,y不都为质数. 第三句话:对于x+y=s,存在唯一一种t=xy使得对于任 ...

  8. mysql操作和详解

    温馨提示 mysql安装包里面:mysqld是服务端,mysql是客户端. mysqld其实是SQL后台程序(也就是MySQL服务器),它是关于服务器端的一个程序,mysqld意思是mysql dae ...

  9. 最小生成树(Prim算法,Kruskal算法 )

    声明:图片及内容基于https://www.bilibili.com/video/BV1yp4y1Q74o?from=articleDetail 最小生成树原理 . 普利姆(Prim)算法 原理 Pr ...

  10. 走进springboot

    SpringBoot基础 核心思想---自动装配---约定大于配置 开发环境:jdk1.8.maven.springboot.idea 一.快速构建一个springboot项目 1.1.进入sprin ...