若依Springboot实现小程序登录

若依Springboot整合微信小程序实现登录

前言

✅作者:TuNan

✨个人主页:图南的个人主页

😉欢迎关注🔎点赞😍收藏⭐留言💌

一、微信小程序官方登录流程图

在这里插入图片描述

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

二、个人实现登录流程

1️⃣首先去我们的微信公众号平台拿到AppId和AppSecret。等一下我们会用到😉

在这里插入图片描述

2️⃣数据库设计

在这里插入图片描述

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️⃣Springboot后端

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;

/**
 * <p>
 * 前端控制器
 * </p>
 *
 * @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 Map<String, Object> requestData) {
        String code = (String) requestData.get("code");
        Map<String, Object> userMap = (Map<String, Object>) 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;

/**
 * <p>
 * 服务类
 * </p>
 *
 * @author TuNan
 * @since 2023-09-18
 */
public interface UserService extends IService<User> {

    /**
     * 微信登录 小程序版
     */
    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;


/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author xiahaike
 * @since 2023/10/13
 */
@Service
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Override
    public ReWxUserInfoVO loginByWxApplets(String code, UserDTO userDTO) {
        // 1.通过code 获取到用户的微信信息
        AppletsWxLoginRO getWxUserInfoRO = WxLoginUtil.toAppletsWxLogin(code);
        // 2.数据库对比 unionid 是否已有信息 如果没有就保持数据库
        QueryWrapper<User> 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️⃣小程序实现

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
                  });
                }
              })
            },
          })
        }
      })
    }
  },

在这里插入图片描述

到此我们所有流程就结束了🤞,出现以上效果说明就成功登录了😉


你好,我是博主图南,有问题可以留言评论或者私信我,大家一起交流学习!

不过都看到这里啦,点个赞吧👩‍💻

在这里插入图片描述

  • 4
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 10
    评论
如果您下载了本程序,但是该程序存在问题无法运行,那么您可以选择退款或者寻求我们的帮助(如果找我们帮助的话,是需要追加额外费用的)。另外,您不会使用资源的话(这种情况不支持退款),也可以找我们帮助(需要追加额外费用) 微信小程序是腾讯公司基于微信平台推出的一种轻量级应用形态,它无需用户下载安装即可在微信内直接使用。自2017年正式上线以来,小程序凭借其便捷性、易获取性和出色的用户体验迅速获得市场认可,并成为连接线上线下服务的重要桥梁。 小程序的核心特点包括: 零安装:用户只需通过微信扫一扫或搜索功能,即可打开和使用小程序,大大降低了用户的使用门槛和手机存储空间压力。 速度快:加载速度相较于传统的HTML5网页更快,依托于微信强大的基础设施,能够实现近乎原生应用的流畅体验。 跨平台兼容:开发者一次开发,即可在多种终端设备上运行,免除了复杂的适配工作,大大提高了开发效率。 社交属性强:小程序可以无缝嵌入微信生态,支持分享至聊天窗口、朋友圈等社交场景,有利于用户间的传播和裂变增长。 丰富接口能力:提供丰富的API接口,可调用微信支付、位置服务、用户身份识别等多种功能,方便企业进行商业服务的集成与拓展。 目前,微信小程序已经覆盖了电商购物、生活服务、娱乐休闲、教育学习、工具助手等多个领域,为数以亿计的用户提供便捷的服务入口,也为众多商家和开发者提供了新的商业模式和创业机会。随着技术的不断升级和完善,小程序已成为现代移动互联网生态中不可或缺的一部分。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值