这个星期最开始 ,老大扔了2个任务过来,这个是其中之一。下面直接说步骤:
1. 查阅微信开发文档
https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/login/auth.code2Session.html
我将两个重要的地方列出来
a 登录流程时序图,及说明
登录流程时序
说明:
- 调用 wx.login() 获取 临时登录凭证code ,并回传到开发者服务器。
- 调用 auth.code2Session 接口,换取 用户唯一标识 OpenID 和 会话密钥 session_key。
之后开发者服务器可以根据用户标识来生成自定义登录态,用于后续业务逻辑中前后端交互时识别用户身份。
注意:
- 会话密钥
session_key
是对用户数据进行 加密签名 的密钥。为了应用自身的数据安全,开发者服务器不应该把会话密钥下发到小程序,也不应该对外提供这个密钥。 - 临时登录凭证 code 只能使用一次
b. auth.code2Session 的文档说明
auth.code2Session
本接口应在服务器端调用,详细说明参见服务端API。
登录凭证校验。通过 wx.login 接口获得临时登录凭证 code 后传到开发者服务器调用此接口完成登录流程。更多使用方法详见 小程序登录。
请求地址
GET https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code
请求参数
属性 | 类型 | 默认值 | 必填 | 说明 |
---|---|---|---|---|
appid | string | 是 | 小程序 appId | |
secret | string | 是 | 小程序 appSecret | |
js_code | string | 是 | 登录时获取的 code | |
grant_type | string | 是 | 授权类型,此处只需填写 authorization_code |
返回值
Object
返回的 JSON 数据包
属性 | 类型 | 说明 |
---|---|---|
openid | string | 用户唯一标识 |
session_key | string | 会话密钥 |
unionid | string | 用户在开放平台的唯一标识符,在满足 UnionID 下发条件的情况下会返回,详见UnionID 机制说明。 |
errcode | number | 错误码 |
errmsg | string | 错误信息 |
errcode 的合法值
值 | 说明 | 最低版本 |
---|---|---|
-1 | 系统繁忙,此时请开发者稍候再试 | |
0 | 请求成功 | |
40029 | code 无效 | |
45011 | 频率限制,每个用户每分钟100次 |
2. WebAPI 实现代码:主要包含三部分
第一部分:建立处理传入参数和返回参数的Model
微信小程序传入参数Model
public class WeXinLoginInModel { /// <summary> /// 小程序appid /// </summary> public string AppId { get; set; } /// <summary> /// 小程序appSecret /// </summary> public string AppSecret { get; set; } /// <summary> /// 小程序code /// </summary> public string Code { get; set; } }
小程序所需返回参数Model
public class WeXinLoginResultModel { /// <summary> /// 用户唯一标识 /// </summary> public string OpenId { get; set; } /// <summary> /// 会话密钥 /// </summary> public string Session_Key { get; set; } /// <summary> /// 用户在开放平台的唯一标识符,在满足 UnionID 下发条件的情况下会返回,详见UnionID 机制说明。 /// </summary> public string Unionid { get; set; } /// <summary> /// 错误码 /// </summary> public int ErrCode { get; set; } /// <summary> /// 错误信息 /// </summary> public string ErrMsg { get; set; } /// <summary> /// Redis里面OpenId值所对应的键OpenIdKey /// </summary> public string OpenIdKey { get; set; } /// <summary> /// Redis里面Session_Key值所对应的键SessionKey /// </summary> public string SessionKey { get; set; } }
第二部分:WebAPI里面写方法,
调用 auth.code2Session里面的请求地址,然后将返回结果中的OpenId、Session_Key以键值对的形式存储起来,而且将键名称相关的信息返回给微信端。
[HttpGet("~/api/WeiXinLogin", Name = "WeiXinLogin")] public async Task<IActionResult> WeiXinLogin(string js_code) { WeXinLoginInModel weixin = new WeXinLoginInModel(); weixin.AppId = "wx30a387595dafb442"; //固定值,请参照小程序参数说明 weixin.AppSecret = "4e24cab02422082b11a406595dacee76";///固定值,请参照小程序参数说明 weixin.Code = js_code; //不固定 string param = $"?appid={weixin.AppId}&secret={weixin.AppSecret}&js_code={weixin.Code}&grant_type=authorization_code"; ; string url = "https://api.weixin.qq.com/sns/jscode2session"+param; var handler = new HttpClientHandler() { AutomaticDecompression = DecompressionMethods.GZip }; using (var http = new HttpClient(handler)) { //await异步等待回应 var response = await http.GetAsync(url); //确保HTTP成功状态值 response.EnsureSuccessStatusCode(); var a= response.StatusCode; //await异步读取最后的JSON(注意此时gzip已经被自动解压缩了,因为上面的AutomaticDecompression = DecompressionMethods.GZip) string responseContent= await response.Content.ReadAsStringAsync(); var resultModel= JsonConvert.DeserializeObject<WeXinLoginResultModel>(responseContent); if(!string.IsNullOrEmpty(resultModel.OpenId) && !string.IsNullOrEmpty(resultModel.Session_Key)) { //将openid,session_key存入到Redis缓存中; string openIdKey = "openIdKey_" + Guid.NewGuid().ToString(); string sessionKey = "sessionKey_" + Guid.NewGuid().ToString(); _redisCacheManager.Set(openIdKey, resultModel.OpenId, TimeSpan.FromDays(1)); _redisCacheManager.Set(sessionKey, resultModel.Session_Key, TimeSpan.FromDays(1)); resultModel.OpenIdKey = openIdKey; resultModel.SessionKey = sessionKey; } //返回结果 return Ok(resultModel); } }
第三部分:微信端将键名称存入storage值,
方便下次发起业务请求时带上这个Storage值,去后端验证OpenId、Session_Key是否有值,若有值,返回业务数据。
公司老大说他用Token, 后面我没做了,过程省略。现提供后续思路如下:Storage值里面取出openIdKey、SessionKey——Redis 缓存里面根据openIdKey、SessionKey 取出openId、Session_Key——如果openId、Session_Key里面有值,说明该用户前面登录过,有权进行接下来的业务操作