|
@@ -0,0 +1,165 @@
|
|
|
|
+package com.futu.goose.user.service.impl;
|
|
|
|
+
|
|
|
|
+import cn.hutool.core.lang.Snowflake;
|
|
|
|
+import cn.hutool.core.util.IdUtil;
|
|
|
|
+import cn.hutool.http.HttpUtil;
|
|
|
|
+import com.alibaba.fastjson.JSON;
|
|
|
|
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
|
|
|
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
|
|
|
+import com.futu.goose.common.util.TokenUtils;
|
|
|
|
+import com.futu.goose.user.config.RedisKey;
|
|
|
|
+import com.futu.goose.user.domain.WechatUsers;
|
|
|
|
+import com.futu.goose.user.domain.TUser;
|
|
|
|
+import com.futu.goose.user.dto.WXAuth;
|
|
|
|
+import com.futu.goose.user.service.WechatUsersService;
|
|
|
|
+import com.futu.goose.user.dao.WechatUsersMapper;
|
|
|
|
+import com.futu.goose.user.dao.TUserMapper;
|
|
|
|
+import com.futu.goose.common.util.Result;
|
|
|
|
+import com.futu.goose.common.util.WxService;
|
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
|
+import org.redisson.api.RLock;
|
|
|
|
+import org.redisson.api.RedissonClient;
|
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
|
+import org.springframework.beans.factory.annotation.Value;
|
|
|
|
+import org.springframework.data.redis.core.RedisTemplate;
|
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
|
+import org.springframework.transaction.annotation.Transactional;
|
|
|
|
+
|
|
|
|
+import java.util.HashMap;
|
|
|
|
+import java.util.Map;
|
|
|
|
+import java.util.UUID;
|
|
|
|
+import java.util.concurrent.TimeUnit;
|
|
|
|
+
|
|
|
|
+@Slf4j
|
|
|
|
+@Service
|
|
|
|
+public class WechatUsersServiceImpl extends ServiceImpl<WechatUsersMapper, WechatUsers>
|
|
|
|
+ implements WechatUsersService {
|
|
|
|
+
|
|
|
|
+ @Value("${wechat.appid}")
|
|
|
|
+ private String appid;
|
|
|
|
+ @Value("${wechat.secret}")
|
|
|
|
+ private String secret;
|
|
|
|
+
|
|
|
|
+ @Autowired
|
|
|
|
+ private RedisTemplate<String, String> redisTemplate;
|
|
|
|
+ @Autowired
|
|
|
|
+ private WxService wxService;
|
|
|
|
+ @Autowired
|
|
|
|
+ private WechatUsersMapper wechatUsersMapper;
|
|
|
|
+ @Autowired
|
|
|
|
+ private TUserMapper userMapper;
|
|
|
|
+ @Autowired
|
|
|
|
+ private RedissonClient redissonClient;
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public Result getSessionId(String code) {
|
|
|
|
+ //拼接一个url
|
|
|
|
+ String url = "https://api.weixin.qq.com/sns/jscode2session?appid={0}&secret={1}&js_code={2}&grant_type=authorization_code";
|
|
|
|
+ String replaceUrl = url.replace("{0}", appid).replace("{1}", secret).replace("{2}", code);
|
|
|
|
+ String res = HttpUtil.get(replaceUrl);
|
|
|
|
+ String uuid = UUID.randomUUID().toString();
|
|
|
|
+ redisTemplate.opsForValue().set(RedisKey.WX_SESSION_ID + uuid, res, 5, TimeUnit.MINUTES);
|
|
|
|
+ Map<String, String> map = new HashMap<>();
|
|
|
|
+ map.put("sessionId", uuid);
|
|
|
|
+ return Result.OK(map);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ @Transactional
|
|
|
|
+ @Override
|
|
|
|
+ public Result authLogin(WXAuth wxAuth) {
|
|
|
|
+ try {
|
|
|
|
+ // 1. 从Redis获取session_key
|
|
|
|
+ String sessionInfo = redisTemplate.opsForValue().get(RedisKey.WX_SESSION_ID + wxAuth.getSessionId());
|
|
|
|
+ if (sessionInfo == null) {
|
|
|
|
+ return Result.ERROR("sessionId已过期,请重新登录");
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ Map<String, String> sessionMap = JSON.parseObject(sessionInfo, Map.class);
|
|
|
|
+ if (sessionMap == null) {
|
|
|
|
+ return Result.ERROR("无法解析session信息");
|
|
|
|
+ }
|
|
|
|
+ String openid = sessionMap.get("openid");
|
|
|
|
+ String unionid = sessionMap.get("unionid");
|
|
|
|
+ String sessionKey = sessionMap.get("session_key");
|
|
|
|
+ // 2. 解密用户信息(传入sessionKey而非sessionId)
|
|
|
|
+ String json = wxService.wxDecrypt(wxAuth.getEncryptedData(), wxAuth.getSessionId(), wxAuth.getIv());
|
|
|
|
+ if (json == null) {
|
|
|
|
+ return Result.ERROR("解密用户信息失败");
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ WechatUsers wechatUsers = JSON.parseObject(json, WechatUsers.class);
|
|
|
|
+
|
|
|
|
+ // 3. 检查微信用户是否存在
|
|
|
|
+ QueryWrapper<WechatUsers> wrapper = new QueryWrapper<>();
|
|
|
|
+ wrapper.eq("openid", openid);
|
|
|
|
+ //加锁
|
|
|
|
+ RLock lock = redissonClient.getLock(openid);
|
|
|
|
+ try {
|
|
|
|
+ boolean tryLock = lock.tryLock(3, TimeUnit.SECONDS);
|
|
|
|
+ if (!tryLock) {
|
|
|
|
+ throw new RuntimeException("操作频繁,请稍后再试");
|
|
|
|
+ }
|
|
|
|
+ WechatUsers dbWechatUser = wechatUsersMapper.selectOne(wrapper);
|
|
|
|
+
|
|
|
|
+ TUser user;
|
|
|
|
+ if (dbWechatUser == null) {
|
|
|
|
+ // 新用户注册
|
|
|
|
+ Snowflake snowflake = IdUtil.getSnowflake();
|
|
|
|
+ wechatUsers.setId(snowflake.nextId());
|
|
|
|
+ wechatUsers.setOpenid(openid);
|
|
|
|
+ wechatUsers.setUnionid(unionid);
|
|
|
|
+ wechatUsers.setSessionKey(sessionKey);
|
|
|
|
+ wechatUsersMapper.insert(wechatUsers);
|
|
|
|
+
|
|
|
|
+ // 创建基础用户信息
|
|
|
|
+ user = createNewUser(wechatUsers);
|
|
|
|
+ wechatUsers.setUserId(user.getId());
|
|
|
|
+ wechatUsersMapper.updateById(wechatUsers);
|
|
|
|
+ } else {
|
|
|
|
+ // 登录
|
|
|
|
+ user = userMapper.selectById(dbWechatUser.getUserId());
|
|
|
|
+ if (user == null) {
|
|
|
|
+ user = createNewUser(wechatUsers);
|
|
|
|
+ dbWechatUser.setUserId(user.getId());
|
|
|
|
+ wechatUsersMapper.updateById(dbWechatUser);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 4. 生成token
|
|
|
|
+ String token = TokenUtils.createJwtToken(user.getId().toString());
|
|
|
|
+ redisTemplate.opsForValue().set(RedisKey.USER_TOKEN + user.getId(), token, 7, TimeUnit.DAYS);
|
|
|
|
+
|
|
|
|
+ // 5. 返回结果
|
|
|
|
+ Map<String, Object> result = new HashMap<>();
|
|
|
|
+ result.put("token", token);
|
|
|
|
+ result.put("userInfo", user);
|
|
|
|
+ return Result.OK(result);
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
+ e.printStackTrace();
|
|
|
|
+ return Result.ERROR("错误"+e);
|
|
|
|
+ } finally {
|
|
|
|
+ if (lock.isLocked() && lock.isHeldByCurrentThread()) {
|
|
|
|
+ lock.unlock(); //解锁
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
+ log.error("微信登录失败: {}", e.getMessage(), e);
|
|
|
|
+ return Result.ERROR("登录失败: " + e.getMessage());
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private TUser createNewUser(WechatUsers wechatUser) {
|
|
|
|
+ TUser user = new TUser();
|
|
|
|
+ Snowflake snowflake = IdUtil.getSnowflake();
|
|
|
|
+ user.setId(snowflake.nextId());
|
|
|
|
+ // 生成随机用户名(微信用户_+时间戳)
|
|
|
|
+ user.setUsername("wx_user_" + System.currentTimeMillis());
|
|
|
|
+ user.setNickname(wechatUser.getNickname());
|
|
|
|
+ user.setAvatar(wechatUser.getAvatarUrl());
|
|
|
|
+ user.setGender(wechatUser.getGender());
|
|
|
|
+ user.setStatus(1);
|
|
|
|
+ userMapper.insert(user);
|
|
|
|
+ return user;
|
|
|
|
+ }
|
|
|
|
+}
|