✅作者:TuNan
✨个人主页:图南的个人主页
😉欢迎关注🔎点赞😍收藏⭐留言💌

主要的流程就是调用wx.getUserProfile向微信服务器发送请求获取code和其他的一些信息,然后再通过wx.login向我们的后台发送请求获取session_key和openid等其他信息


CREATE TABLE `user` ( `pk_id` bigint(20) NOT NULL COMMENT '主键', `nickname` varchar(50) DEFAULT NULL COMMENT '用户昵称', `service_man_id` bigint(20) DEFAULT NULL, `avatarUrl` varchar(200) DEFAULT NULL COMMENT '用户头像', `openid` varchar(50) DEFAULT NULL, `unionid` varchar(50) DEFAULT NULL COMMENT '用户统一标识。针对一个微信开放平台帐号下的应用,同一用户的unionid是唯一的。', `create_time` datetime DEFAULT CURRENT_TIMESTAMP, `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`pk_id`) USING BTREE, UNIQUE KEY `user_unionid_uindex` (`unionid`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;
这里service_man_id和unioinid可以不用
3.1 将我们刚才从微信公众号平台获取到的appld定义一个常量类

package com.ruoyi.gas.constant;
/**
* @Description 系统常量
* @Author TuNan
* @Date 2023/10/15
*/
public class SystemConstant {
/**
* 应用唯一标识,在微信开放平台提交应用审核通过后获得
*/
public static final String APPLETS_APPID="wx98935fbf9774bf5a";
/**
* 应用密钥AppSecret,在微信开放平台提交应用审核通过后获得
*/
public static final String APPLETS_SECRET ="adbecc45d036d4ba52aab8285c159216";
}
3.2实体类

package com.ruoyi.gas.domain; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import lombok.Getter; import lombok.Setter; import lombok.experimental.Accessors; import java.io.Serializable; /** * 移动端用户对象 gas_xcx_user * * @author TuNan * @date 2023-09-17 */ @Getter @Setter @TableName("user") @Accessors(chain = true) public class User implements Serializable { private static final long serialVersionUID = 1L; @TableId("pk_id") private Long pkId; /** * 用户昵称 */ @TableField("nickname") private String nickname; /** * 用户头像 */ @TableField("avatarUrl") private String avatarUrl; /** * 用户统一标识。针对一个微信开放平台帐号下的应用,同一用户的unionid是唯一的。 */ @TableField("unionid") private String unionId; @TableField("openid") private String openid; private Long ServiceManId; }
3.3 controller层

package com.ruoyi.gas.controller; import com.ruoyi.gas.domain.dto.UserDTO; import com.ruoyi.gas.domain.vo.ReWxUserInfoVO; import com.ruoyi.gas.service.UserService; import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; import java.util.Map; /** ** 前端控制器 *
* * @author TuNan * @since 2023/10/13 */ @RestController @RequestMapping("/gas/user") public class UserController { @Resource private UserService userService; /** * 微信小程序登录 * * @param requestData 请求参数 * @return ReWxUserInfoVO */ @PostMapping("/getUserLoginByApplets") @SuppressWarnings("unchecked") // 用于抑制编译器产生警告信息。 public ReWxUserInfoVO getUserLoginByApplets(@RequestBody MaprequestData) { String code = (String) requestData.get("code"); Map userMap = (Map ) requestData.get("user"); UserDTO userDTO = new UserDTO(); 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 服务层及实现
package com.ruoyi.gas.service; import com.baomidou.mybatisplus.extension.service.IService; import com.ruoyi.gas.domain.User; import com.ruoyi.gas.domain.dto.UserDTO; import com.ruoyi.gas.domain.vo.ReWxUserInfoVO; /** ** 服务类 *
* * @author TuNan * @since 2023-09-18 */ public interface UserService extends IService{ /** * 微信登录 小程序版 */ ReWxUserInfoVO loginByWxApplets(String code, UserDTO userDTO); }
package com.ruoyi.gas.service.impl; import cn.dev33.satoken.stp.StpUtil; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.ObjectUtil; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.ruoyi.common.core.domain.model.LoginUser; import com.ruoyi.common.enums.DeviceType; import com.ruoyi.common.helper.LoginHelper; import com.ruoyi.gas.domain.User; import com.ruoyi.gas.domain.dto.UserDTO; import com.ruoyi.gas.domain.ro.AppletsWxLoginRO; import com.ruoyi.gas.domain.vo.ReWxUserInfoVO; import com.ruoyi.gas.mapper.UserMapper; import com.ruoyi.gas.service.UserService; import com.ruoyi.gas.utils.WxLoginUtil; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; /** ** 服务实现类 *
* * @author xiahaike * @since 2023/10/13 */ @Service @Slf4j public class UserServiceImpl extends ServiceImplimplements UserService { @Override public ReWxUserInfoVO loginByWxApplets(String code, UserDTO userDTO) { // 1.通过code 获取到用户的微信信息 AppletsWxLoginRO getWxUserInfoRO = WxLoginUtil.toAppletsWxLogin(code); // 2.数据库对比 unionid 是否已有信息 如果没有就保持数据库 QueryWrapper queryWrapper = new QueryWrapper<>(); // 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(new User().setPkId(userId).setNickname(nickName).setOpenid(getWxUserInfoRO.getOpenid()).setAvatarUrl(userDTO.getAvatarUrl()).setServiceManId(0L)); LoginUser loginUser = BeanUtil.toBean(new User().setPkId(userId).setNickname(nickName), LoginUser.class); loginUser.setUserType("sys_user"); loginUser.setUserId(IdUtil.getSnowflakeNextId()); LoginHelper.loginByDevice(loginUser, DeviceType.XCX); return new ReWxUserInfoVO().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); return new ReWxUserInfoVO().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微信登录工具包
package com.ruoyi.gas.utils;
import cn.hutool.core.text.StrFormatter;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
import com.ruoyi.gas.Enum.WxApiType;
import com.ruoyi.gas.constant.SystemConstant;
import com.ruoyi.gas.domain.ro.AppletsWxLoginRO;
import lombok.extern.slf4j.Slf4j;
/**
* @Description 微信登录工具包
* @Author TuNan
* @Date 2023/10/16
*/
@Slf4j
public class WxLoginUtil {
/**
*微信登录
* @param code 前端请求获取=>微信code
* @return void
* @author zhangjunrong
* @date 2022/12/19 20:16
*/
public static AppletsWxLoginRO toAppletsWxLogin(String code){
//1.通过前端给的code获取openid和access_token还有unionid
String 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 获取用户信息失败 抛异常
return JSONUtil.toBean(data, AppletsWxLoginRO.class);
}
}
3.6 Ro及Vo
package com.ruoyi.gas.domain.ro;
import lombok.Data;
/**
* @Description 微信用户基础信息
* @Author TuNan
* @Date 2023/10/16
*/
@Data
public class WxUserInfoRO {
/**
* 用户昵称
*/
private String nickname;
/**
* 用户头像
*/
private String avatarUrl;
/**
* 用户微信统一标识
*/
private String unionid;
private String session_key;
private String openid;
}
package com.ruoyi.gas.domain.ro;
import lombok.Data;
/**
* @Description TODO
* @Author TuNan
* @Date 2023/09/18
*/
@Data
public class AppletsWxLoginRO {
/**
*普通用户标识,对该公众帐号唯一
*/
private String openid;
/**
*用户在开放平台的唯一标识符
*/
private String unionid;
private String 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.1首先我们在app.js中定义全局变量

// app.js
App({
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
});
}
})
},
})
}
})
}
},

到此我们所有流程就结束了🤞,出现以上效果说明就成功登录了😉
你好,我是博主图南,有问题可以留言评论或者私信我,大家一起交流学习!
不过都看到这里啦,点个赞吧👩💻
