feng_ting-ting 3 dagen geleden
bovenliggende
commit
3025204e2b

+ 136 - 0
src/main/java/com/zhentao/user/domain/User.java

@@ -0,0 +1,136 @@
+package com.zhentao.user.domain;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import java.io.Serializable;
+import java.util.Date;
+import lombok.Data;
+
+/**
+ * @TableName user
+ */
+@TableName(value ="user")
+@Data
+public class User implements Serializable {
+    @TableId(type = IdType.AUTO)
+    private Integer userId;
+
+    private String username;
+
+    private String password;
+
+    private String realName;
+
+    private Integer gender;
+
+    private Date birthday;
+
+    private String mobile;
+
+    private Integer role;
+
+    private Date createTime;
+
+    private Date lastLoginTime;
+
+    private String wxOpenid;
+
+    private String wxUnionid;
+
+    private String wxNickname;
+
+    private String wxAvatarUrl;
+
+    private String wxSessionKey;
+
+    private Date wxLastLoginTime;
+
+    private Integer loginType;
+
+    private static final long serialVersionUID = 1L;
+
+    @Override
+    public boolean equals(Object that) {
+        if (this == that) {
+            return true;
+        }
+        if (that == null) {
+            return false;
+        }
+        if (getClass() != that.getClass()) {
+            return false;
+        }
+        User other = (User) that;
+        return (this.getUserId() == null ? other.getUserId() == null : this.getUserId().equals(other.getUserId()))
+            && (this.getUsername() == null ? other.getUsername() == null : this.getUsername().equals(other.getUsername()))
+            && (this.getPassword() == null ? other.getPassword() == null : this.getPassword().equals(other.getPassword()))
+            && (this.getRealName() == null ? other.getRealName() == null : this.getRealName().equals(other.getRealName()))
+            && (this.getGender() == null ? other.getGender() == null : this.getGender().equals(other.getGender()))
+            && (this.getBirthday() == null ? other.getBirthday() == null : this.getBirthday().equals(other.getBirthday()))
+            && (this.getMobile() == null ? other.getMobile() == null : this.getMobile().equals(other.getMobile()))
+            && (this.getRole() == null ? other.getRole() == null : this.getRole().equals(other.getRole()))
+            && (this.getCreateTime() == null ? other.getCreateTime() == null : this.getCreateTime().equals(other.getCreateTime()))
+            && (this.getLastLoginTime() == null ? other.getLastLoginTime() == null : this.getLastLoginTime().equals(other.getLastLoginTime()))
+            && (this.getWxOpenid() == null ? other.getWxOpenid() == null : this.getWxOpenid().equals(other.getWxOpenid()))
+            && (this.getWxUnionid() == null ? other.getWxUnionid() == null : this.getWxUnionid().equals(other.getWxUnionid()))
+            && (this.getWxNickname() == null ? other.getWxNickname() == null : this.getWxNickname().equals(other.getWxNickname()))
+            && (this.getWxAvatarUrl() == null ? other.getWxAvatarUrl() == null : this.getWxAvatarUrl().equals(other.getWxAvatarUrl()))
+            && (this.getWxSessionKey() == null ? other.getWxSessionKey() == null : this.getWxSessionKey().equals(other.getWxSessionKey()))
+            && (this.getWxLastLoginTime() == null ? other.getWxLastLoginTime() == null : this.getWxLastLoginTime().equals(other.getWxLastLoginTime()))
+            && (this.getLoginType() == null ? other.getLoginType() == null : this.getLoginType().equals(other.getLoginType()));
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((getUserId() == null) ? 0 : getUserId().hashCode());
+        result = prime * result + ((getUsername() == null) ? 0 : getUsername().hashCode());
+        result = prime * result + ((getPassword() == null) ? 0 : getPassword().hashCode());
+        result = prime * result + ((getRealName() == null) ? 0 : getRealName().hashCode());
+        result = prime * result + ((getGender() == null) ? 0 : getGender().hashCode());
+        result = prime * result + ((getBirthday() == null) ? 0 : getBirthday().hashCode());
+        result = prime * result + ((getMobile() == null) ? 0 : getMobile().hashCode());
+        result = prime * result + ((getRole() == null) ? 0 : getRole().hashCode());
+        result = prime * result + ((getCreateTime() == null) ? 0 : getCreateTime().hashCode());
+        result = prime * result + ((getLastLoginTime() == null) ? 0 : getLastLoginTime().hashCode());
+        result = prime * result + ((getWxOpenid() == null) ? 0 : getWxOpenid().hashCode());
+        result = prime * result + ((getWxUnionid() == null) ? 0 : getWxUnionid().hashCode());
+        result = prime * result + ((getWxNickname() == null) ? 0 : getWxNickname().hashCode());
+        result = prime * result + ((getWxAvatarUrl() == null) ? 0 : getWxAvatarUrl().hashCode());
+        result = prime * result + ((getWxSessionKey() == null) ? 0 : getWxSessionKey().hashCode());
+        result = prime * result + ((getWxLastLoginTime() == null) ? 0 : getWxLastLoginTime().hashCode());
+        result = prime * result + ((getLoginType() == null) ? 0 : getLoginType().hashCode());
+        return result;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append(getClass().getSimpleName());
+        sb.append(" [");
+        sb.append("Hash = ").append(hashCode());
+        sb.append(", userId=").append(userId);
+        sb.append(", username=").append(username);
+        sb.append(", password=").append(password);
+        sb.append(", realName=").append(realName);
+        sb.append(", gender=").append(gender);
+        sb.append(", birthday=").append(birthday);
+        sb.append(", mobile=").append(mobile);
+        sb.append(", role=").append(role);
+        sb.append(", createTime=").append(createTime);
+        sb.append(", lastLoginTime=").append(lastLoginTime);
+        sb.append(", wxOpenid=").append(wxOpenid);
+        sb.append(", wxUnionid=").append(wxUnionid);
+        sb.append(", wxNickname=").append(wxNickname);
+        sb.append(", wxAvatarUrl=").append(wxAvatarUrl);
+        sb.append(", wxSessionKey=").append(wxSessionKey);
+        sb.append(", wxLastLoginTime=").append(wxLastLoginTime);
+        sb.append(", loginType=").append(loginType);
+        sb.append(", serialVersionUID=").append(serialVersionUID);
+        sb.append("]");
+        return sb.toString();
+    }
+}

+ 20 - 0
src/main/java/com/zhentao/user/mapper/UserMapper.java

@@ -0,0 +1,20 @@
+package com.zhentao.user.mapper;
+
+import com.zhentao.user.domain.User;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+* @author ASUS
+* @description 针对表【user(用户基本信息表)】的数据库操作Mapper
+* @createDate 2025-05-20 09:53:17
+* @Entity com.zhentao.user.domain.User
+*/
+@Mapper
+public interface UserMapper extends BaseMapper<User> {
+
+}
+
+
+
+

+ 15 - 0
src/main/java/com/zhentao/user/service/UserService.java

@@ -0,0 +1,15 @@
+package com.zhentao.user.service;
+
+import com.zhentao.user.domain.User;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.zhentao.user.dto.LoginResponseDTO;
+import com.zhentao.user.dto.WechatLoginDTO;
+
+/**
+* @author ASUS
+* @description 针对表【user(用户基本信息表)】的数据库操作Service
+* @createDate 2025-05-20 09:53:17
+*/
+public interface UserService extends IService<User> {
+    LoginResponseDTO wechatLogin(WechatLoginDTO dto);
+}

+ 194 - 0
src/main/java/com/zhentao/user/service/impl/UserServiceImpl.java

@@ -0,0 +1,194 @@
+package com.zhentao.user.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.zhentao.user.domain.User;
+import com.zhentao.user.service.UserService;
+import com.zhentao.user.mapper.UserMapper;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.zhentao.user.dto.LoginResponseDTO;
+import com.zhentao.user.dto.WechatLoginDTO;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.util.LinkedMultiValueMap;
+import org.springframework.util.MultiValueMap;
+import org.springframework.web.client.RestTemplate;
+
+import javax.annotation.Resource;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+import java.util.concurrent.TimeUnit;
+
+/**
+* @author ASUS
+* @description 针对表【user(用户基本信息表)】的数据库操作Service实现
+* @createDate 2025-05-20 09:53:17
+*/
+@Service
+@Slf4j
+public class UserServiceImpl extends ServiceImpl<UserMapper, User>
+    implements UserService{
+    @Value("${wx.appid}")
+    private String appId;
+
+    @Value("${wx.secret}")
+    private String appSecret;
+
+    @Value("${wx.login-url}")
+    private String loginUrl;
+
+    @Autowired
+    private RedisTemplate<String, Object> redisTemplate;
+
+    @Autowired
+    private RestTemplate restTemplate;
+
+    @Override
+    public LoginResponseDTO wechatLogin(WechatLoginDTO dto) {
+        try {
+            // 1. 向微信服务器换取session_key和openid
+            Map<String, String> wxResult = getWxSession(dto.getCode());
+            String openid = wxResult.get("openid");
+            String sessionKey = wxResult.get("session_key");
+
+            if (openid == null || sessionKey == null) {
+                log.error("微信登录失败:获取openid或session_key失败,返回结果: {}", wxResult);
+                throw new RuntimeException("微信登录失败:获取openid或session_key失败");
+            }
+
+            // 2. 查询或创建用户
+            User user = getUserByOpenid(openid);
+            boolean isNewUser = false;
+
+            if (user == null) {
+                // 创建新用户
+                user = createWechatUser(openid, sessionKey, dto);
+                isNewUser = true;
+            } else {
+                // 更新用户信息和session_key
+                updateUserInfo(user, sessionKey, dto);
+            }
+
+            // 3. 生成JWT Token并缓存到Redis
+            String token = generateToken(user.getUserId());
+            cacheUserToken(user.getUserId(), token);
+
+            // 4. 构建响应
+            LoginResponseDTO response = new LoginResponseDTO();
+            response.setUserId(user.getUserId());
+            response.setToken(token);
+            response.setLoginType(user.getLoginType());
+            response.setWxNickname(user.getWxNickname());
+            response.setWxAvatarUrl(user.getWxAvatarUrl());
+            response.setIsNewUser(isNewUser);
+
+            return response;
+        } catch (Exception e) {
+            log.error("微信登录服务出错,请求参数: {}", dto, e);
+            throw e;
+        }
+    }
+
+    private Map<String, String> getWxSession(String code) {
+        MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
+        params.add("appid", appId);
+        params.add("secret", appSecret);
+        params.add("js_code", code);
+        params.add("grant_type", "authorization_code");
+
+        String result = restTemplate.postForObject(loginUrl, params, String.class);
+
+        try {
+            ObjectMapper mapper = new ObjectMapper();
+            Map<String, Object> resultMap = mapper.readValue(result, Map.class);
+
+            if (resultMap.containsKey("errcode")) {
+                log.error("微信登录失败,错误码:{},错误信息:{}",
+                        resultMap.get("errcode"),
+                        resultMap.get("errmsg"));
+                return new HashMap<>();
+            }
+
+            Map<String, String> sessionInfo = new HashMap<>();
+            sessionInfo.put("openid", (String) resultMap.get("openid"));
+            sessionInfo.put("session_key", (String) resultMap.get("session_key"));
+            return sessionInfo;
+        } catch (Exception e) {
+            log.error("解析微信登录结果失败", e);
+            return new HashMap<>();
+        }
+    }
+
+    private User getUserByOpenid(String openid) {
+        return this.getOne(new LambdaQueryWrapper<User>()
+                .eq(User::getWxOpenid, openid));
+    }
+
+    private User createWechatUser(String openid, String sessionKey, WechatLoginDTO dto) {
+        User user = new User();
+        user.setWxOpenid(openid);
+        user.setWxSessionKey(sessionKey);
+        user.setLoginType(1); // 1=微信登录
+    
+        // 如果有用户信息,填充到实体
+        if (dto.getRawData() != null) {
+            try {
+                ObjectMapper mapper = new ObjectMapper();
+                Map<String, Object> userInfo = mapper.readValue(dto.getRawData(), Map.class);
+                user.setWxNickname((String) userInfo.get("nickName"));
+                user.setGender(Integer.parseInt(userInfo.get("gender").toString()));
+                user.setWxAvatarUrl((String) userInfo.get("avatarUrl"));
+                log.info("成功解析用户信息,昵称: {}, 头像: {}", user.getWxNickname(), user.getWxAvatarUrl()); // 添加日志输出
+            } catch (Exception e) {
+                log.error("解析微信用户信息失败", e); // 修改为 error 级别日志
+            }
+        }
+
+        this.save(user);
+        return user;
+    }
+
+    private void updateUserInfo(User user, String sessionKey, WechatLoginDTO dto) {
+        user.setWxSessionKey(sessionKey);
+        user.setWxLastLoginTime(new java.util.Date());
+    
+        // 如果有新的用户信息,更新
+        if (dto.getRawData() != null) {
+            try {
+                ObjectMapper mapper = new ObjectMapper();
+                Map<String, Object> userInfo = mapper.readValue(dto.getRawData(), Map.class);
+                user.setWxNickname((String) userInfo.get("nickName"));
+                user.setGender(Integer.parseInt(userInfo.get("gender").toString()));
+                user.setWxAvatarUrl((String) userInfo.get("avatarUrl"));
+                log.info("成功更新用户信息,昵称: {}, 头像: {}", user.getWxNickname(), user.getWxAvatarUrl()); // 添加日志输出
+            } catch (Exception e) {
+                log.error("解析微信用户信息失败", e); // 修改为 error 级别日志
+            }
+        }
+
+        this.updateById(user);
+    }
+
+    private String generateToken(Integer userId) {
+        // 生成唯一Token
+        return UUID.randomUUID().toString().replace("-", "");
+    }
+
+    private void cacheUserToken(Integer userId, String token) {
+        // 将Token缓存到Redis,有效期24小时
+        redisTemplate.opsForValue().set(
+                "user_token:" + userId,
+                token,
+                24,
+                TimeUnit.HOURS
+        );
+    }
+}
+
+
+
+

+ 35 - 0
src/main/resources/mapper/UserMapper.xml

@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper
+        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.zhentao.user.mapper.UserMapper">
+
+    <resultMap id="BaseResultMap" type="com.zhentao.user.domain.User">
+            <id property="userId" column="user_id" jdbcType="INTEGER"/>
+            <result property="username" column="username" jdbcType="VARCHAR"/>
+            <result property="password" column="password" jdbcType="VARCHAR"/>
+            <result property="realName" column="real_name" jdbcType="VARCHAR"/>
+            <result property="gender" column="gender" jdbcType="TINYINT"/>
+            <result property="birthday" column="birthday" jdbcType="DATE"/>
+            <result property="mobile" column="mobile" jdbcType="CHAR"/>
+            <result property="role" column="role" jdbcType="TINYINT"/>
+            <result property="createTime" column="create_time" jdbcType="TIMESTAMP"/>
+            <result property="lastLoginTime" column="last_login_time" jdbcType="TIMESTAMP"/>
+            <result property="wxOpenid" column="wx_openid" jdbcType="VARCHAR"/>
+            <result property="wxUnionid" column="wx_unionid" jdbcType="VARCHAR"/>
+            <result property="wxNickname" column="wx_nickname" jdbcType="VARCHAR"/>
+            <result property="wxAvatarUrl" column="wx_avatar_url" jdbcType="VARCHAR"/>
+            <result property="wxSessionKey" column="wx_session_key" jdbcType="VARCHAR"/>
+            <result property="wxLastLoginTime" column="wx_last_login_time" jdbcType="TIMESTAMP"/>
+            <result property="loginType" column="login_type" jdbcType="TINYINT"/>
+    </resultMap>
+
+    <sql id="Base_Column_List">
+        user_id,username,password,
+        real_name,gender,birthday,
+        mobile,role,create_time,
+        last_login_time,wx_openid,wx_unionid,
+        wx_nickname,wx_avatar_url,wx_session_key,
+        wx_last_login_time,login_type
+    </sql>
+</mapper>