若依Springboot整合微信小程序实现登录
前言
✅作者:TuNan
✨个人主页:图南的个人主页
😉欢迎关注🔎点赞😍收藏⭐留言💌
一、微信小程序官方登录流程图
主要的流程就是调用wx.getUserProfile向微信服务器发送请求获取code和其他的一些信息,然后再通过wx.login向我们的后台发送请求获取session_key和openid等其他信息
二、个人实现登录流程
1️⃣首先去我们的微信公众号平台拿到AppId和AppSecret。等一下我们会用到😉
2️⃣数据库设计
CREATETABLE`user`(`pk_id`bigint(20)NOTNULLCOMMENT'主键',`nickname`varchar(50)DEFAULTNULLCOMMENT'用户昵称',`service_man_id`bigint(20)DEFAULTNULL,`avatarUrl`varchar(200)DEFAULTNULLCOMMENT'用户头像',`openid`varchar(50)DEFAULTNULL,`unionid`varchar(50)DEFAULTNULLCOMMENT'用户统一标识。针对一个微信开放平台帐号下的应用,同一用户的unionid是唯一的。',`create_time`datetimeDEFAULTCURRENT_TIMESTAMP,`update_time`datetimeNOTNULLDEFAULTCURRENT_TIMESTAMPONUPDATECURRENT_TIMESTAMP,PRIMARYKEY(`pk_id`)USINGBTREE,UNIQUEKEY`user_unionid_uindex`(`unionid`)USINGBTREE)ENGINE=InnoDBDEFAULTCHARSET=utf8 ROW_FORMAT=DYNAMIC;
这里service_man_id和unioinid可以不用
3️⃣Springboot后端
3.1 将我们刚才从微信公众号平台获取到的appld定义一个常量类
packagecom.ruoyi.gas.constant;/**
* @Description 系统常量
* @Author TuNan
* @Date 2023/10/15
*/publicclassSystemConstant{/**
* 应用唯一标识,在微信开放平台提交应用审核通过后获得
*/publicstaticfinalStringAPPLETS_APPID="wx98935fbf9774bf5a";/**
* 应用密钥AppSecret,在微信开放平台提交应用审核通过后获得
*/publicstaticfinalStringAPPLETS_SECRET="adbecc45d036d4ba52aab8285c159216";}
3.2实体类
packagecom.ruoyi.gas.domain;importcom.baomidou.mybatisplus.annotation.TableField;importcom.baomidou.mybatisplus.annotation.TableId;importcom.baomidou.mybatisplus.annotation.TableName;importlombok.Getter;importlombok.Setter;importlombok.experimental.Accessors;importjava.io.Serializable;/**
* 移动端用户对象 gas_xcx_user
*
* @author TuNan
* @date 2023-09-17
*/@Getter@Setter@TableName("user")@Accessors(chain =true)publicclassUserimplementsSerializable{privatestaticfinallong serialVersionUID =1L;@TableId("pk_id")privateLong pkId;/**
* 用户昵称
*/@TableField("nickname")privateString nickname;/**
* 用户头像
*/@TableField("avatarUrl")privateString avatarUrl;/**
* 用户统一标识。针对一个微信开放平台帐号下的应用,同一用户的unionid是唯一的。
*/@TableField("unionid")privateString unionId;@TableField("openid")privateString openid;privateLongServiceManId;}
3.3 controller层
packagecom.ruoyi.gas.controller;importcom.ruoyi.gas.domain.dto.UserDTO;importcom.ruoyi.gas.domain.vo.ReWxUserInfoVO;importcom.ruoyi.gas.service.UserService;importorg.springframework.web.bind.annotation.*;importjavax.annotation.Resource;importjava.util.Map;/**
* <p>
* 前端控制器
* </p>
*
* @author TuNan
* @since 2023/10/13
*/@RestController@RequestMapping("/gas/user")publicclassUserController{@ResourceprivateUserService userService;/**
* 微信小程序登录
*
* @param requestData 请求参数
* @return ReWxUserInfoVO
*/@PostMapping("/getUserLoginByApplets")@SuppressWarnings("unchecked")// 用于抑制编译器产生警告信息。publicReWxUserInfoVOgetUserLoginByApplets(@RequestBodyMap<String,Object> requestData){String code =(String) requestData.get("code");Map<String,Object> userMap =(Map<String,Object>) requestData.get("user");UserDTO userDTO =newUserDTO();
userDTO.setAvatarUrl((String) userMap.get("avatarUrl"));
userDTO.setCity((String) userMap.get("city"));
userDTO.setCountry((String) userMap.get("country"));
userDTO.setGender((Integer) userMap.get("gender"));
userDTO.setLanguage((String) userMap.get("language"));
userDTO.setNickName((String) userMap.get("nickName"));System.out.println("userDTO = "+ userDTO);return userService.loginByWxApplets(code , userDTO);}}
3.4 服务层及实现
packagecom.ruoyi.gas.service;importcom.baomidou.mybatisplus.extension.service.IService;importcom.ruoyi.gas.domain.User;importcom.ruoyi.gas.domain.dto.UserDTO;importcom.ruoyi.gas.domain.vo.ReWxUserInfoVO;/**
* <p>
* 服务类
* </p>
*
* @author TuNan
* @since 2023-09-18
*/publicinterfaceUserServiceextendsIService<User>{/**
* 微信登录 小程序版
*/ReWxUserInfoVOloginByWxApplets(String code,UserDTO userDTO);}
packagecom.ruoyi.gas.service.impl;importcn.dev33.satoken.stp.StpUtil;importcn.hutool.core.bean.BeanUtil;importcn.hutool.core.util.IdUtil;importcn.hutool.core.util.ObjectUtil;importcom.baomidou.mybatisplus.core.conditions.query.QueryWrapper;importcom.baomidou.mybatisplus.extension.service.impl.ServiceImpl;importcom.ruoyi.common.core.domain.model.LoginUser;importcom.ruoyi.common.enums.DeviceType;importcom.ruoyi.common.helper.LoginHelper;importcom.ruoyi.gas.domain.User;importcom.ruoyi.gas.domain.dto.UserDTO;importcom.ruoyi.gas.domain.ro.AppletsWxLoginRO;importcom.ruoyi.gas.domain.vo.ReWxUserInfoVO;importcom.ruoyi.gas.mapper.UserMapper;importcom.ruoyi.gas.service.UserService;importcom.ruoyi.gas.utils.WxLoginUtil;importlombok.extern.slf4j.Slf4j;importorg.springframework.stereotype.Service;/**
* <p>
* 服务实现类
* </p>
*
* @author xiahaike
* @since 2023/10/13
*/@Service@Slf4jpublicclassUserServiceImplextendsServiceImpl<UserMapper,User>implementsUserService{@OverridepublicReWxUserInfoVOloginByWxApplets(String code,UserDTO userDTO){// 1.通过code 获取到用户的微信信息AppletsWxLoginRO getWxUserInfoRO =WxLoginUtil.toAppletsWxLogin(code);// 2.数据库对比 unionid 是否已有信息 如果没有就保持数据库QueryWrapper<User> queryWrapper =newQueryWrapper<>();// 3.通过查询pk_id 索引优化查询 无需回表查询用户信息 索引 openid
queryWrapper.eq("openid", getWxUserInfoRO.getOpenid());User user =getOne(queryWrapper);
log.info("数据库查询用户是否已有账号==空则没有==={}====", user);// 4.如果用户不存在则创建用户if(ObjectUtil.isEmpty(user)){long userId =IdUtil.getSnowflakeNextId();String nickName = userDTO.getNickName();save(newUser().setPkId(userId).setNickname(nickName).setOpenid(getWxUserInfoRO.getOpenid()).setAvatarUrl(userDTO.getAvatarUrl()).setServiceManId(0L));LoginUser loginUser =BeanUtil.toBean(newUser().setPkId(userId).setNickname(nickName),LoginUser.class);
loginUser.setUserType("sys_user");
loginUser.setUserId(IdUtil.getSnowflakeNextId());LoginHelper.loginByDevice(loginUser,DeviceType.XCX);returnnewReWxUserInfoVO().setPkId(userId).setNickname(nickName).setSession_key(getWxUserInfoRO.getSession_key()).setOpenid(getWxUserInfoRO.getOpenid()).setToken(StpUtil.getTokenValue()).setAvatarUrl(userDTO.getAvatarUrl()).setServiceManId(0L);}// 5.如果用户存在则直接登录LoginUser loginUser =BeanUtil.toBean(user,LoginUser.class);
loginUser.setUserType("sys_user");
loginUser.setUserId(IdUtil.getSnowflakeNextId());LoginHelper.loginByDevice(loginUser,DeviceType.XCX);returnnewReWxUserInfoVO().setPkId(user.getPkId()).setNickname(user.getNickname()).setAvatarUrl(user.getAvatarUrl()).setSession_key(getWxUserInfoRO.getSession_key()).setOpenid(getWxUserInfoRO.getOpenid()).setToken(StpUtil.getTokenValue()).setServiceManId(user.getServiceManId());}}
3.5微信登录工具包
packagecom.ruoyi.gas.utils;importcn.hutool.core.text.StrFormatter;importcn.hutool.http.HttpUtil;importcn.hutool.json.JSONUtil;importcom.ruoyi.gas.Enum.WxApiType;importcom.ruoyi.gas.constant.SystemConstant;importcom.ruoyi.gas.domain.ro.AppletsWxLoginRO;importlombok.extern.slf4j.Slf4j;/**
* @Description 微信登录工具包
* @Author TuNan
* @Date 2023/10/16
*/@Slf4jpublicclassWxLoginUtil{/**
*微信登录
* @param code 前端请求获取=>微信code
* @return void
* @author zhangjunrong
* @date 2022/12/19 20:16
*/publicstaticAppletsWxLoginROtoAppletsWxLogin(String code){//1.通过前端给的code获取openid和access_token还有unionidString getTokenOpenid =StrFormatter.format(WxApiType.APPLETS_GET_TOKEN_OPENID.getValue(),SystemConstant.APPLETS_APPID,SystemConstant.APPLETS_SECRET, code);String data =HttpUtil.get(getTokenOpenid);
log.info("微信获取获取openid和unionid,返回结果======{}=====",data);//json=>bean//todo 获取用户信息失败 抛异常returnJSONUtil.toBean(data,AppletsWxLoginRO.class);}}
3.6 Ro及Vo
packagecom.ruoyi.gas.domain.ro;importlombok.Data;/**
* @Description 微信用户基础信息
* @Author TuNan
* @Date 2023/10/16
*/@DatapublicclassWxUserInfoRO{/**
* 用户昵称
*/privateString nickname;/**
* 用户头像
*/privateString avatarUrl;/**
* 用户微信统一标识
*/privateString unionid;privateString session_key;privateString openid;}
packagecom.ruoyi.gas.domain.ro;importlombok.Data;/**
* @Description TODO
* @Author TuNan
* @Date 2023/09/18
*/@DatapublicclassAppletsWxLoginRO{/**
*普通用户标识,对该公众帐号唯一
*/privateString openid;/**
*用户在开放平台的唯一标识符
*/privateString unionid;privateString session_key;}
package com.ruoyi.gas.domain.vo;
import lombok.Data;
import lombok.experimental.Accessors;
/**
* @Description 返回前端微信个人信息
* @Author TuNan
* @Date 2023/9/17 15:27
*/
@Data
@Accessors(chain = true)
public class ReWxUserInfoVO {
/**
* 用户id
*/
private Long pkId;
/**
* 用户昵称
*/
private String nickname;
/**
* 用户头像
*/
private String avatarUrl;
private String unionid;
private String session_key;
private String openid;
private String token;
private Long ServiceManId;
}
以下就是我们后端的所有代码,接下来是小程序端的代码
4️⃣小程序实现
4.1首先我们在app.js中定义全局变量
// app.jsApp({globalData:{token:'',openid:null,sessionKey:null,serviceManId:0,pkId:0,// 用于判断用户是否登录}})
4.2 然后是我们在主页调用wx.logind的js代码
const app = getApp()
// 点击登录按钮login(){if(this.data.pkId !=0){
Toast.fail("您已登录,请勿重复提交")}else{
console.log('执行了登录操作');
wx.getUserProfile({desc:'Wexin',// 这里应该是向微信发送请求获取用户名和头像success:(res)=>{this.setData({userInfo: res.userInfo
})let user =this.data.userInfo // user里面保存从微信获取的信息(用户名和头像)// 向后台发送请求 将code、用户头像、用户名一起发送至后台
console.log(user)
wx.login({success:(res)=>{
console.log(res)const code = res.code;
wx.request({url: baseUrl +'/gas/user/getUserLoginByApplets',method:"POST",data:{
user,
code
},success:(res)=>{// 后端返回的数据var Mydata = res.data
// 将从服务器获取的token、session_key等保存到globalData中
app.globalData.token = Mydata.token
app.globalData.session_key = Mydata.session_key
app.globalData.serviceManId = Mydata.serviceManId
app.globalData.openid = Mydata.openid
app.globalData.pkId = Mydata.pkId
// 将serviceId和pkid保存到当前页面中this.setData({serviceManId: app.globalData.serviceManId,pkId: res.data.pkId
});}})},})}})}},
到此我们所有流程就结束了🤞,出现以上效果说明就成功登录了😉
你好,我是博主
图南
,有问题可以留言评论或者私信我,大家一起交流学习!
不过都看到这里啦,点个赞吧👩💻
版权归原作者 Tunanna 所有, 如有侵权,请联系我们删除。