一、结构图
二、分析过程
1、首先用户通过登录按钮,拉取wx.login方法,获取code。
2、获取到code之后,通过调用自己的服务器接口,向微信的服务器发送get请求。
3、给jscode2session传递appid、secret、code参数,微信服务器通过处理成功后,返回openid给自己的服务器。
4、我们可以通过对应的openid去获取对应的用户信息,并且通过JWT进行openid的token封装,并返回给微信小程序。
5、微信小程序解析数据后将数据渲染到页面,并进行页面跳转,完成登录。
三、代码
微信小程序代码:
①page/login/login.wxml
<button wx:if="{{canIUse}}" class="grace-login-three-items grace-icons icon-weixin grace-blue"
open-type="getUserInfo" bindgetuserinfo="getUserInfo">
</button>
②page/login/login.js
var app = getApp();
var auth = require("../../utils/auth");
Page({
data: {
canIUse: auth.canIUse
},
onLoad(){
//对微信登录进行工具类的封装
auth.weixinLogin();
},
//如果没有,必须点击一个按钮,然后触发自定义的方法bindGetUserInfo,参数e就是你授权确定以后的用户的信息数据。
getUserInfo (e) {
auth.loginWithWx(e.detail.userInfo);
}
})
③utils/auth.js
// 5: 远程注册用户信息,并且获取token以及用户信息,flog标记登录状态
loginWeixin: function (userinfo,flag="1") {
var that = this;
// 1:调用微信登陆的login方法获取code
wx.login({
success(res) {
if (res.code) {
wx.request({
method: "GET",
url: API.API_LOGIN,
data: {
code: res.code,
...userinfo
},
success: function (res) {
if(res.data.code !=200){
wx.showToast({title:"用户授权失败!", icon:"none"});
}
var userinfo = res.data.data;
// 如何将用户信息存储公共位置呢,
// 放入缓存中一份
that.setUser(userinfo);
// 跳转指定页面或者首页
if (flag == "1") {
wx.switchTab({
url: '../../pages/index/index',
})
} else {
wx.navigateBack({
delta: 1
});
}
}
})
}
}
})
},
服务器端代码:
/**
* 微信登陆
* @param weixinDataVo
* @return
*/
@GetMapping("/wxlogin")
public WeixinDataVo weixinlogin(WeixinDataVo weixinDataVo) {
// 1:判断code是否合法
if (StringUtils.isEmpty(weixinDataVo.getCode())) {
throw new KuangShenException(22008, "登录失败,尝试刷新重新扫码登录!");
}
// 2:通过code和appid和secret组装请求微信服务器的地址
String loginUrl = "https://api.weixin.qq.com/sns/jscode2session" +
"?appid=%s" +
"&secret=%s" +
"&js_code=%s" +
"&grant_type=authorization_code";
String loginResult = null;
try {
// 3:执行请求,获取微信请求返回得数据 WxConstantProperties为配置文件,通过配置进行获取
loginResult = new HttpClientUtils().get(String.format(loginUrl, WxConstantProperties.WX_OPEN_APP_ID, WxConstantProperties.WX_OPEN_APP_SECRET, weixinDataVo.getCode()));
log.info("2---->微信返回的日志信息是:code:{},result:{}", weixinDataVo.getCode(), loginResult);
} catch (Exception e) {
throw new KuangShenException(22007, "登录失败,尝试刷新重新扫码登录!");
}
// 4: 对微信返回得数据进行转换
Map<String, Object> resultMap = JsonUtil.string2Obj(loginResult, HashMap.class);
log.info("3---->微信返回的日志信息是:code:{},resultMap:{}", weixinDataVo.getCode(), resultMap);
// 5: 解析微信用户得唯一凭证openid
String openid = (String) resultMap.get("openid");
if (StringUtils.isEmpty(openid)) {
throw new KuangShenException(22009, "登录失败,尝试刷新重新扫码登录!!!");
}
//6:什么是openid:是小程序给每个用户生成的唯一用户标识,在开发中我们可以拿标识做为用户的唯一票据。直接使用openid判断一个用户是否被注册,
// - 如果注册:直接根据openid查询用户信息,然后生成token返回,
// - 如果没有没有注册:就进行用户的注册,并且生成token然后进行返回
weixinDataVo.setOpenid(openid);
User user = userService.wexinRegUser(weixinDataVo);
log.info("1----------------保护用户信息是:{}",user);
if(user !=null) {
// 用户id一定要在生产token之前放进去
weixinDataVo.setUserId(user.getId());
weixinDataVo.setRole(user.getRole());
// 生成token
String token = jwtService.token(weixinDataVo);
weixinDataVo.setToken(token);
return weixinDataVo;
}
return null;
}