当前位置: 首页 > news >正文

对接微信小程序授权登录

文章目录

    • 一. 微信小程序授权登录
      • 引入依赖
      • 修改配置文件
      • 配置类Properties
      • 配置类Config
      • Controller控制器代码
      • Service接口层代码
      • ServiceImpl实现层代码
      • 统一响应类 R
      • 具体授权登录代码

一. 微信小程序授权登录



引入依赖

<!--微信小程序-->
<dependency><groupId>com.github.binarywang</groupId><artifactId>weixin-java-miniapp</artifactId><version>4.3.0</version>
</dependency>

修改配置文件

wx:# 微信小程序appidapp-id: wxcbxxxxxxxxxxxxxxx# 小程序密钥app-secret: 8ccxxxxxxxxxxxxxxxxmsgDataFormat: JSON

配置类Properties

import lombok.Data;
import lombok.ToString;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;/*** @Author:Ccoo* @Date:2024/3/21 20:40*/
@Data
@ToString
@Component
@ConfigurationProperties(prefix = "wx")
public class WxProperties {/*** 设置微信小程序的appid*/private String appId;/*** 设置微信小程序的Secret*/private String appSecret;/*** 消息格式,XML或者JSON*/private String msgDataFormat;}

配置类Config

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.api.WxMaUserService;
import cn.binarywang.wx.miniapp.api.impl.WxMaServiceImpl;
import cn.binarywang.wx.miniapp.api.impl.WxMaUserServiceImpl;
import cn.binarywang.wx.miniapp.config.impl.WxMaDefaultConfigImpl;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxRuntimeException;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Objects;@Slf4j
@Configuration
public class WxMaConfiguration {@Resourceprivate WxProperties wxProperties;@Beanpublic WxMaService wxMaService() {if (Objects.isNull(wxProperties)) {throw new WxRuntimeException("请添加下相关配置, 注意别配错了!");}WxMaService maService = new WxMaServiceImpl();try {WxMaDefaultConfigImpl config = new WxMaDefaultConfigImpl();config.setAppid(wxProperties.getAppId());config.setSecret(wxProperties.getAppSecret());config.setMsgDataFormat(wxProperties.getMsgDataFormat());HashMap configMap = new HashMap<>();configMap.put(config.getAppid(), config);maService.setMultiConfigs(configMap);} catch (Exception e) {throw new WxRuntimeException("微信小程序相关配置配置失败!");}return maService;}}

Controller控制器代码

import com.itheima.mp.domain.R;
import com.itheima.mp.service.WeChatService;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;/*** <p>*  前端控制器* </p>** @author Ccoo* @since 2023-10-01*/
@RestController
@RequestMapping("/wechat")
public class WeChatController {@Autowiredprivate WeChatService wechatService;@ApiOperation(value = "微信小程序授权登录", notes = "微信小程序授权登录")@PostMapping("/wxLogin")public R<?> wxLogin(@ApiParam("loginCode") @RequestParam String code) {return wechatService.wxLogin(code);}}

Service接口层代码

import com.itheima.mp.domain.R;/*** @author Ccoo* 2024/8/23*/
public interface WeChatService {/*** 微信授权登录* @param code  授权码* @return 结果*/R<?> wxLogin(String code);}

ServiceImpl实现层代码

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.hutool.json.JSONUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import org.springframework.stereotype.Service;/*** @author Ccoo* 2024/8/23*/
@Slf4j
@Service
@RequiredArgsConstructor
public class WeChatServiceImpl implements WeChatService {private final WxMaService wxMaService;/*** 微信授权登录** @param code 授权码* @return 结果*/@Overridepublic R<?> wxLogin(String code) {try {WxMaJscode2SessionResult sessionInfo = wxMaService.getUserService().getSessionInfo(code);String info = JSONUtil.toJsonStr(sessionInfo);log.info("微信授权登录成功:{}", info);return R.ok(info);} catch (WxErrorException e) {log.error("微信授权登录失败:{}", e.getError().getErrorMsg());return R.fail(e.getError().getErrorCode(), e.getError().getErrorMsg());}}
}

统一响应类 R

import java.io.Serializable;/*** 响应信息主体** @author Ccoo*/
public class R<T> implements Serializable
{private static final long serialVersionUID = 1L;/** 成功 */public static final int SUCCESS = 200;/** 失败 */public static final int FAIL = 500;private int code;private String msg;private T data;public static <T> R<T> ok(){return restResult(null, SUCCESS, "操作成功");}public static <T> R<T> ok(String msg){return restResult(null, SUCCESS, msg);}public static <T> R<T> ok(T data){return restResult(data, SUCCESS, "操作成功");}public static <T> R<T> ok(T data, String msg){return restResult(data, SUCCESS, msg);}public static <T> R<T> fail(){return restResult(null, FAIL, "操作失败");}public static <T> R<T> fail(String msg){return restResult(null, FAIL, msg);}public static <T> R<T> fail(T data){return restResult(data, FAIL, "操作失败");}public static <T> R<T> fail(T data, String msg){return restResult(data, FAIL, msg);}public static <T> R<T> fail(int code, String msg){return restResult(null, code, msg);}private static <T> R<T> restResult(T data, int code, String msg){R<T> apiResult = new R<>();apiResult.setCode(code);apiResult.setData(data);apiResult.setMsg(msg);return apiResult;}public int getCode(){return code;}public void setCode(int code){this.code = code;}public String getMsg(){return msg;}public void setMsg(String msg){this.msg = msg;}public T getData(){return data;}public void setData(T data){this.data = data;}
}

具体授权登录代码

微信小程序授权登录思路 :

  1. 先判断Redis中缓存是否命中, 如果命中则直接返回缓存信息
  2. 如果未命中缓存, 则使用临时校验码code去微信换取openid
  3. 查询数据库该openid对应用户信息是否存在, 存在则直接返回, 不存在则注册用户信息
  4. 最后将用户信息存入redis, 并返回相应的token供下次授权登录前判断是否缓存信息

具体实现代码如下

@ApiOperation("微信授权登录")
@PostMapping("/customer_login")
public R<SysWxUser> customerLogin(@RequestBody WXAuth wxAuth) {return weixinService.customerLogin(wxAuth);
}
R<SysWxUser> customerLogin(WXAuth wxAuth);
/*** 授权登录** @param wxAuth 授权信息* @return 结果*/
@Override
public R<SysWxUser> customerLogin(WXAuth wxAuth) {String code = wxAuth.getCode();String iv = wxAuth.getIv();String token = wxAuth.getToken();String encryptedData = wxAuth.getEncryptedData();if(StrUtil.isBlank(code) && StrUtil.isBlank(token)){return R.fail(MessageConstants.PARAMS_ERROR);}// 判断登录态是否在有效期if(StrUtil.isNotBlank(token)){// token不为空  判断token是否过期String content = redisTemplate.opsForValue().get(RedisKey.WX_SESSION_KEY + token);if(content == null){return R.fail(MessageConstants.TOKEN_NOT_EXIST);}// 查询token对应用户信息SysWxUser info = JSONUtil.toBean(content, SysWxUser.class);// 刷新token有效时间redisTemplate.opsForValue().set(RedisKey.WX_SESSION_KEY + token, content, 3600, TimeUnit.SECONDS);return R.ok(info);}SysWxUser wxUser = null;WxMaJscode2SessionResult sessionInfo = null;try {sessionInfo = wxMaService.getUserService().getSessionInfo(code);WxMaUserInfo userInfo = wxMaService.getUserService().getUserInfo(sessionInfo.getSessionKey(), encryptedData, iv);String openid = sessionInfo.getOpenid();// 使用微信openId查询是否有此用户(WxUser)wxUser = lambdaQuery().eq(SysWxUser::getOpenid, openid).one();// 不存在 构建用户信息进行注册if(wxUser == null) {wxUser = new SysWxUser();wxUser.setOpenid(openid);wxUser.setWxName(Constants.WX_PREFIX + RandomUtil.randomString(6));wxUser.setAvatarUrl(userInfo.getAvatarUrl());int insert = wxUserMapper.insert(wxUser);if (insert == 0) {return R.fail(MessageConstants.USER_BIND_ERROR);}}} catch (Exception e) {e.printStackTrace();log.error(MessageConstants.SYSTEM_ERROR);}String sessionKey = sessionInfo.getSessionKey();String cacheKey = RedisKey.WX_SESSION_KEY + sessionKey;// 将 openid / sessionKey 存入redisredisTemplate.opsForValue().set(cacheKey, JSONUtil.toJsonStr(wxUser), 3600, TimeUnit.SECONDS);return R.ok(wxUser,Constants.TOKEN_PRE + sessionKey);
}

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • qt处理表格,Qtxlsx库文件的安装以及导入
  • Python 点云ISS关键点提取算法
  • 文本向量化的六种常见模式
  • Spark MLlib模型训练—分类算法Multinomial Logistic Regression
  • SAP 表格设置全部隐藏后的恢复问题
  • Centos服务器配置使用密钥登录
  • oracle 重做日志(Redo LogBuffer)
  • uni-app开发日志:schema2code生成的新增页和修改页因字段太多用分段器实现分段分类
  • 【iOS端】基于Uniapp跨平台接入即构RTC+相芯美颜
  • 使用 Python TorchRL 进行多代理强化学习
  • 【AI大模型】提示词(Prompt)全面解析
  • 前端数据爬虫之puppeteer
  • 如何监控Spring Boot 项目运行情况?
  • Hive SQL 练习
  • 网络版本控制:协同进化的基石
  • 【407天】跃迁之路——程序员高效学习方法论探索系列(实验阶段164-2018.03.19)...
  • Debian下无root权限使用Python访问Oracle
  • gops —— Go 程序诊断分析工具
  • If…else
  • vue--为什么data属性必须是一个函数
  • zookeeper系列(七)实战分布式命名服务
  • 对象管理器(defineProperty)学习笔记
  • 多线程事务回滚
  • 分享一份非常强势的Android面试题
  • 前端临床手札——文件上传
  • 区块链将重新定义世界
  • 一加3T解锁OEM、刷入TWRP、第三方ROM以及ROOT
  • 赢得Docker挑战最佳实践
  • ​configparser --- 配置文件解析器​
  • ​LeetCode解法汇总2182. 构造限制重复的字符串
  • !! 2.对十份论文和报告中的关于OpenCV和Android NDK开发的总结
  • # MySQL server 层和存储引擎层是怎么交互数据的?
  • #HarmonyOS:基础语法
  • ${factoryList }后面有空格不影响
  • $LayoutParams cannot be cast to android.widget.RelativeLayout$LayoutParams
  • (14)目标检测_SSD训练代码基于pytorch搭建代码
  • (C#)Windows Shell 外壳编程系列4 - 上下文菜单(iContextMenu)(二)嵌入菜单和执行命令...
  • (java版)排序算法----【冒泡,选择,插入,希尔,快速排序,归并排序,基数排序】超详细~~
  • (二)PySpark3:SparkSQL编程
  • (二)斐波那契Fabonacci函数
  • (二)构建dubbo分布式平台-平台功能导图
  • (二刷)代码随想录第16天|104.二叉树的最大深度 559.n叉树的最大深度● 111.二叉树的最小深度● 222.完全二叉树的节点个数
  • (附源码)springboot 智能停车场系统 毕业设计065415
  • (论文阅读23/100)Hierarchical Convolutional Features for Visual Tracking
  • (论文阅读30/100)Convolutional Pose Machines
  • (七)Java对象在Hibernate持久化层的状态
  • (推荐)叮当——中文语音对话机器人
  • (一)python发送HTTP 请求的两种方式(get和post )
  • (幽默漫画)有个程序员老公,是怎样的体验?
  • (转载)Linux 多线程条件变量同步
  • .NET 依赖注入和配置系统
  • .net操作Excel出错解决
  • .NET框架设计—常被忽视的C#设计技巧
  • .net用HTML开发怎么调试,如何使用ASP.NET MVC在调试中查看控制器生成的html?
  • :=