对接微信小步调授权登录

尚未崩坏  论坛元老 | 2024-8-29 02:50:31 | 来自手机 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 1884|帖子 1884|积分 5652

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
一. 微信小步调授权登录



引入依靠

  1. <!--微信小程序-->
  2. <dependency>
  3.     <groupId>com.github.binarywang</groupId>
  4.     <artifactId>weixin-java-miniapp</artifactId>
  5.     <version>4.3.0</version>
  6. </dependency>
复制代码

修改设置文件

  1. wx:
  2.   # 微信小程序appid
  3.   app-id: wxcbxxxxxxxxxxxxxxx
  4.   # 小程序密钥
  5.   app-secret: 8ccxxxxxxxxxxxxxxxx
  6.   msgDataFormat: JSON
复制代码

设置类Properties

  1. import lombok.Data;
  2. import lombok.ToString;
  3. import org.springframework.boot.context.properties.ConfigurationProperties;
  4. import org.springframework.stereotype.Component;
  5. /**
  6. * @Author:Ccoo
  7. * @Date:2024/3/21 20:40
  8. */
  9. @Data
  10. @ToString
  11. @Component
  12. @ConfigurationProperties(prefix = "wx")
  13. public class WxProperties {
  14.     /**
  15.      * 设置微信小程序的appid
  16.      */
  17.     private String appId;
  18.     /**
  19.      * 设置微信小程序的Secret
  20.      */
  21.     private String appSecret;
  22.     /**
  23.      * 消息格式,XML或者JSON
  24.      */
  25.     private String msgDataFormat;
  26. }
复制代码

设置类Config

  1. import cn.binarywang.wx.miniapp.api.WxMaService;
  2. import cn.binarywang.wx.miniapp.api.WxMaUserService;
  3. import cn.binarywang.wx.miniapp.api.impl.WxMaServiceImpl;
  4. import cn.binarywang.wx.miniapp.api.impl.WxMaUserServiceImpl;
  5. import cn.binarywang.wx.miniapp.config.impl.WxMaDefaultConfigImpl;
  6. import lombok.extern.slf4j.Slf4j;
  7. import me.chanjar.weixin.common.error.WxRuntimeException;
  8. import org.springframework.context.annotation.Bean;
  9. import org.springframework.context.annotation.Configuration;
  10. import javax.annotation.Resource;
  11. import java.util.HashMap;
  12. import java.util.Objects;
  13. @Slf4j
  14. @Configuration
  15. public class WxMaConfiguration {
  16.     @Resource
  17.     private WxProperties wxProperties;
  18.     @Bean
  19.     public WxMaService wxMaService() {
  20.         if (Objects.isNull(wxProperties)) {
  21.             throw new WxRuntimeException("请添加下相关配置, 注意别配错了!");
  22.         }
  23.         WxMaService maService = new WxMaServiceImpl();
  24.         try {
  25.             WxMaDefaultConfigImpl config = new WxMaDefaultConfigImpl();
  26.             config.setAppid(wxProperties.getAppId());
  27.             config.setSecret(wxProperties.getAppSecret());
  28.             config.setMsgDataFormat(wxProperties.getMsgDataFormat());
  29.             HashMap configMap = new HashMap<>();
  30.             configMap.put(config.getAppid(), config);
  31.             maService.setMultiConfigs(configMap);
  32.         } catch (Exception e) {
  33.             throw new WxRuntimeException("微信小程序相关配置配置失败!");
  34.         }
  35.         return maService;
  36.     }
  37. }
复制代码

Controller控制器代码

  1. import com.itheima.mp.domain.R;
  2. import com.itheima.mp.service.WeChatService;
  3. import io.swagger.annotations.ApiOperation;
  4. import io.swagger.annotations.ApiParam;
  5. import org.springframework.beans.factory.annotation.Autowired;
  6. import org.springframework.web.bind.annotation.PostMapping;
  7. import org.springframework.web.bind.annotation.RequestMapping;
  8. import org.springframework.web.bind.annotation.RequestParam;
  9. import org.springframework.web.bind.annotation.RestController;
  10. /**
  11. * <p>
  12. *  前端控制器
  13. * </p>
  14. *
  15. * @author Ccoo
  16. * @since 2023-10-01
  17. */
  18. @RestController
  19. @RequestMapping("/wechat")
  20. public class WeChatController {
  21.         @Autowired
  22.         private WeChatService wechatService;
  23.         @ApiOperation(value = "微信小程序授权登录", notes = "微信小程序授权登录")
  24.         @PostMapping("/wxLogin")
  25.         public R<?> wxLogin(@ApiParam("loginCode") @RequestParam String code) {
  26.                 return wechatService.wxLogin(code);
  27.         }
  28. }
复制代码

Service接口层代码

  1. import com.itheima.mp.domain.R;
  2. /**
  3. * @author Ccoo
  4. * 2024/8/23
  5. */
  6. public interface WeChatService {
  7.         /**
  8.          * 微信授权登录
  9.          * @param code  授权码
  10.          * @return 结果
  11.          */
  12.         R<?> wxLogin(String code);
  13. }
复制代码

ServiceImpl实现层代码

  1. import cn.binarywang.wx.miniapp.api.WxMaService;
  2. import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
  3. import cn.hutool.json.JSONUtil;
  4. import lombok.RequiredArgsConstructor;
  5. import lombok.extern.slf4j.Slf4j;
  6. import me.chanjar.weixin.common.error.WxErrorException;
  7. import org.springframework.stereotype.Service;
  8. /**
  9. * @author Ccoo
  10. * 2024/8/23
  11. */
  12. @Slf4j
  13. @Service
  14. @RequiredArgsConstructor
  15. public class WeChatServiceImpl implements WeChatService {
  16.         private final WxMaService wxMaService;
  17.         /**
  18.          * 微信授权登录
  19.          *
  20.          * @param code 授权码
  21.          * @return 结果
  22.          */
  23.         @Override
  24.         public R<?> wxLogin(String code) {
  25.                
  26.                 try {
  27.                         WxMaJscode2SessionResult sessionInfo = wxMaService.getUserService().getSessionInfo(code);
  28.                         String info = JSONUtil.toJsonStr(sessionInfo);
  29.                         log.info("微信授权登录成功:{}", info);
  30.                         return R.ok(info);
  31.                 } catch (WxErrorException e) {
  32.                         log.error("微信授权登录失败:{}", e.getError().getErrorMsg());
  33.                         return R.fail(e.getError().getErrorCode(), e.getError().getErrorMsg());
  34.                 }
  35.         }
  36. }
复制代码

同一相应类 R

  1. import java.io.Serializable;
  2. /**
  3. * 响应信息主体
  4. *
  5. * @author Ccoo
  6. */
  7. public class R<T> implements Serializable
  8. {
  9.     private static final long serialVersionUID = 1L;
  10.     /** 成功 */
  11.     public static final int SUCCESS = 200;
  12.     /** 失败 */
  13.     public static final int FAIL = 500;
  14.     private int code;
  15.     private String msg;
  16.     private T data;
  17.     public static <T> R<T> ok()
  18.     {
  19.         return restResult(null, SUCCESS, "操作成功");
  20.     }
  21.     public static <T> R<T> ok(String msg)
  22.     {
  23.         return restResult(null, SUCCESS, msg);
  24.     }
  25.     public static <T> R<T> ok(T data)
  26.     {
  27.         return restResult(data, SUCCESS, "操作成功");
  28.     }
  29.     public static <T> R<T> ok(T data, String msg)
  30.     {
  31.         return restResult(data, SUCCESS, msg);
  32.     }
  33.     public static <T> R<T> fail()
  34.     {
  35.         return restResult(null, FAIL, "操作失败");
  36.     }
  37.     public static <T> R<T> fail(String msg)
  38.     {
  39.         return restResult(null, FAIL, msg);
  40.     }
  41.     public static <T> R<T> fail(T data)
  42.     {
  43.         return restResult(data, FAIL, "操作失败");
  44.     }
  45.     public static <T> R<T> fail(T data, String msg)
  46.     {
  47.         return restResult(data, FAIL, msg);
  48.     }
  49.     public static <T> R<T> fail(int code, String msg)
  50.     {
  51.         return restResult(null, code, msg);
  52.     }
  53.     private static <T> R<T> restResult(T data, int code, String msg)
  54.     {
  55.         R<T> apiResult = new R<>();
  56.         apiResult.setCode(code);
  57.         apiResult.setData(data);
  58.         apiResult.setMsg(msg);
  59.         return apiResult;
  60.     }
  61.     public int getCode()
  62.     {
  63.         return code;
  64.     }
  65.     public void setCode(int code)
  66.     {
  67.         this.code = code;
  68.     }
  69.     public String getMsg()
  70.     {
  71.         return msg;
  72.     }
  73.     public void setMsg(String msg)
  74.     {
  75.         this.msg = msg;
  76.     }
  77.     public T getData()
  78.     {
  79.         return data;
  80.     }
  81.     public void setData(T data)
  82.     {
  83.         this.data = data;
  84.     }
  85. }
复制代码

具体授权登录代码

   微信小步调授权登录思路 :
  

  • 先判断Redis中缓存是否命中, 如果命中则直接返回缓存信息
  • 如果未命中缓存, 则使用暂时校验码code去微信调换openid
  • 查询数据库该openid对应用户信息是否存在, 存在则直接返回, 不存在则注册用户信息
  • 最后将用户信息存入redis, 并返回相应的token供下次授权登录前判断是否缓存信息
   具体实当代码如下
  1. @ApiOperation("微信授权登录")
  2. @PostMapping("/customer_login")
  3. public R<SysWxUser> customerLogin(@RequestBody WXAuth wxAuth) {
  4.     return weixinService.customerLogin(wxAuth);
  5. }
复制代码
  1. R<SysWxUser> customerLogin(WXAuth wxAuth);
复制代码
  1. /**
  2. * 授权登录
  3. *
  4. * @param wxAuth 授权信息
  5. * @return 结果
  6. */
  7. @Override
  8. public R<SysWxUser> customerLogin(WXAuth wxAuth) {
  9.     String code = wxAuth.getCode();
  10.     String iv = wxAuth.getIv();
  11.     String token = wxAuth.getToken();
  12.     String encryptedData = wxAuth.getEncryptedData();
  13.     if(StrUtil.isBlank(code) && StrUtil.isBlank(token)){
  14.         return R.fail(MessageConstants.PARAMS_ERROR);
  15.     }
  16.     // 判断登录态是否在有效期
  17.     if(StrUtil.isNotBlank(token)){
  18.         // token不为空  判断token是否过期
  19.         String content = redisTemplate.opsForValue().get(RedisKey.WX_SESSION_KEY + token);
  20.         if(content == null){
  21.             return R.fail(MessageConstants.TOKEN_NOT_EXIST);
  22.         }
  23.         // 查询token对应用户信息
  24.         SysWxUser info = JSONUtil.toBean(content, SysWxUser.class);
  25.         // 刷新token有效时间
  26.         redisTemplate.opsForValue().set(RedisKey.WX_SESSION_KEY + token, content, 3600, TimeUnit.SECONDS);
  27.         return R.ok(info);
  28.     }
  29.     SysWxUser wxUser = null;
  30.     WxMaJscode2SessionResult sessionInfo = null;
  31.     try {
  32.         sessionInfo = wxMaService.getUserService().getSessionInfo(code);
  33.         WxMaUserInfo userInfo = wxMaService.getUserService().getUserInfo(sessionInfo.getSessionKey(), encryptedData, iv);
  34.         
  35.         String openid = sessionInfo.getOpenid();
  36.         
  37.         // 使用微信openId查询是否有此用户(WxUser)
  38.         wxUser = lambdaQuery().eq(SysWxUser::getOpenid, openid).one();
  39.         
  40.         // 不存在 构建用户信息进行注册
  41.         if(wxUser == null) {
  42.             wxUser = new SysWxUser();
  43.             wxUser.setOpenid(openid);
  44.             wxUser.setWxName(Constants.WX_PREFIX + RandomUtil.randomString(6));
  45.             wxUser.setAvatarUrl(userInfo.getAvatarUrl());
  46.             int insert = wxUserMapper.insert(wxUser);
  47.             if (insert == 0) {
  48.                 return R.fail(MessageConstants.USER_BIND_ERROR);
  49.             }
  50.         }
  51.         
  52.     } catch (Exception e) {
  53.         e.printStackTrace();
  54.         log.error(MessageConstants.SYSTEM_ERROR);
  55.     }
  56.     String sessionKey = sessionInfo.getSessionKey();
  57.     String cacheKey = RedisKey.WX_SESSION_KEY + sessionKey;
  58.     // 将 openid / sessionKey 存入redis
  59.     redisTemplate.opsForValue().set(cacheKey, JSONUtil.toJsonStr(wxUser), 3600, TimeUnit.SECONDS);
  60.     return R.ok(wxUser,Constants.TOKEN_PRE + sessionKey);
  61. }
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

尚未崩坏

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表