fengjiajia 4 days ago
commit
fea0f8e7ef

+ 33 - 0
.gitignore

@@ -0,0 +1,33 @@
+HELP.md
+target/
+!.mvn/wrapper/maven-wrapper.jar
+!**/src/main/**/target/
+!**/src/test/**/target/
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+build/
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+### VS Code ###
+.vscode/

+ 137 - 0
pom.xml

@@ -0,0 +1,137 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <groupId>com.zhentao</groupId>
+    <artifactId>TourismHD</artifactId>
+    <version>0.0.1-SNAPSHOT</version>
+    <name>TourismHD</name>
+    <description>TourismHD</description>
+    <properties>
+        <java.version>1.8</java.version>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+        <spring-boot.version>2.6.13</spring-boot.version>
+    </properties>
+    <dependencies>
+        <!-- Spring Boot Starters -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-data-redis</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+
+        <!-- MyBatis Plus -->
+        <dependency>
+            <groupId>com.baomidou</groupId>
+            <artifactId>mybatis-plus-boot-starter</artifactId>
+            <version>3.5.4</version>
+        </dependency>
+
+        <!-- MySQL -->
+        <dependency>
+            <groupId>mysql</groupId>
+            <artifactId>mysql-connector-java</artifactId>
+        </dependency>
+
+        <!-- Lombok -->
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+        </dependency>
+
+<!--        关于微信登录的配置-->
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpclient</artifactId>
+            <version>4.5.13</version>
+        </dependency>
+        <dependency>
+            <groupId>io.jsonwebtoken</groupId>
+            <artifactId>jjwt</artifactId>
+            <version>0.9.0</version>
+        </dependency>
+        <dependency>
+            <groupId>cn.hutool</groupId>
+            <artifactId>hutool-all</artifactId>
+            <version>5.8.11</version> <!-- 确保版本号是正确的 -->
+        </dependency>
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpcore</artifactId>
+            <version>4.4.14</version>
+        </dependency>
+        <!-- jwt支持 -->
+        <dependency>
+            <groupId>com.auth0</groupId>
+            <artifactId>java-jwt</artifactId>
+            <version>3.19.2</version>
+        </dependency>
+
+        <!-- json格式化 -->
+        <dependency>
+            <groupId>com.google.code.gson</groupId>
+            <artifactId>gson</artifactId>
+            <version>2.8.9</version>
+        </dependency>
+
+
+
+    </dependencies>
+    <dependencyManagement>
+        <dependencies>
+            <dependency>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-dependencies</artifactId>
+                <version>${spring-boot.version}</version>
+                <type>pom</type>
+                <scope>import</scope>
+            </dependency>
+        </dependencies>
+    </dependencyManagement>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <version>3.8.1</version>
+                <configuration>
+                    <source>1.8</source>
+                    <target>1.8</target>
+                    <encoding>UTF-8</encoding>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+                <version>${spring-boot.version}</version>
+                <configuration>
+                    <mainClass>com.zhentao.TourismHdApplication</mainClass>
+                    <skip>true</skip>
+                </configuration>
+                <executions>
+                    <execution>
+                        <id>repackage</id>
+                        <goals>
+                            <goal>repackage</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>

+ 15 - 0
src/main/java/com/zhentao/TourismHdApplication.java

@@ -0,0 +1,15 @@
+package com.zhentao;
+
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+@MapperScan("com.zhentao.mapper")
+public class TourismHdApplication {
+
+    public static void main(String[] args) {
+        SpringApplication.run(TourismHdApplication.class, args);
+    }
+
+}

+ 30 - 0
src/main/java/com/zhentao/controller/WeChatController.java

@@ -0,0 +1,30 @@
+package com.zhentao.controller;
+
+import com.zhentao.dto.user.WeChatMode;
+import com.zhentao.service.WeChatLogin;
+import com.zhentao.vo.Result;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+@RestController
+public class WeChatController {
+    @Autowired
+    private WeChatLogin weChatLogin;
+
+
+    /**
+     * 处理微信登录请求的接口方法
+     * 该方法通过接收微信服务器发送的授权码(Code)来实现用户的登录功能
+     *
+     * @param weChatMode 包含微信授权码等信息的实体对象
+     * @return 返回登录结果,通常包括用户信息或错误信息
+     */
+    @PostMapping("/WeChart/login")
+    public Result WeChartLogin(@RequestBody WeChatMode weChatMode) {
+        // 打印接收到的微信授权码,用于调试和验证
+        System.err.println(weChatMode.getCode());
+        // 调用服务层方法处理微信登录逻辑
+        return weChatLogin.WeChatLogin(weChatMode);
+    }
+
+}

+ 294 - 0
src/main/java/com/zhentao/domain/UserLogin.java

@@ -0,0 +1,294 @@
+package com.zhentao.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.math.BigDecimal;
+import java.util.Date;
+import lombok.Data;
+
+/**
+ * 用户
+ * @TableName user_login
+ */
+@TableName(value ="user_login")
+@Data
+public class UserLogin implements Serializable {
+    /**
+     * 用户ID
+     */
+    @TableId
+    private Long id;
+
+    /**
+     * 账号
+     */
+    private String userUsername;
+
+    /**
+     * 密码
+     */
+    private String userPassword;
+
+    /**
+     * 盐
+     */
+    private String salt;
+
+    /**
+     * 用户昵称
+     */
+    private String nickName;
+
+    /**
+     * 头像图片
+     */
+    private String avatar;
+
+    /**
+     * 用户名称
+     */
+    private String userName;
+
+    /**
+     * 性别1男2女3未知
+     */
+    private Integer gender;
+
+    /**
+     * 个性签名
+     */
+    private String userIntro;
+
+    /**
+     * 手机号
+     */
+    private String userMobile;
+
+    /**
+     * 身份证号
+     */
+    private String idenNo;
+
+    /**
+     * 用户等级
+     */
+    private Long gradeId;
+
+    /**
+     * 等级描述
+     */
+    private String gradeDesc;
+
+    /**
+     * 是否付费会员0否1是
+     */
+    private Integer isMember;
+
+    /**
+     * 过期时间
+     */
+    private Date loseDate;
+
+    /**
+     * 1临时会员2副卡3正式会员
+     */
+    private Integer memberType;
+
+    /**
+     * 生日
+     */
+    private Date birthDay;
+
+    /**
+     * 月
+     */
+    private Integer birthMonth;
+
+    /**
+     * 日
+     */
+    private Integer days;
+
+    /**
+     * 总订单数
+     */
+    private Integer totalOrder;
+
+    /**
+     * 总消费金额
+     */
+    private BigDecimal totalConsume;
+
+    /**
+     * 标签列表
+     */
+    private String labelList;
+
+    /**
+     * 状态1正常0锁定
+     */
+    private Integer status;
+
+    /**
+     * 备注
+     */
+    private String remark;
+
+    /**
+     * 创建时间
+     */
+    private Date createdTime;
+
+    /**
+     * 更新人
+     */
+    private String updatedBy;
+
+    /**
+     * 更新时间
+     */
+    private Date updatedTime;
+
+    /**
+     * 
+     */
+    private String openId;
+
+    /**
+     * 
+     */
+    private String sessionKey;
+
+    /**
+     * 
+     */
+    private String uniId;
+
+    @TableField(exist = false)
+    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;
+        }
+        UserLogin other = (UserLogin) that;
+        return (this.getId() == null ? other.getId() == null : this.getId().equals(other.getId()))
+            && (this.getUserUsername() == null ? other.getUserUsername() == null : this.getUserUsername().equals(other.getUserUsername()))
+            && (this.getUserPassword() == null ? other.getUserPassword() == null : this.getUserPassword().equals(other.getUserPassword()))
+            && (this.getSalt() == null ? other.getSalt() == null : this.getSalt().equals(other.getSalt()))
+            && (this.getNickName() == null ? other.getNickName() == null : this.getNickName().equals(other.getNickName()))
+            && (this.getAvatar() == null ? other.getAvatar() == null : this.getAvatar().equals(other.getAvatar()))
+            && (this.getUserName() == null ? other.getUserName() == null : this.getUserName().equals(other.getUserName()))
+            && (this.getGender() == null ? other.getGender() == null : this.getGender().equals(other.getGender()))
+            && (this.getUserIntro() == null ? other.getUserIntro() == null : this.getUserIntro().equals(other.getUserIntro()))
+            && (this.getUserMobile() == null ? other.getUserMobile() == null : this.getUserMobile().equals(other.getUserMobile()))
+            && (this.getIdenNo() == null ? other.getIdenNo() == null : this.getIdenNo().equals(other.getIdenNo()))
+            && (this.getGradeId() == null ? other.getGradeId() == null : this.getGradeId().equals(other.getGradeId()))
+            && (this.getGradeDesc() == null ? other.getGradeDesc() == null : this.getGradeDesc().equals(other.getGradeDesc()))
+            && (this.getIsMember() == null ? other.getIsMember() == null : this.getIsMember().equals(other.getIsMember()))
+            && (this.getLoseDate() == null ? other.getLoseDate() == null : this.getLoseDate().equals(other.getLoseDate()))
+            && (this.getMemberType() == null ? other.getMemberType() == null : this.getMemberType().equals(other.getMemberType()))
+            && (this.getBirthDay() == null ? other.getBirthDay() == null : this.getBirthDay().equals(other.getBirthDay()))
+            && (this.getBirthMonth() == null ? other.getBirthMonth() == null : this.getBirthMonth().equals(other.getBirthMonth()))
+            && (this.getDays() == null ? other.getDays() == null : this.getDays().equals(other.getDays()))
+            && (this.getTotalOrder() == null ? other.getTotalOrder() == null : this.getTotalOrder().equals(other.getTotalOrder()))
+            && (this.getTotalConsume() == null ? other.getTotalConsume() == null : this.getTotalConsume().equals(other.getTotalConsume()))
+            && (this.getLabelList() == null ? other.getLabelList() == null : this.getLabelList().equals(other.getLabelList()))
+            && (this.getStatus() == null ? other.getStatus() == null : this.getStatus().equals(other.getStatus()))
+            && (this.getRemark() == null ? other.getRemark() == null : this.getRemark().equals(other.getRemark()))
+            && (this.getCreatedTime() == null ? other.getCreatedTime() == null : this.getCreatedTime().equals(other.getCreatedTime()))
+            && (this.getUpdatedBy() == null ? other.getUpdatedBy() == null : this.getUpdatedBy().equals(other.getUpdatedBy()))
+            && (this.getUpdatedTime() == null ? other.getUpdatedTime() == null : this.getUpdatedTime().equals(other.getUpdatedTime()))
+            && (this.getOpenId() == null ? other.getOpenId() == null : this.getOpenId().equals(other.getOpenId()))
+            && (this.getSessionKey() == null ? other.getSessionKey() == null : this.getSessionKey().equals(other.getSessionKey()))
+            && (this.getUniId() == null ? other.getUniId() == null : this.getUniId().equals(other.getUniId()));
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((getId() == null) ? 0 : getId().hashCode());
+        result = prime * result + ((getUserUsername() == null) ? 0 : getUserUsername().hashCode());
+        result = prime * result + ((getUserPassword() == null) ? 0 : getUserPassword().hashCode());
+        result = prime * result + ((getSalt() == null) ? 0 : getSalt().hashCode());
+        result = prime * result + ((getNickName() == null) ? 0 : getNickName().hashCode());
+        result = prime * result + ((getAvatar() == null) ? 0 : getAvatar().hashCode());
+        result = prime * result + ((getUserName() == null) ? 0 : getUserName().hashCode());
+        result = prime * result + ((getGender() == null) ? 0 : getGender().hashCode());
+        result = prime * result + ((getUserIntro() == null) ? 0 : getUserIntro().hashCode());
+        result = prime * result + ((getUserMobile() == null) ? 0 : getUserMobile().hashCode());
+        result = prime * result + ((getIdenNo() == null) ? 0 : getIdenNo().hashCode());
+        result = prime * result + ((getGradeId() == null) ? 0 : getGradeId().hashCode());
+        result = prime * result + ((getGradeDesc() == null) ? 0 : getGradeDesc().hashCode());
+        result = prime * result + ((getIsMember() == null) ? 0 : getIsMember().hashCode());
+        result = prime * result + ((getLoseDate() == null) ? 0 : getLoseDate().hashCode());
+        result = prime * result + ((getMemberType() == null) ? 0 : getMemberType().hashCode());
+        result = prime * result + ((getBirthDay() == null) ? 0 : getBirthDay().hashCode());
+        result = prime * result + ((getBirthMonth() == null) ? 0 : getBirthMonth().hashCode());
+        result = prime * result + ((getDays() == null) ? 0 : getDays().hashCode());
+        result = prime * result + ((getTotalOrder() == null) ? 0 : getTotalOrder().hashCode());
+        result = prime * result + ((getTotalConsume() == null) ? 0 : getTotalConsume().hashCode());
+        result = prime * result + ((getLabelList() == null) ? 0 : getLabelList().hashCode());
+        result = prime * result + ((getStatus() == null) ? 0 : getStatus().hashCode());
+        result = prime * result + ((getRemark() == null) ? 0 : getRemark().hashCode());
+        result = prime * result + ((getCreatedTime() == null) ? 0 : getCreatedTime().hashCode());
+        result = prime * result + ((getUpdatedBy() == null) ? 0 : getUpdatedBy().hashCode());
+        result = prime * result + ((getUpdatedTime() == null) ? 0 : getUpdatedTime().hashCode());
+        result = prime * result + ((getOpenId() == null) ? 0 : getOpenId().hashCode());
+        result = prime * result + ((getSessionKey() == null) ? 0 : getSessionKey().hashCode());
+        result = prime * result + ((getUniId() == null) ? 0 : getUniId().hashCode());
+        return result;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append(getClass().getSimpleName());
+        sb.append(" [");
+        sb.append("Hash = ").append(hashCode());
+        sb.append(", id=").append(id);
+        sb.append(", userUsername=").append(userUsername);
+        sb.append(", userPassword=").append(userPassword);
+        sb.append(", salt=").append(salt);
+        sb.append(", nickName=").append(nickName);
+        sb.append(", avatar=").append(avatar);
+        sb.append(", userName=").append(userName);
+        sb.append(", gender=").append(gender);
+        sb.append(", userIntro=").append(userIntro);
+        sb.append(", userMobile=").append(userMobile);
+        sb.append(", idenNo=").append(idenNo);
+        sb.append(", gradeId=").append(gradeId);
+        sb.append(", gradeDesc=").append(gradeDesc);
+        sb.append(", isMember=").append(isMember);
+        sb.append(", loseDate=").append(loseDate);
+        sb.append(", memberType=").append(memberType);
+        sb.append(", birthDay=").append(birthDay);
+        sb.append(", birthMonth=").append(birthMonth);
+        sb.append(", days=").append(days);
+        sb.append(", totalOrder=").append(totalOrder);
+        sb.append(", totalConsume=").append(totalConsume);
+        sb.append(", labelList=").append(labelList);
+        sb.append(", status=").append(status);
+        sb.append(", remark=").append(remark);
+        sb.append(", createdTime=").append(createdTime);
+        sb.append(", updatedBy=").append(updatedBy);
+        sb.append(", updatedTime=").append(updatedTime);
+        sb.append(", openId=").append(openId);
+        sb.append(", sessionKey=").append(sessionKey);
+        sb.append(", uniId=").append(uniId);
+        sb.append(", serialVersionUID=").append(serialVersionUID);
+        sb.append("]");
+        return sb.toString();
+    }
+}

+ 13 - 0
src/main/java/com/zhentao/dto/user/WeChatLoginDto.java

@@ -0,0 +1,13 @@
+package com.zhentao.dto.user;
+
+import lombok.Data;
+
+@Data
+public class WeChatLoginDto {
+    //头像图片
+    private String avatarUrl;
+    //性别1男2女3未知
+    private Integer gender;
+//    用户昵称
+    private String nickName;
+}

+ 14 - 0
src/main/java/com/zhentao/dto/user/WeChatMode.java

@@ -0,0 +1,14 @@
+package com.zhentao.dto.user;
+
+import lombok.Data;
+
+//用来接受前端传来的参数
+@Data
+public class WeChatMode {
+//    临时登录凭证
+    private String code;
+    private WeChatLoginDto weChatLoginDto;
+
+    //微信服务器上的唯一id
+    private String openId;
+}

+ 16 - 0
src/main/java/com/zhentao/dto/user/WeChatSessionModel.java

@@ -0,0 +1,16 @@
+package com.zhentao.dto.user;
+
+import lombok.Data;
+//用来就接受调用微信验证code后返回的数据
+@Data
+public class WeChatSessionModel {
+
+    //微信服务器上辨识用户的唯一id
+    private String openid;
+    //身份凭证
+    private String session_key;
+    //错误代码
+    private String errcode;
+    //错误信息
+    private String errmsg;
+}

+ 28 - 0
src/main/java/com/zhentao/enums/ApiServerException.java

@@ -0,0 +1,28 @@
+package com.zhentao.enums;
+
+public enum ApiServerException implements BaseExceptionEnum{
+    SUCCESS(1, "成功"),
+    NULL_USERNAME(1,"用户名错误"),
+    SUCCESS_login(1,"登录成功"),
+    TOKEN_ERR(101,"token错误,请重新登录"),
+    INTERRUPT(1,"操作中断"),
+    REGISTERED(1,"已注册"),
+    NOTE_ERROR(1,"验证码错误"),
+    NULL_PASSWORD(1,"密码错误");
+
+    ApiServerException(Integer code,String msg){
+        this.code=code;
+        this.msg=msg;
+    }
+    @Override
+    public Integer getCode() {
+        return code;
+    }
+
+    @Override
+    public String getMsg() {
+        return msg;
+    }
+    private Integer code;
+    private String msg;
+}

+ 6 - 0
src/main/java/com/zhentao/enums/BaseExceptionEnum.java

@@ -0,0 +1,6 @@
+package com.zhentao.enums;
+
+public interface BaseExceptionEnum {
+    Integer getCode();
+    String getMsg();
+}

+ 15 - 0
src/main/java/com/zhentao/exception/AsynException.java

@@ -0,0 +1,15 @@
+package com.zhentao.exception;
+
+import com.zhentao.enums.BaseExceptionEnum;
+import lombok.Data;
+
+@Data
+public class AsynException extends RuntimeException{
+    private Integer code;
+    private String msg;
+    public AsynException(BaseExceptionEnum baseExceptionEnum){
+        super(baseExceptionEnum.getMsg());
+        this.code = baseExceptionEnum.getCode();
+        this.msg = baseExceptionEnum.getMsg();
+    }
+}

+ 56 - 0
src/main/java/com/zhentao/exception/GlobalExceptionHandler.java

@@ -0,0 +1,56 @@
+package com.zhentao.exception;
+
+
+import com.zhentao.vo.Result;
+import lombok.extern.slf4j.Slf4j;
+
+import org.springframework.web.bind.MethodArgumentNotValidException;
+import org.springframework.web.bind.annotation.ControllerAdvice;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.bind.annotation.RestControllerAdvice;
+import org.springframework.web.multipart.MultipartException;
+
+import javax.servlet.http.HttpServletRequest;
+
+@Slf4j
+@RestControllerAdvice
+@ControllerAdvice
+public class GlobalExceptionHandler {
+    // 捕获所有异常的处理器,指定捕获的异常类型为Exception
+    @ExceptionHandler(value = Exception.class)
+// 将处理结果以JSON格式返回
+    @ResponseBody
+    public Result defaultErrorHandler(HttpServletRequest req, Exception e) throws Exception {
+        // 记录异常信息到日志,这里只记录异常信息,不记录堆栈信息
+        log.error(e.getMessage());
+
+        // 判断异常类型并进行处理
+        if (e instanceof org.springframework.web.servlet.NoHandlerFoundException) {
+            // 如果是404异常,即没有找到处理器
+            return Result.error(404,"不存在页面请求");
+        }
+
+        if (e instanceof AsynException) {
+            // 如果是自定义的AsynException
+            AsynException customException = (AsynException) e;
+
+            // 返回自定义异常的错误码和错误信息
+            return Result.error(customException.getCode(), customException.getMessage());
+        } else if (e instanceof MultipartException) {
+            // 如果是文件上传异常
+            log.error("系统异常{}", e); // 记录异常堆栈信息
+            return Result.error(1000, "上传文件异常");
+        } else if (e instanceof MethodArgumentNotValidException) {
+            // 如果是校验异常,例如使用@Valid注解校验参数失败
+            MethodArgumentNotValidException methodArgumentNotValidException = (MethodArgumentNotValidException) e;
+
+            // 获取校验失败的第一个字段的错误信息
+            return Result.error(1002, methodArgumentNotValidException.getBindingResult().getFieldError().getDefaultMessage());
+        } else {
+            // 其他未处理的异常
+            log.error("系统异常{}", e); // 记录异常堆栈信息
+            return Result.error(1001, "系统参数异常");
+        }
+    }
+}

+ 26 - 0
src/main/java/com/zhentao/filter/TokenFilter.java

@@ -0,0 +1,26 @@
+package com.zhentao.filter;
+
+
+import javax.servlet.*;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+/**
+ * TokenFilter类实现了Filter接口,用于在Servlet请求处理前后进行拦截和处理
+ * 主要功能是进行跨域资源共享(CORS)配置,以允许来自不同域的请求
+ */
+public class TokenFilter implements Filter {
+
+
+    @Override
+    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
+        // 将ServletResponse转换为HttpServletResponse,以便后续操作
+        HttpServletResponse response = (HttpServletResponse) servletResponse;
+        // 将ServletRequest转换为HttpServletRequest,以便后续操作
+        HttpServletRequest request = (HttpServletRequest) servletRequest;
+        // 将请求和响应对象传递给链中的下一个过滤器或目标资源
+        filterChain.doFilter(request,response);
+    }
+}
+

+ 18 - 0
src/main/java/com/zhentao/mapper/UserLoginMapper.java

@@ -0,0 +1,18 @@
+package com.zhentao.mapper;
+
+import com.zhentao.domain.UserLogin;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+* @author lenovo
+* @description 针对表【user_login(用户)】的数据库操作Mapper
+* @createDate 2025-05-16 18:48:43
+* @Entity com.zhentao.domain.UserLogin
+*/
+public interface UserLoginMapper extends BaseMapper<UserLogin> {
+
+}
+
+
+
+

+ 13 - 0
src/main/java/com/zhentao/service/UserLoginService.java

@@ -0,0 +1,13 @@
+package com.zhentao.service;
+
+import com.zhentao.domain.UserLogin;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+* @author lenovo
+* @description 针对表【user_login(用户)】的数据库操作Service
+* @createDate 2025-05-16 18:48:43
+*/
+public interface UserLoginService extends IService<UserLogin> {
+
+}

+ 9 - 0
src/main/java/com/zhentao/service/WeChatLogin.java

@@ -0,0 +1,9 @@
+package com.zhentao.service;
+
+import com.zhentao.dto.user.WeChatMode;
+import com.zhentao.vo.Result;
+
+public interface WeChatLogin {
+    //微信登录
+    Result WeChatLogin(WeChatMode weChatMode);
+}

+ 22 - 0
src/main/java/com/zhentao/service/impl/UserLoginServiceImpl.java

@@ -0,0 +1,22 @@
+package com.zhentao.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.zhentao.domain.UserLogin;
+import com.zhentao.service.UserLoginService;
+import com.zhentao.mapper.UserLoginMapper;
+import org.springframework.stereotype.Service;
+
+/**
+* @author lenovo
+* @description 针对表【user_login(用户)】的数据库操作Service实现
+* @createDate 2025-05-16 18:48:43
+*/
+@Service
+public class UserLoginServiceImpl extends ServiceImpl<UserLoginMapper, UserLogin>
+    implements UserLoginService{
+
+}
+
+
+
+

+ 88 - 0
src/main/java/com/zhentao/service/impl/WeChatLoginimpl.java

@@ -0,0 +1,88 @@
+package com.zhentao.service.impl;
+
+import cn.hutool.core.util.IdUtil;
+import com.zhentao.domain.UserLogin;
+import com.zhentao.dto.user.WeChatMode;
+import com.zhentao.dto.user.WeChatSessionModel;
+import com.zhentao.service.UserLoginService;
+import com.zhentao.service.WeChatLogin;
+import com.zhentao.tool.TokenUtils;
+import com.zhentao.tool.WechatLoginUtil;
+import com.zhentao.vo.Result;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.stereotype.Service;
+
+import java.io.IOException;
+import java.util.HashMap;
+
+@Service
+public class WeChatLoginimpl implements WeChatLogin {
+    @Autowired
+    private StringRedisTemplate stringRedisTemplate;
+
+    @Autowired
+    private UserLoginService userLoginService;
+    //微信登录
+    @Override
+    public Result WeChatLogin(WeChatMode weChatMode) {
+        try {
+            // 获取微信会话信息
+            WeChatSessionModel authInfo = WechatLoginUtil.getAuthInfo(weChatMode.getCode());
+            if(authInfo.getErrcode() == null) {
+                // 生成用户令牌
+                String token = generateToken(authInfo.getOpenid());
+
+                // 将用户信息存储到Redis
+                stringRedisTemplate.opsForValue().set(authInfo.getOpenid(),authInfo.toString());
+
+                // 创建包含token和用户信息的Map
+                HashMap<String,Object> map=new HashMap<>();
+                map.put("token",token);
+                map.put("openid",authInfo);
+
+                // 创建用户登录对象并设置属性
+                UserLogin userLogin=new UserLogin();
+                long l = IdUtil.getSnowflake(1, 1).nextId();
+                userLogin.setId(l);
+                userLogin.setOpenId(authInfo.getOpenid());
+                userLogin.setSessionKey(authInfo.getSession_key());
+                userLogin.setNickName(weChatMode.getWeChatLoginDto().getNickName());
+                userLogin.setAvatar(weChatMode.getWeChatLoginDto().getAvatarUrl());
+                userLogin.setGender(weChatMode.getWeChatLoginDto().getGender());
+
+                // 保存用户登录信息到数据库
+                userLoginService.save(userLogin);
+
+                // 返回登录成功结果
+                return Result.OK(map,"登录成功");
+            } else {
+                // 返回登录失败结果
+                return Result.ERR("登录失败",authInfo.getErrmsg());
+            }
+        } catch (IOException e) {
+            // 打印异常信息并返回登录失败结果
+            e.printStackTrace();
+            return Result.ERR("登录失败",null);
+        }
+
+    }
+
+
+
+
+
+    /**
+     * 生成用户认证令牌
+     *
+     * 本方法通过调用TokenUtils工具类的createJwtToken方法,为给定的用户openid生成一个JWT令牌
+     * 这个令牌可以用于后续的用户身份验证和授权操作
+     *
+     * @param openid 用户的唯一标识符,用于标识请求的用户
+     * @return 生成的JWT令牌字符串
+     */
+    private String generateToken(String openid){
+        String token = TokenUtils.createJwtToken(openid);
+        return token;
+    }
+}

+ 93 - 0
src/main/java/com/zhentao/tool/TokenUtils.java

@@ -0,0 +1,93 @@
+package com.zhentao.tool;
+
+import com.zhentao.enums.ApiServerException;
+import com.zhentao.exception.AsynException;
+import io.jsonwebtoken.Claims;
+import io.jsonwebtoken.JwtBuilder;
+import io.jsonwebtoken.Jwts;
+import io.jsonwebtoken.SignatureAlgorithm;
+
+import javax.crypto.spec.SecretKeySpec;
+import javax.xml.bind.DatatypeConverter;
+import java.security.Key;
+import java.util.Date;
+
+public class TokenUtils {
+
+    public static final String SECRET = "cjyfutu1688";
+
+    public static String createJwtToken(String id) {
+        String issuer = "www.futureading.com";
+        String subject = "65532781@qq.com";
+        long ttlMillis = 3600000; // 例如,设置token有效期为1小时
+        return createJwtToken(id, issuer, subject, ttlMillis);
+    }
+
+    public static String createJwtToken(String id, String issuer, String subject, long ttlMillis) {
+        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
+        long nowMillis = System.currentTimeMillis();
+        Date now = new Date(nowMillis);
+
+        byte[] apiKeySecretBytes = DatatypeConverter.parseBase64Binary(SECRET);
+        Key signingKey = new SecretKeySpec(apiKeySecretBytes, signatureAlgorithm.getJcaName());
+
+        JwtBuilder builder = Jwts.builder().setId(id)
+                .setIssuedAt(now)
+                .setSubject(subject)
+                .setIssuer(issuer)
+                .signWith(signatureAlgorithm, signingKey);
+
+        if (ttlMillis >= 0) {
+            long expMillis = nowMillis + ttlMillis;
+            Date exp = new Date(expMillis);
+            builder.setExpiration(exp);
+        }
+
+        return builder.compact();
+    }
+
+    public static Claims parseJWT(String jwt) {
+        Claims claims = Jwts.parser()
+                .setSigningKey(DatatypeConverter.parseBase64Binary(SECRET))
+                .parseClaimsJws(jwt).getBody();
+        return claims;
+    }
+
+    public static Long getUserId(String token) {
+        Claims claims = null;
+        try {
+            claims = parseJWT(token);
+        } catch (Exception e) {
+            throw new AsynException(ApiServerException.TOKEN_ERR);
+        }
+
+        if (null == claims) {
+            throw new AsynException(ApiServerException.TOKEN_ERR);
+        }
+        String id = claims.getId();
+        Long userId = Long.valueOf(id);
+
+        return userId;
+    }
+
+    /**
+     * 检查token是否过期
+     * @param jwt 要检查的token
+     * @return 如果token过期返回true,否则返回false
+     */
+    public static boolean isTokenExpired(String jwt) {
+        Claims claims = parseJWT(jwt);
+        Date exp = claims.getExpiration();
+        if (exp == null) {
+            // 如果没有设置过期时间,可以认为token不过期
+            return false;
+        }
+        return exp.before(new Date()); // 比较当前时间和过期时间
+    }
+
+    public static void main(String[] args) {
+        String token = TokenUtils.createJwtToken("admin");
+        System.out.println("Token: " + token);
+        System.out.println("Is expired: " + TokenUtils.isTokenExpired(token));
+    }
+}

+ 83 - 0
src/main/java/com/zhentao/tool/WechatLoginUtil.java

@@ -0,0 +1,83 @@
+package com.zhentao.tool;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import com.zhentao.dto.user.WeChatMode;
+import com.zhentao.dto.user.WeChatSessionModel;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.util.EntityUtils;
+
+import javax.crypto.Cipher;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.util.Base64;
+
+public class WechatLoginUtil {
+
+    private static final String APP_ID = "wxf1e39756b564fd41"; // 替换为你的AppID
+    private static final String APP_SECRET = "628082cc4dc055f61be83dffa6761e55"; // 替换为你的AppSecret
+    private static final String WECHAT_LOGIN_URL = "https://api.weixin.qq.com/sns/jscode2session";
+
+    public static WeChatSessionModel getAuthInfo(String code) throws IOException {
+        // 构造微信登录接口的URL,包含必要的参数
+        String url = WECHAT_LOGIN_URL + "?appid=" + APP_ID + "&secret=" + APP_SECRET + "&js_code=" + code + "&grant_type=authorization_code";
+
+        // 创建一个默认的HTTP客户端,用于发送HTTP请求
+        CloseableHttpClient httpClient = HttpClients.createDefault();
+
+        // 创建一个HTTP GET请求对象,指定请求的URL
+        HttpGet httpGet = new HttpGet(url);
+
+        // 执行HTTP GET请求,获取微信服务器的响应
+        CloseableHttpResponse response = httpClient.execute(httpGet);
+
+        // 从响应中获取响应体内容,并将其转换为字符串
+        String jsonResponse = EntityUtils.toString(response.getEntity());
+        // 创建一个Jackson的ObjectMapper对象,用于处理JSON数据
+        ObjectMapper objectMapper = new ObjectMapper();
+
+        // 将微信返回的JSON字符串解析为WechatAuthResponse对象
+        // WechatAuthResponse是一个自定义的Java类,用于封装微信返回的用户认证信息
+        return objectMapper.readValue(jsonResponse, WeChatSessionModel.class);
+    }
+
+    private static final String ALGORITHM = "AES/CBC/PKCS5Padding";
+
+    public static String decryptPhoneNumber(String encryptedData, String sessionKey, String iv) throws Exception {
+        // Base64解码
+        byte[] encryptedDataBytes = Base64.getDecoder().decode(encryptedData);
+        byte[] sessionKeyBytes = Base64.getDecoder().decode(sessionKey);
+        byte[] ivBytes = Base64.getDecoder().decode(iv);
+
+        // 设置AES密钥和初始化向量
+        SecretKeySpec secretKeySpec = new SecretKeySpec(sessionKeyBytes, "AES");
+        IvParameterSpec ivParameterSpec = new IvParameterSpec(ivBytes);
+
+        // 创建Cipher实例并初始化
+        Cipher cipher = Cipher.getInstance(ALGORITHM);
+        cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec);
+
+        // 解密
+        byte[] decryptedBytes = cipher.doFinal(encryptedDataBytes);
+        // 将解密后的字节转换为字符串
+        return new String(decryptedBytes, StandardCharsets.UTF_8);
+    }
+
+
+
+
+
+
+
+
+
+
+
+
+
+}

+ 38 - 0
src/main/java/com/zhentao/vo/Result.java

@@ -0,0 +1,38 @@
+package com.zhentao.vo;
+
+import lombok.Data;
+
+@Data
+public class Result {
+    private Integer code;
+    private Object data;
+    private String msg;
+
+
+    public static Result OK(Object data,String msg) {
+        Result result = new Result();
+        result.setCode(200);
+        result.setData(data);
+        result.setMsg(msg);
+        return result;
+    }
+
+
+    public static Result ERR(Object data,String msg) {
+        Result result = new Result();
+        result.setCode(400);
+        result.setData(data);
+        result.setMsg(msg);
+        return result;
+    }
+
+    public static Result error(Integer code,Object data){
+        Result result=new Result();
+        result.setCode(code);
+        result.setData(data);
+        return result;
+    }
+
+
+
+}

+ 20 - 0
src/main/resources/application.yml

@@ -0,0 +1,20 @@
+server:
+  port: 3333
+spring:
+  datasource:
+    driver-class-name: com.mysql.cj.jdbc.Driver
+    url: jdbc:mysql://47.110.46.22:3306/lvYou?useSSL=false&serverTimezone=UTC
+    username: root
+    password: Fengjaijia0610
+  redis:
+    host: 47.110.46.22
+    port: 6379
+    database: 0
+jwt:
+  header: Authorization
+  tokenPrefix: Bearer
+  secret: "maohe101"
+  expireTime: 3600000 #token有效时间 300000 ==>60分钟
+#微信小程序的配置
+  APPID: wx97b71d70f5b2d51f
+  APPSECRET: b78d9bf60e17518475bc8e1d44fd9ad6

+ 52 - 0
src/main/resources/mapper/UserLoginMapper.xml

@@ -0,0 +1,52 @@
+<?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.mapper.UserLoginMapper">
+
+    <resultMap id="BaseResultMap" type="com.zhentao.domain.UserLogin">
+            <id property="id" column="id" jdbcType="BIGINT"/>
+            <result property="userUsername" column="user_username" jdbcType="VARCHAR"/>
+            <result property="userPassword" column="user_password" jdbcType="VARCHAR"/>
+            <result property="salt" column="salt" jdbcType="VARCHAR"/>
+            <result property="nickName" column="nick_name" jdbcType="VARCHAR"/>
+            <result property="avatar" column="avatar" jdbcType="VARCHAR"/>
+            <result property="userName" column="user_name" jdbcType="VARCHAR"/>
+            <result property="gender" column="gender" jdbcType="INTEGER"/>
+            <result property="userIntro" column="user_intro" jdbcType="VARCHAR"/>
+            <result property="userMobile" column="user_mobile" jdbcType="VARCHAR"/>
+            <result property="idenNo" column="iden_no" jdbcType="VARCHAR"/>
+            <result property="gradeId" column="grade_id" jdbcType="BIGINT"/>
+            <result property="gradeDesc" column="grade_desc" jdbcType="VARCHAR"/>
+            <result property="isMember" column="is_member" jdbcType="INTEGER"/>
+            <result property="loseDate" column="lose_date" jdbcType="TIMESTAMP"/>
+            <result property="memberType" column="member_type" jdbcType="INTEGER"/>
+            <result property="birthDay" column="birth_day" jdbcType="DATE"/>
+            <result property="birthMonth" column="birth_month" jdbcType="INTEGER"/>
+            <result property="days" column="days" jdbcType="INTEGER"/>
+            <result property="totalOrder" column="total_order" jdbcType="INTEGER"/>
+            <result property="totalConsume" column="total_consume" jdbcType="DECIMAL"/>
+            <result property="labelList" column="label_list" jdbcType="VARCHAR"/>
+            <result property="status" column="status" jdbcType="INTEGER"/>
+            <result property="remark" column="remark" jdbcType="VARCHAR"/>
+            <result property="createdTime" column="created_time" jdbcType="TIMESTAMP"/>
+            <result property="updatedBy" column="updated_by" jdbcType="VARCHAR"/>
+            <result property="updatedTime" column="updated_time" jdbcType="TIMESTAMP"/>
+            <result property="openId" column="open_id" jdbcType="VARCHAR"/>
+            <result property="sessionKey" column="session_key" jdbcType="VARCHAR"/>
+            <result property="uniId" column="uni_id" jdbcType="VARCHAR"/>
+    </resultMap>
+
+    <sql id="Base_Column_List">
+        id,user_username,user_password,
+        salt,nick_name,avatar,
+        user_name,gender,user_intro,
+        user_mobile,iden_no,grade_id,
+        grade_desc,is_member,lose_date,
+        member_type,birth_day,birth_month,
+        days,total_order,total_consume,
+        label_list,status,remark,
+        created_time,updated_by,updated_time,
+        open_id,session_key,uni_id
+    </sql>
+</mapper>

+ 13 - 0
src/test/java/com/zhentao/tourismhd/TourismHdApplicationTests.java

@@ -0,0 +1,13 @@
+package com.zhentao.tourismhd;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+
+@SpringBootTest
+class TourismHdApplicationTests {
+
+    @Test
+    void contextLoads() {
+    }
+
+}