Sfoglia il codice sorgente

Merge remote-tracking branch 'origin/dev0.0.1' into dev0.0.1

# Conflicts:
#	game-module/game-sdk/pom.xml
#	game-module/game-sdk/src/main/java/com/zanxiang/sdk/config/MybatisPlusConfig.java
#	game-module/game-sdk/src/main/java/com/zanxiang/sdk/domain/params/CommonParam.java
#	game-module/game-sdk/src/main/java/com/zanxiang/sdk/service/Impl/UserTokenServiceImpl.java
xufeng 2 anni fa
parent
commit
a6159ca8db
31 ha cambiato i file con 1117 aggiunte e 408 eliminazioni
  1. 62 52
      game-module/game-common/src/main/java/com/zanxiang/common/domain/ResultVo.java
  2. 5 0
      game-module/game-common/src/main/java/com/zanxiang/common/enums/ExpireTimeEnum.java
  3. 12 2
      game-module/game-common/src/main/java/com/zanxiang/common/enums/HttpStatusEnum.java
  4. 10 0
      game-module/game-common/src/main/java/com/zanxiang/common/utils/StringUtils.java
  5. 12 0
      game-module/game-sdk/pom.xml
  6. 96 96
      game-module/game-sdk/src/main/java/com/zanxiang/sdk/config/MybatisPlusConfig.java
  7. 19 0
      game-module/game-sdk/src/main/java/com/zanxiang/sdk/config/RestTemplateConfig.java
  8. 5 0
      game-module/game-sdk/src/main/java/com/zanxiang/sdk/constant/RedisKeyConstant.java
  9. 99 0
      game-module/game-sdk/src/main/java/com/zanxiang/sdk/domain/dto/UserDTO.java
  10. 3 0
      game-module/game-sdk/src/main/java/com/zanxiang/sdk/domain/dto/UserTokenDTO.java
  11. 7 2
      game-module/game-sdk/src/main/java/com/zanxiang/sdk/domain/entity/User.java
  12. 17 0
      game-module/game-sdk/src/main/java/com/zanxiang/sdk/domain/entity/UserLoginLog.java
  13. 39 0
      game-module/game-sdk/src/main/java/com/zanxiang/sdk/domain/enums/AccountStatusEnum.java
  14. 30 0
      game-module/game-sdk/src/main/java/com/zanxiang/sdk/domain/enums/CmfSaltEnum.java
  15. 17 0
      game-module/game-sdk/src/main/java/com/zanxiang/sdk/domain/enums/SmsTypeEnum.java
  16. 2 13
      game-module/game-sdk/src/main/java/com/zanxiang/sdk/domain/params/LoginMobileParam.java
  17. 4 0
      game-module/game-sdk/src/main/java/com/zanxiang/sdk/domain/params/LoginPasswordParam.java
  18. 37 0
      game-module/game-sdk/src/main/java/com/zanxiang/sdk/domain/params/SmsCheckParam.java
  19. 30 0
      game-module/game-sdk/src/main/java/com/zanxiang/sdk/domain/params/SmsSendParam.java
  20. 0 80
      game-module/game-sdk/src/main/java/com/zanxiang/sdk/domain/vo/ResultVO.java
  21. 9 0
      game-module/game-sdk/src/main/java/com/zanxiang/sdk/domain/vo/UserLoginVO.java
  22. 30 0
      game-module/game-sdk/src/main/java/com/zanxiang/sdk/service/ISmsService.java
  23. 19 0
      game-module/game-sdk/src/main/java/com/zanxiang/sdk/service/IUserLoginLogService.java
  24. 33 0
      game-module/game-sdk/src/main/java/com/zanxiang/sdk/service/IUserService.java
  25. 9 0
      game-module/game-sdk/src/main/java/com/zanxiang/sdk/service/IUserTokenService.java
  26. 147 0
      game-module/game-sdk/src/main/java/com/zanxiang/sdk/service/Impl/SmsServiceImpl.java
  27. 31 0
      game-module/game-sdk/src/main/java/com/zanxiang/sdk/service/Impl/UserLoginLogServiceImpl.java
  28. 126 4
      game-module/game-sdk/src/main/java/com/zanxiang/sdk/service/Impl/UserServiceImpl.java
  29. 195 158
      game-module/game-sdk/src/main/java/com/zanxiang/sdk/service/Impl/UserTokenServiceImpl.java
  30. 1 1
      game-module/game-sdk/src/main/java/com/zanxiang/sdk/utils/RedisUtils.java
  31. 11 0
      game-module/game-sdk/src/main/resources/bootstrap.yml

+ 62 - 52
game-module/game-common/src/main/java/com/zanxiang/common/domain/ResultVo.java

@@ -1,85 +1,95 @@
 package com.zanxiang.common.domain;
 
-import com.zanxiang.common.enums.ResEnum;
+import com.zanxiang.common.enums.HttpStatusEnum;
+import lombok.AllArgsConstructor;
 import lombok.Data;
+import lombok.NoArgsConstructor;
 
 import java.io.Serializable;
+import java.util.Objects;
 
 /**
- * 响应信息主体
- *
- * @author ruoyi
+ * @author : lingfeng
+ * @time : 2022-06-07
+ * @description : http响应消息
  */
 @Data
+@NoArgsConstructor
+@AllArgsConstructor
 public class ResultVo<T> implements Serializable {
-    private static final long serialVersionUID = 1L;
 
-    // 成功
-    public static final int CODE_SUCCESS = 200;
-    // 页面重定向
-    public static final int CODE_REDIRECT = 301;
-    // 重新去登录
-    public static final int CODE_TO_LOGIN = 310;
-    // 服务异常
-    public static final int CODE_ERROR = 500;
+    /**
+     * 序列化
+     */
+    private static final long serialVersionUID = 1L;
 
+    /**
+     * 错误码
+     */
     private int code;
 
+    /**
+     * 错误信息
+     */
     private String msg;
 
+    /**
+     * 返回内容
+     */
     private T data;
 
-    private ResultVo() {
-        this(CODE_SUCCESS);
+    /**
+     * 错误消息返回构造
+     *
+     * @param httpStatusEnum : http响应消息枚举
+     */
+    public ResultVo(HttpStatusEnum httpStatusEnum) {
+        this.code = httpStatusEnum.getCode();
+        this.msg = httpStatusEnum.getMsg();
     }
 
-    public ResultVo(int code) {
-        this(code, null);
+    /**
+     * 默认返回成功构造
+     *
+     * @param data : 返回的内容
+     */
+    public ResultVo(T data) {
+        this.code = HttpStatusEnum.SUCCESS.getCode();
+        this.msg = HttpStatusEnum.SUCCESS.getMsg();
+        this.data = data;
     }
 
-    public ResultVo(int code, String msg) {
-        this(code, msg, null);
+    /**
+     * 消息返回构造
+     *
+     * @param httpStatusEnum : http响应消息枚举
+     * @param data           : 返回的内容
+     */
+    public ResultVo(HttpStatusEnum httpStatusEnum, T data) {
+        this.code = httpStatusEnum.getCode();
+        this.msg = httpStatusEnum.getMsg();
+        this.data = data;
     }
 
-    public ResultVo(int code, String msg, T data) {
+    /**
+     * 自定义消息异常
+     *
+     * @param code : 错误码
+     * @param msg  : 错误消息
+     */
+    public ResultVo(int code, String msg) {
         this.code = code;
         this.msg = msg;
-        this.data = data;
-    }
-
-    public static <T> ResultVo<T> ok() {
-        return new ResultVo<>(CODE_SUCCESS);
-    }
-
-    public static <T> ResultVo<T> ok(T data) {
-        return new ResultVo<>(CODE_SUCCESS, null, data);
     }
 
-    public static <T> ResultVo<T> fail(ResEnum res) {
-        return new ResultVo<>(res.getCode(), res.getMsg());
-    }
-
-    public static <T> ResultVo<T> fail() {
-        return fail("服务异常!!");
+    /**
+     * 判断是否成功
+     */
+    public boolean isSuccess() {
+        return Objects.equals(HttpStatusEnum.SUCCESS.getCode(), this.code);
     }
 
     public static <T> ResultVo<T> fail(String msg) {
-        return new ResultVo<>(CODE_ERROR, msg);
-    }
-
-    public static <T> ResultVo<T> toLogin() {
-        return toLogin("登录错误,请重新登录!!!");
-    }
-
-    public static <T> ResultVo<T> toLogin(String msg) {
-        return new ResultVo<>(CODE_TO_LOGIN, msg);
-    }
-
-    public boolean hasSuccess() {
-        return this.code == CODE_SUCCESS;
-    }
-
-    public boolean hasFailed() {
-        return !hasSuccess();
+        return new ResultVo<>(HttpStatusEnum.FAIL.getCode(), msg);
     }
 }

+ 5 - 0
game-module/game-common/src/main/java/com/zanxiang/common/enums/ExpireTimeEnum.java

@@ -22,6 +22,11 @@ public enum ExpireTimeEnum {
      */
     ONE_MIN(60, "1分钟"),
 
+    /**
+     * 5分钟
+     */
+    FIVE_MIN(5 * 60, "1分钟"),
+
     /**
      * 1小时
      */

+ 12 - 2
game-module/game-sdk/src/main/java/com/zanxiang/sdk/domain/enums/UserStatusEnum.java → game-module/game-common/src/main/java/com/zanxiang/common/enums/HttpStatusEnum.java

@@ -1,4 +1,4 @@
-package com.zanxiang.sdk.domain.enums;
+package com.zanxiang.common.enums;
 
 import lombok.AllArgsConstructor;
 import lombok.Getter;
@@ -10,7 +10,17 @@ import lombok.Getter;
  */
 @Getter
 @AllArgsConstructor
-public enum UserStatusEnum {
+public enum HttpStatusEnum {
+
+    /**
+     * 成功
+     */
+    SUCCESS(200, "成功"),
+
+    /**
+     * 服务器异常
+     */
+    FAIL(500, "服务器异常"),
 
     /**
      * 未知错误

+ 10 - 0
game-module/game-common/src/main/java/com/zanxiang/common/utils/StringUtils.java

@@ -349,6 +349,16 @@ public class StringUtils extends org.apache.commons.lang.StringUtils {
         return sb.toString();
     }
 
+    /**
+     * 验证字符串是否为手机号
+     *
+     * @param str : 字符串
+     * @return : 是否为手机号
+     */
+    public static boolean checkPhone(String str) {
+        return str.matches("^[1][3,4,5,7,8,9][0-9]{9}$");
+    }
+
     @SuppressWarnings("unchecked")
     public static <T> T cast(Object obj) {
         return (T) obj;

+ 12 - 0
game-module/game-sdk/pom.xml

@@ -25,6 +25,18 @@
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-test</artifactId>
         </dependency>
+        <dependency>
+            <groupId>com.zanxiangnet.module</groupId>
+            <artifactId>zx-sms</artifactId>
+            <version>1.0.0-SNAPSHOT</version>
+        </dependency>
+        <!-- 解决validated不生效的依赖问题 -->
+        <dependency>
+            <groupId>org.hibernate.validator</groupId>
+            <artifactId>hibernate-validator</artifactId>
+            <version>6.0.17.Final</version>
+            <scope>compile</scope>
+        </dependency>
         <!--    支付相关pom  -->
         <dependency>
             <groupId>com.alipay.sdk</groupId>

+ 96 - 96
game-module/game-sdk/src/main/java/com/zanxiang/sdk/config/MybatisPlusConfig.java

@@ -1,96 +1,96 @@
-//package com.zanxiang.sdk.config;
-//
-//import com.baomidou.mybatisplus.annotation.DbType;
-//import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
-//import com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor;
-//import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
-//import lombok.extern.slf4j.Slf4j;
-//import org.apache.ibatis.cache.CacheKey;
-//import org.apache.ibatis.executor.Executor;
-//import org.apache.ibatis.executor.statement.StatementHandler;
-//import org.apache.ibatis.mapping.BoundSql;
-//import org.apache.ibatis.mapping.MappedStatement;
-//import org.apache.ibatis.session.ResultHandler;
-//import org.apache.ibatis.session.RowBounds;
-//import org.mybatis.spring.annotation.MapperScan;
-//import org.springframework.context.annotation.Bean;
-//import org.springframework.context.annotation.Configuration;
-//import org.springframework.transaction.annotation.EnableTransactionManagement;
-//
-//import java.sql.Connection;
-//import java.sql.SQLException;
-//
-///**
-// * @Author wcc
-// * @Date 2020/9/11 9:30
-// * @Version 1.0
-// * @Description
-// */
-//@Configuration
-//@EnableTransactionManagement
-//@MapperScan("com.zanxiang.sdk.mapper")
-//public class MybatisPlusConfig {
-//
-//    /**
-//     * 分页插件
-//     */
-//    @Bean
-//    public MybatisPlusInterceptor mybatisPlusInterceptor() {
-//        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
-//        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
-//        interceptor.addInnerInterceptor(new DatascopeInterceptor());
-//        return interceptor;
-//    }
-//
-//    @Slf4j
-//    public static class DatascopeInterceptor implements InnerInterceptor {
-//        /**
-//         * {@link Executor#query(MappedStatement, Object, RowBounds, ResultHandler, CacheKey, BoundSql)} 操作前置处理
-//         * <p>
-//         * 改改sql啥的
-//         *
-//         * @param executor      Executor(可能是代理对象)
-//         * @param ms            MappedStatement
-//         * @param parameter     parameter
-//         * @param rowBounds     rowBounds
-//         * @param resultHandler resultHandler
-//         * @param boundSql      boundSql
-//         */
-//        @Override
-//        public void beforeQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
-//            /*System.out.println("-- beforeQuery --");
-//            try {
-//                Select select = (Select) CCJSqlParserUtil.parse(boundSql.getSql());
-//                SelectBody selectBody = select.getSelectBody();
-//                if (selectBody instanceof PlainSelect) {
-//                    PlainSelect plainSelect = (PlainSelect) selectBody;
-//                    List<OrderByElement> orderByElements = plainSelect.getOrderByElements();
-//                    System.out.println(select.toString());
-//                } else if (selectBody instanceof SetOperationList) {
-//                    SetOperationList setOperationList = (SetOperationList) selectBody;
-//                    List<OrderByElement> orderByElements = setOperationList.getOrderByElements();
-//                    System.out.println(select.toString());
-//                } else if (selectBody instanceof WithItem) {
-//                    // todo: don't known how to resole
-//                    System.out.println(selectBody);
-//                }
-//            } catch (JSQLParserException e) {
-//                log.warn("failed to parse sql, exception:\n" + e.getCause());
-//            }*/
-//        }
-//
-//        /**
-//         * {@link StatementHandler#prepare(Connection, Integer)} 操作前置处理
-//         * <p>
-//         * 改改sql啥的
-//         *
-//         * @param sh                 StatementHandler(可能是代理对象)
-//         * @param connection         Connection
-//         * @param transactionTimeout transactionTimeout
-//         */
-//        @Override
-//        public void beforePrepare(StatementHandler sh, Connection connection, Integer transactionTimeout) {
-//            //System.out.println("-- beforePrepare --");
-//        }
-//    }
-//}
+package com.zanxiang.sdk.config;
+
+import com.baomidou.mybatisplus.annotation.DbType;
+import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
+import com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor;
+import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.ibatis.cache.CacheKey;
+import org.apache.ibatis.executor.Executor;
+import org.apache.ibatis.executor.statement.StatementHandler;
+import org.apache.ibatis.mapping.BoundSql;
+import org.apache.ibatis.mapping.MappedStatement;
+import org.apache.ibatis.session.ResultHandler;
+import org.apache.ibatis.session.RowBounds;
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.transaction.annotation.EnableTransactionManagement;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+
+/**
+ * @Author wcc
+ * @Date 2020/9/11 9:30
+ * @Version 1.0
+ * @Description
+ */
+@Configuration
+@EnableTransactionManagement
+@MapperScan("com.zanxiang.sdk.mapper")
+public class MybatisPlusConfig {
+
+    /**
+     * 分页插件
+     */
+    @Bean
+    public MybatisPlusInterceptor mybatisPlusInterceptor() {
+        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
+        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
+        interceptor.addInnerInterceptor(new DatascopeInterceptor());
+        return interceptor;
+    }
+
+    @Slf4j
+    public static class DatascopeInterceptor implements InnerInterceptor {
+        /**
+         * {@link Executor#query(MappedStatement, Object, RowBounds, ResultHandler, CacheKey, BoundSql)} 操作前置处理
+         * <p>
+         * 改改sql啥的
+         *
+         * @param executor      Executor(可能是代理对象)
+         * @param ms            MappedStatement
+         * @param parameter     parameter
+         * @param rowBounds     rowBounds
+         * @param resultHandler resultHandler
+         * @param boundSql      boundSql
+         */
+        @Override
+        public void beforeQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
+            /*System.out.println("-- beforeQuery --");
+            try {
+                Select select = (Select) CCJSqlParserUtil.parse(boundSql.getSql());
+                SelectBody selectBody = select.getSelectBody();
+                if (selectBody instanceof PlainSelect) {
+                    PlainSelect plainSelect = (PlainSelect) selectBody;
+                    List<OrderByElement> orderByElements = plainSelect.getOrderByElements();
+                    System.out.println(select.toString());
+                } else if (selectBody instanceof SetOperationList) {
+                    SetOperationList setOperationList = (SetOperationList) selectBody;
+                    List<OrderByElement> orderByElements = setOperationList.getOrderByElements();
+                    System.out.println(select.toString());
+                } else if (selectBody instanceof WithItem) {
+                    // todo: don't known how to resole
+                    System.out.println(selectBody);
+                }
+            } catch (JSQLParserException e) {
+                log.warn("failed to parse sql, exception:\n" + e.getCause());
+            }*/
+        }
+
+        /**
+         * {@link StatementHandler#prepare(Connection, Integer)} 操作前置处理
+         * <p>
+         * 改改sql啥的
+         *
+         * @param sh                 StatementHandler(可能是代理对象)
+         * @param connection         Connection
+         * @param transactionTimeout transactionTimeout
+         */
+        @Override
+        public void beforePrepare(StatementHandler sh, Connection connection, Integer transactionTimeout) {
+            //System.out.println("-- beforePrepare --");
+        }
+    }
+}

+ 19 - 0
game-module/game-sdk/src/main/java/com/zanxiang/sdk/config/RestTemplateConfig.java

@@ -0,0 +1,19 @@
+package com.zanxiang.sdk.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.client.RestTemplate;
+
+/**
+ * @author : lingfeng
+ * @time : 2021-08-18
+ * @description : redis配置
+ */
+@Configuration
+public class RestTemplateConfig {
+
+    @Bean
+    public RestTemplate restTemplate() {
+        return new RestTemplate();
+    }
+}

+ 5 - 0
game-module/game-sdk/src/main/java/com/zanxiang/sdk/constant/RedisKeyConstant.java

@@ -21,4 +21,9 @@ public class RedisKeyConstant {
      * token缓存key
      */
     public static final String TOKEN_INFO_KEY = RedisKeyConstant.REDIS_PREFIX + "token_info";
+
+    /**
+     * 手机验证码缓存key
+     */
+    public static final String SMS_PHONE_KEY = RedisKeyConstant.REDIS_PREFIX + "sms_phone";
 }

+ 99 - 0
game-module/game-sdk/src/main/java/com/zanxiang/sdk/domain/dto/UserDTO.java

@@ -0,0 +1,99 @@
+package com.zanxiang.sdk.domain.dto;
+
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+/**
+ * @author : lingfeng
+ * @time : 2022-06-09
+ * @description : 用户信息
+ */
+@Data
+public class UserDTO {
+
+    /**
+     * id
+     */
+    private Long id;
+
+    /**
+     * 所属渠道ID
+     */
+    private Long agentId;
+
+    /**
+     * 用户名
+     */
+    private String username;
+
+    /**
+     * 昵称
+     */
+    private String nickname;
+
+    /**
+     * 注册手机号
+     */
+    private String regMobile;
+
+    /**
+     * 注册邮箱
+     */
+    private String regEmail;
+
+    /**
+     * 密码
+     */
+    private String password;
+
+    /**
+     * 绑定邮箱
+     */
+    private String email;
+
+    /**
+     * 绑定手机号码
+     */
+    private String mobile;
+
+    /**
+     * 设备来源 mobile,android,iphone,ipad,web,pc,mac,wxapp
+     */
+    private String fromDevice;
+
+    /**
+     * 设备ID android 为imei ios 为idfa
+     */
+    private String deviceId;
+
+    /**
+     * 设备类型
+     */
+    private String deviceType;
+
+    /**
+     * -1 为冻结状态, 1 为试玩状态 2为正常状态
+     */
+    private Integer status;
+
+    /**
+     * 头像
+     */
+    private String avatar;
+
+    /**
+     * 渠道
+     */
+    private Long channel;
+
+    /**
+     * 注册时间
+     */
+    private LocalDateTime createTime;
+
+    /**
+     * 更改时间
+     */
+    private LocalDateTime updateTime;
+}

+ 3 - 0
game-module/game-sdk/src/main/java/com/zanxiang/sdk/domain/dto/UserTokenDTO.java

@@ -1,5 +1,7 @@
 package com.zanxiang.sdk.domain.dto;
 
+import lombok.Data;
+
 import java.time.LocalDateTime;
 
 /**
@@ -7,6 +9,7 @@ import java.time.LocalDateTime;
  * @time : 2022-06-08
  * @description : 用户token信息
  */
+@Data
 public class UserTokenDTO {
 
     /**

+ 7 - 2
game-module/game-sdk/src/main/java/com/zanxiang/sdk/domain/entity/User.java

@@ -79,9 +79,14 @@ public class User {
     private String deviceId;
 
     /**
-     * 1 为试玩状态 2为正常状态,3为冻结状态
+     * 设备类型
      */
-    private Boolean status;
+    private String deviceType;
+
+    /**
+     * -1 为冻结状态, 1 为试玩状态 2为正常状态
+     */
+    private Integer status;
 
     /**
      * 头像

+ 17 - 0
game-module/game-sdk/src/main/java/com/zanxiang/sdk/domain/entity/UserLoginLog.java

@@ -62,4 +62,21 @@ public class UserLoginLog {
      * 登录时间
      */
     private LocalDateTime loginTime;
+
+    /**
+     * 构造方法
+     *
+     * @param loginIp : 用户ip
+     * @param user    : 用户信息
+     * @param gameId  : 游戏id
+     */
+    public UserLoginLog(String loginIp, User user, Long gameId) {
+        this.userId = user.getId();
+        this.agentId = user.getAgentId();
+        this.fromDevice = user.getFromDevice();
+        this.deviceId = user.getDeviceId();
+        this.loginIp = loginIp;
+        this.gameId = gameId;
+        this.loginTime = LocalDateTime.now();
+    }
 }

+ 39 - 0
game-module/game-sdk/src/main/java/com/zanxiang/sdk/domain/enums/AccountStatusEnum.java

@@ -0,0 +1,39 @@
+package com.zanxiang.sdk.domain.enums;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * @author : lingfeng
+ * @time : 2022-06-09
+ * @description : 账号状态枚举
+ */
+@Getter
+@AllArgsConstructor
+public enum AccountStatusEnum {
+
+    /**
+     * 密码加密盐值
+     */
+    TRY_PLAY_STATUS(1, "试玩状态"),
+
+    /**
+     * 正常状态
+     */
+    NORMAL_STATUS(2, "正常状态"),
+
+    /**
+     * 冻结状态
+     */
+    FROZEN_STATUS(-1, "冻结状态");
+
+    /**
+     * 盐值
+     */
+    private Integer status;
+
+    /**
+     * 描述
+     */
+    private String describe;
+}

+ 30 - 0
game-module/game-sdk/src/main/java/com/zanxiang/sdk/domain/enums/CmfSaltEnum.java

@@ -0,0 +1,30 @@
+package com.zanxiang.sdk.domain.enums;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * @author : lingfeng
+ * @time : 2022-06-09
+ * @description : cmf加密盐值
+ */
+@Getter
+@AllArgsConstructor
+public enum CmfSaltEnum {
+
+    /**
+     * 密码加密盐值
+     */
+    CMF_PASSWORD("ZX_PASSWORD_SALT", "密码加密盐值");
+
+    /**
+     * 盐值
+     */
+    private String salt;
+
+    /**
+     * 描述
+     */
+    private String describe;
+
+}

+ 17 - 0
game-module/game-sdk/src/main/java/com/zanxiang/sdk/domain/enums/SmsTypeEnum.java

@@ -3,6 +3,9 @@ package com.zanxiang.sdk.domain.enums;
 import lombok.AllArgsConstructor;
 import lombok.Getter;
 
+import java.util.Arrays;
+import java.util.Objects;
+
 /**
  * @author : lingfeng
  * @time : 2022-06-07
@@ -56,4 +59,18 @@ public enum SmsTypeEnum {
      * 描述
      */
     private String describe;
+
+    /**
+     * 根据type获取枚举
+     *
+     * @return : 返回枚举对象
+     */
+    public static SmsTypeEnum getByType(Integer type) {
+        if (type == null) {
+            return null;
+        }
+        return Arrays.stream(SmsTypeEnum.values())
+                .filter(e -> Objects.equals(e.getType(), type))
+                .findFirst().orElse(null);
+    }
 }

+ 2 - 13
game-module/game-sdk/src/main/java/com/zanxiang/sdk/domain/params/LoginMobileParam.java

@@ -23,22 +23,11 @@ public class LoginMobileParam extends CommonParam {
      * 手机号
      */
     @JsonAlias("sms-mobile")
-    private Long mobile;
+    private String mobile;
 
     /**
      * 验证码
      */
     @JsonAlias("sms-code")
-    private Integer code;
-
-    /**
-     * 重定向地址
-     */
-    @JsonAlias("redirect_url")
-    private String redirectUrl;
-
-    /**
-     * json类型
-     */
-    private String format;
+    private String code;
 }

+ 4 - 0
game-module/game-sdk/src/main/java/com/zanxiang/sdk/domain/params/LoginPasswordParam.java

@@ -4,6 +4,8 @@ import com.fasterxml.jackson.annotation.JsonAlias;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
 
+import javax.validation.constraints.NotBlank;
+
 /**
  * @author : lingfeng
  * @time : 2022-06-07
@@ -17,11 +19,13 @@ public class LoginPasswordParam extends CommonParam {
      * 用户名
      */
     @JsonAlias("mem-username")
+    @NotBlank(message = "登陆用户名字不可为空")
     private String username;
 
     /**
      * 密码
      */
+    @NotBlank(message = "登陆密码不可为空")
     @JsonAlias("mem-password")
     private String password;
 }

+ 37 - 0
game-module/game-sdk/src/main/java/com/zanxiang/sdk/domain/params/SmsCheckParam.java

@@ -0,0 +1,37 @@
+package com.zanxiang.sdk.domain.params;
+
+import com.fasterxml.jackson.annotation.JsonAlias;
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+
+/**
+ * @author : lingfeng
+ * @time : 2022-06-13
+ * @description : 短信验证码校验参数
+ */
+@Data
+public class SmsCheckParam {
+
+    /**
+     * 验证码类型
+     */
+    @JsonAlias("sms-type")
+    @NotNull(message = "验证码类型不可为空")
+    private Integer type;
+
+    /**
+     * 手机号码
+     */
+    @JsonAlias("sms-mobile")
+    @NotBlank(message = "手机号码不可为空")
+    private String mobile;
+
+    /**
+     * 手机验证码
+     */
+    @JsonAlias("sms-code")
+    @NotBlank(message = "手机验证码不可为空")
+    private String code;
+}

+ 30 - 0
game-module/game-sdk/src/main/java/com/zanxiang/sdk/domain/params/SmsSendParam.java

@@ -0,0 +1,30 @@
+package com.zanxiang.sdk.domain.params;
+
+import com.fasterxml.jackson.annotation.JsonAlias;
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+
+/**
+ * @author : lingfeng
+ * @time : 2022-06-09
+ * @description : 发送短信参数
+ */
+@Data
+public class SmsSendParam {
+
+    /**
+     * 验证码类型
+     */
+    @JsonAlias("sms-type")
+    @NotNull(message = "验证码类型不可为空")
+    private Integer type;
+
+    /**
+     * 手机号码
+     */
+    @JsonAlias("sms-mobile")
+    @NotBlank(message = "手机号码不可为空")
+    private String mobile;
+}

+ 0 - 80
game-module/game-sdk/src/main/java/com/zanxiang/sdk/domain/vo/ResultVO.java

@@ -1,80 +0,0 @@
-package com.zanxiang.sdk.domain.vo;
-
-import com.zanxiang.sdk.domain.enums.UserStatusEnum;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-import java.io.Serializable;
-
-/**
- * 响应信息主体
- *
- * @author ruoyi
- */
-@Data
-@NoArgsConstructor
-@AllArgsConstructor
-@Builder
-public class ResultVO<T> implements Serializable {
-
-    private static final long serialVersionUID = 1L;
-
-    /**
-     * 成功code
-     */
-    public static final Integer CODE_SUCCESS = 200;
-
-    /**
-     * 成功msg
-     */
-    public static final String CODE_SUCCESS_MSG = "成功";
-
-    /**
-     * 错误码
-     */
-    private Integer code;
-
-    /**
-     * 错误消息
-     */
-    private String msg;
-
-    /**
-     * 返回数据
-     */
-    private T data;
-
-    /**
-     * 构造方法
-     *
-     * @param code : 错误码
-     * @param msg  : 错误消息
-     */
-    private ResultVO(int code, String msg) {
-        this(code, msg, null);
-    }
-
-    /**
-     * 错误信息构造
-     *
-     * @param userStatusEnum : 错误枚举
-     * @param <T>            : 泛型
-     * @return : 返回
-     */
-    public static <T> ResultVO<T> fail(UserStatusEnum userStatusEnum) {
-        return new ResultVO<>(userStatusEnum.getCode(), userStatusEnum.getMsg());
-    }
-
-    /**
-     * 成功返回数据
-     *
-     * @param data : 数据
-     * @param <T>  : 泛型
-     * @return : 返回
-     */
-    public static <T> ResultVO<T> ok(T data) {
-        return new ResultVO<>(CODE_SUCCESS, "成功", data);
-    }
-}

+ 9 - 0
game-module/game-sdk/src/main/java/com/zanxiang/sdk/domain/vo/UserLoginVO.java

@@ -14,4 +14,13 @@ public class UserLoginVO {
      * 登录授权的token
      */
     private String token;
+
+    /**
+     * 构造方法
+     *
+     * @param token : 用户token
+     */
+    public UserLoginVO(String token) {
+        this.token = token;
+    }
 }

+ 30 - 0
game-module/game-sdk/src/main/java/com/zanxiang/sdk/service/ISmsService.java

@@ -0,0 +1,30 @@
+package com.zanxiang.sdk.service;
+
+import com.zanxiang.common.domain.ResultVo;
+import com.zanxiang.common.enums.HttpStatusEnum;
+import com.zanxiang.sdk.domain.params.SmsSendParam;
+
+/**
+ * @author : lingfeng
+ * @time : 2022-06-13
+ * @description :
+ */
+public interface ISmsService {
+
+    /**
+     * 发送短信验证码
+     *
+     * @param smsSendParam : 获取短信验证码参数
+     */
+    ResultVo<Void> smsSend(SmsSendParam smsSendParam);
+
+    /**
+     * 校验短信验证码
+     *
+     * @param type   : 短信类型
+     * @param mobile : 手机号
+     * @param code   : 验证码
+     * @return : 返回验证结果
+     */
+    HttpStatusEnum smsCheck(Integer type, String mobile, String code);
+}

+ 19 - 0
game-module/game-sdk/src/main/java/com/zanxiang/sdk/service/IUserLoginLogService.java

@@ -0,0 +1,19 @@
+package com.zanxiang.sdk.service;
+
+import com.zanxiang.sdk.domain.entity.User;
+
+/**
+ * @author : lingfeng
+ * @time : 2022-06-13
+ * @description :
+ */
+public interface IUserLoginLogService {
+
+    /**
+     * 添加用户登录日志
+     *
+     * @param user   : 用户信息
+     * @param gameId : 游戏id
+     */
+    void addUserLoginLog(String realIp, User user, Long gameId);
+}

+ 33 - 0
game-module/game-sdk/src/main/java/com/zanxiang/sdk/service/IUserService.java

@@ -1,7 +1,14 @@
 package com.zanxiang.sdk.service;
 
 import com.baomidou.mybatisplus.extension.service.IService;
+import com.zanxiang.common.domain.ResultVo;
+import com.zanxiang.sdk.domain.dto.UserDTO;
 import com.zanxiang.sdk.domain.entity.User;
+import com.zanxiang.sdk.domain.params.LoginMobileParam;
+import com.zanxiang.sdk.domain.params.LoginPasswordParam;
+import com.zanxiang.sdk.domain.vo.UserLoginVO;
+
+import javax.servlet.http.HttpServletRequest;
 
 /**
  * @author : lingfeng
@@ -9,4 +16,30 @@ import com.zanxiang.sdk.domain.entity.User;
  * @description : 用户信息
  */
 public interface IUserService extends IService<User> {
+
+    /**
+     * 用户名密码登录
+     *
+     * @param userLoginParam : 登录参数
+     * @param request        : HttpServletRequest
+     * @return : 返回登录token
+     */
+    ResultVo<UserLoginVO> loginPassword(LoginPasswordParam userLoginParam, HttpServletRequest request);
+
+    /**
+     * 手机号登录
+     *
+     * @param loginMobileParam : 手机号登录参数
+     * @param request          : HttpServletRequest
+     * @return : 返回登录信息
+     */
+    ResultVo<UserLoginVO> loginMobile(LoginMobileParam loginMobileParam, HttpServletRequest request);
+
+    /**
+     * 检查用户手机号是否存在
+     *
+     * @param mobile : 用户手机号
+     * @return : 返回用户信息
+     */
+    UserDTO getUserInfoByMobile(String mobile);
 }

+ 9 - 0
game-module/game-sdk/src/main/java/com/zanxiang/sdk/service/IUserTokenService.java

@@ -11,6 +11,15 @@ import com.zanxiang.sdk.domain.entity.UserToken;
  */
 public interface IUserTokenService extends IService<UserToken> {
 
+    /**
+     * 通过token设备获取token详情
+     *
+     * @param token      : 用户token
+     * @param deviceType : 设备类型
+     * @return : 返回用户token详情
+     */
+    UserTokenDTO getTokenInfoByTokenDevice(String token, String deviceType);
+
     /**
      * 通过用户设备获取token详情
      *

+ 147 - 0
game-module/game-sdk/src/main/java/com/zanxiang/sdk/service/Impl/SmsServiceImpl.java

@@ -0,0 +1,147 @@
+package com.zanxiang.sdk.service.Impl;
+
+import com.zanxiang.common.domain.ResultVo;
+import com.zanxiang.common.enums.ExpireTimeEnum;
+import com.zanxiang.common.enums.HttpStatusEnum;
+import com.zanxiang.common.utils.StringUtils;
+import com.zanxiang.sdk.constant.RedisKeyConstant;
+import com.zanxiang.sdk.domain.dto.UserDTO;
+import com.zanxiang.sdk.domain.enums.SmsTypeEnum;
+import com.zanxiang.sdk.domain.params.SmsSendParam;
+import com.zanxiang.sdk.service.ISmsService;
+import com.zanxiang.sdk.service.IUserService;
+import com.zanxiang.sdk.utils.RedisUtils;
+import com.zanxiangnet.module.sms.pojo.SendResult;
+import com.zanxiangnet.module.sms.service.impl.AliSmsService;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.logging.log4j.util.Strings;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.Objects;
+import java.util.Random;
+
+/**
+ * @author : lingfeng
+ * @time : 2022-06-09
+ * @description : 手机短信逻辑
+ */
+@Slf4j
+@Service
+public class SmsServiceImpl implements ISmsService {
+
+    @Autowired
+    private IUserService userService;
+
+    @Autowired
+    private RedisUtils<String> redisUtils;
+
+    @Autowired
+    private AliSmsService aliSmsService;
+
+    /**
+     * 发送短信验证码
+     *
+     * @param smsSendParam : 获取短信验证码参数
+     */
+    @Override
+    public ResultVo<Void> smsSend(SmsSendParam smsSendParam) {
+        //类型
+        Integer type = smsSendParam.getType();
+        //手机号码
+        String mobile = smsSendParam.getMobile();
+        //根据手机号获取用户信息
+        UserDTO userDTO = userService.getUserInfoByMobile(mobile);
+        //找回密码获取
+        if (Objects.equals(type, SmsTypeEnum.SMS_FIND_PWD.getType())) {
+            //手机号对应用户信息不存在
+            if (userDTO == null) {
+                return new ResultVo<>(HttpStatusEnum.USERNAME_NOT_EXISTS);
+            }
+        }
+        //用户注册获取
+        if (Objects.equals(type, SmsTypeEnum.SMS_REG.getType())) {
+            //判断手机号是否已注册
+            if (userDTO != null) {
+                return new ResultVo<>(HttpStatusEnum.PHONE_IS_REG);
+            }
+        }
+        //验证手机号
+        if (!StringUtils.checkPhone(mobile)) {
+            return new ResultVo<>(HttpStatusEnum.PHONE_ERROR);
+        }
+        //验证类型
+        SmsTypeEnum smsTypeEnum = SmsTypeEnum.getByType(type);
+        if (smsTypeEnum == null) {
+            return new ResultVo<>(HttpStatusEnum.CODE_TYPE_ERROR);
+        }
+        //判断是否已经发送
+        String cache = redisUtils.getCache(this.smsKey(mobile, type));
+        if (Strings.isNotBlank(cache)) {
+            return new ResultVo<>(HttpStatusEnum.PHONE_HAS_SEND);
+        }
+        //发送验证码
+        String randomCode = this.randomCode();
+        SendResult sendResult = aliSmsService.sendCode(randomCode, mobile);
+        //发送成功设置缓存, 时效5分钟
+        if (sendResult.isSuccess()) {
+            redisUtils.setCache(this.smsKey(mobile, type), randomCode, ExpireTimeEnum.FIVE_MIN.getTime());
+        }
+        return new ResultVo<>(HttpStatusEnum.SUCCESS);
+    }
+
+    /**
+     * 校验短信验证码
+     *
+     * @param type   : 短信类型
+     * @param mobile : 手机号
+     * @param code   : 验证码
+     * @return : 返回验证结果
+     */
+    @Override
+    public HttpStatusEnum smsCheck(Integer type, String mobile, String code) {
+        //验证类型
+        SmsTypeEnum smsTypeEnum = SmsTypeEnum.getByType(type);
+        if (smsTypeEnum == null) {
+            return HttpStatusEnum.CODE_TYPE_ERROR;
+        }
+        //验证手机号
+        if (!StringUtils.checkPhone(mobile)) {
+            return HttpStatusEnum.PHONE_ERROR;
+        }
+        //获取缓存中的验证码
+        String smsKey = this.smsKey(mobile, type);
+        String cache = redisUtils.getCache(smsKey);
+        //验证码已过期
+        if (Strings.isBlank(cache)) {
+            return HttpStatusEnum.CODE_IS_EXPIRED;
+        }
+        //验证码错误
+        if (!Objects.equals(cache, code)) {
+            return HttpStatusEnum.CODE_ERROR;
+        }
+        //验证成功, 删除缓存
+        redisUtils.deleteCache(smsKey);
+        //返回成功
+        return HttpStatusEnum.SUCCESS;
+    }
+
+    /**
+     * 获取手机验证码
+     */
+    private String randomCode() {
+        Random random = new Random();
+        return String.valueOf(random.nextInt(999999) + 100000);
+    }
+
+    /**
+     * 手机验证码缓存key
+     *
+     * @param mobile : 手机号
+     * @param type   : 短信类型
+     * @return : 返回redis缓存key
+     */
+    private String smsKey(String mobile, Integer type) {
+        return RedisKeyConstant.SMS_PHONE_KEY + "_" + mobile + "_" + type;
+    }
+}

+ 31 - 0
game-module/game-sdk/src/main/java/com/zanxiang/sdk/service/Impl/UserLoginLogServiceImpl.java

@@ -0,0 +1,31 @@
+package com.zanxiang.sdk.service.Impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.zanxiang.sdk.domain.entity.User;
+import com.zanxiang.sdk.domain.entity.UserLoginLog;
+import com.zanxiang.sdk.mapper.UserLoginLogMapper;
+import com.zanxiang.sdk.service.IUserLoginLogService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+/**
+ * @author : lingfeng
+ * @time : 2022-06-13
+ * @description : 用户登录日志
+ */
+@Slf4j
+@Service
+public class UserLoginLogServiceImpl extends ServiceImpl<UserLoginLogMapper, UserLoginLog> implements IUserLoginLogService {
+
+    /**
+     * 添加用户登录日志
+     *
+     * @param user   : 用户信息
+     * @param gameId : 游戏id
+     */
+    @Override
+    public void addUserLoginLog(String realIp, User user, Long gameId) {
+        UserLoginLog userLoginLog = new UserLoginLog(realIp, user, gameId);
+        super.save(userLoginLog);
+    }
+}

+ 126 - 4
game-module/game-sdk/src/main/java/com/zanxiang/sdk/service/Impl/UserServiceImpl.java

@@ -1,14 +1,34 @@
 package com.zanxiang.sdk.service.Impl;
 
+import com.alibaba.nacos.common.utils.MD5Utils;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.zanxiang.common.domain.ResultVo;
+import com.zanxiang.common.enums.HttpStatusEnum;
+import com.zanxiang.common.exception.BaseException;
+import com.zanxiang.common.utils.IpUtils;
+import com.zanxiang.common.utils.StringUtils;
+import com.zanxiang.common.utils.bean.BeanUtils;
+import com.zanxiang.sdk.domain.dto.UserDTO;
 import com.zanxiang.sdk.domain.entity.User;
+import com.zanxiang.sdk.domain.enums.AccountStatusEnum;
+import com.zanxiang.sdk.domain.enums.CmfSaltEnum;
+import com.zanxiang.sdk.domain.params.LoginMobileParam;
 import com.zanxiang.sdk.domain.params.LoginPasswordParam;
 import com.zanxiang.sdk.domain.vo.UserLoginVO;
 import com.zanxiang.sdk.mapper.UserMapper;
+import com.zanxiang.sdk.service.ISmsService;
+import com.zanxiang.sdk.service.IUserLoginLogService;
 import com.zanxiang.sdk.service.IUserService;
+import com.zanxiang.sdk.service.IUserTokenService;
 import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
+import javax.servlet.http.HttpServletRequest;
+import java.security.NoSuchAlgorithmException;
+import java.util.Objects;
+
 /**
  * @author : lingfeng
  * @time : 2022-06-07
@@ -18,21 +38,123 @@ import org.springframework.stereotype.Service;
 @Service
 public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
 
+    @Autowired
+    private IUserTokenService userTokenService;
+
+    @Autowired
+    private ISmsService smsService;
+
+    @Autowired
+    private IUserLoginLogService userLoginLogService;
+
     /**
      * 用户名密码登录
      *
      * @param userLoginParam : 登录参数
+     * @param request : HttpServletRequest
      * @return : 返回登录token
      */
-    public UserLoginVO loginPassword(LoginPasswordParam userLoginParam) {
-        return null;
+    @Override
+    public ResultVo<UserLoginVO> loginPassword(LoginPasswordParam userLoginParam, HttpServletRequest request) {
+        //用户名
+        String username = userLoginParam.getUsername();
+        //密码
+        String password = userLoginParam.getPassword();
+        //用户信息
+        User user;
+        //验证用户名是否为手机号
+        if (StringUtils.checkPhone(username)) {
+            user = super.getOne(new LambdaQueryWrapper<User>().eq(User::getMobile, username));
+        } else {
+            user = super.getOne(new LambdaQueryWrapper<User>().eq(User::getUsername, username));
+        }
+        //用户信息不存在
+        if (user == null) {
+            return new ResultVo<>(HttpStatusEnum.USERNAME_OR_PASSWORD_ERR);
+        }
+        //判断账号是否停用
+        if (Objects.equals(AccountStatusEnum.FROZEN_STATUS.getStatus(), user.getStatus())) {
+            return new ResultVo<>(HttpStatusEnum.ACCOUNT_HALT);
+        }
+        //验证密码
+        if (!Objects.equals(this.cmfPassword(password), user.getPassword())) {
+            return new ResultVo<>(HttpStatusEnum.USERNAME_OR_PASSWORD_ERR);
+        }
+        //验证通过, 获取token
+        String userToken = userTokenService.getUserToken(user.getId(), user.getDeviceType());
+        //登录的ip
+        String realIp = IpUtils.getRealIp(request);
+        //插入用户登录记录
+        userLoginLogService.addUserLoginLog(realIp, user, userLoginParam.getGameId());
+        //构造返回
+        return new ResultVo<>(new UserLoginVO(userToken));
     }
 
+
     /**
      * 手机号登录
+     *
+     * @param loginMobileParam : 手机号登录参数
+     * @param request : HttpServletRequest
+     * @return : 返回登录信息
+     */
+    @Override
+    public ResultVo<UserLoginVO> loginMobile(LoginMobileParam loginMobileParam, HttpServletRequest request) {
+        Integer type = loginMobileParam.getType();
+        String mobile = loginMobileParam.getMobile();
+        String code = loginMobileParam.getCode();
+        //验证码校验
+        HttpStatusEnum httpStatusEnum = smsService.smsCheck(type, mobile, code);
+        //验证不通过, 返回
+        if (!Objects.equals(httpStatusEnum, HttpStatusEnum.SUCCESS)) {
+            return new ResultVo<>(httpStatusEnum);
+        }
+        //获取用户信息
+        User user = super.getOne(new LambdaQueryWrapper<User>().eq(User::getMobile, mobile));
+        //用户信息不存在
+        if (user == null) {
+            return new ResultVo<>(HttpStatusEnum.PHONE_NOT_REG);
+        }
+        //判断账号是否停用
+        if (Objects.equals(AccountStatusEnum.FROZEN_STATUS.getStatus(), user.getStatus())) {
+            return new ResultVo<>(HttpStatusEnum.ACCOUNT_HALT);
+        }
+        //验证通过, 获取token
+        String userToken = userTokenService.getUserToken(user.getId(), user.getDeviceType());
+        //登录的ip
+        String realIp = IpUtils.getRealIp(request);
+        //插入用户登录记录
+        userLoginLogService.addUserLoginLog(realIp, user, loginMobileParam.getGameId());
+        //构造返回
+        return new ResultVo<>(new UserLoginVO(userToken));
+    }
+
+    /**
+     * 密码cfm加密
+     *
+     * @param password : 密码
+     * @return : 返回加密完的密码
+     */
+    private String cmfPassword(String password) {
+        String passwordSalt = password + CmfSaltEnum.CMF_PASSWORD.getSalt();
+        try {
+            return "###" + MD5Utils.md5Hex(MD5Utils.md5Hex(passwordSalt.getBytes()).getBytes());
+        } catch (NoSuchAlgorithmException e) {
+            e.printStackTrace();
+            throw new BaseException("密码加密异常");
+        }
+    }
+
+    /**
+     * 检查用户手机号是否存在
+     *
+     * @param mobile : 用户手机号
+     * @return : 返回用户信息
      */
-    public UserLoginVO loginMobile(LoginPasswordParam userLoginParam) {
-        return null;
+    @Override
+    public UserDTO getUserInfoByMobile(String mobile) {
+        User user = super.getOne(new LambdaQueryWrapper<User>().eq(User::getMobile, mobile));
+        return BeanUtils.copy(user, UserDTO.class);
     }
 
 }

+ 195 - 158
game-module/game-sdk/src/main/java/com/zanxiang/sdk/service/Impl/UserTokenServiceImpl.java

@@ -1,158 +1,195 @@
-//package com.zanxiang.sdk.service.Impl;
-//
-//import com.alibaba.nacos.common.utils.CollectionUtils;
-//import com.alibaba.nacos.common.utils.MD5Utils;
-//import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-//import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-//import com.zanxiang.common.enums.ExpireTimeEnum;
-//import com.zanxiang.common.exception.BaseException;
-//import com.zanxiang.common.redis.utils.RedisUtils;
-//import com.zanxiang.common.text.UUID;
-//import com.zanxiang.common.utils.bean.BeanUtils;
-//import com.zanxiang.sdk.constant.RedisKeyConstant;
-//import com.zanxiang.sdk.domain.dto.UserTokenDTO;
-//import com.zanxiang.sdk.domain.entity.UserToken;
-//import com.zanxiang.sdk.mapper.UserTokenMapper;
-//import com.zanxiang.sdk.service.IUserTokenService;
-//import lombok.extern.slf4j.Slf4j;
-//import org.springframework.beans.factory.annotation.Autowired;
-//import org.springframework.stereotype.Service;
-//
-//import java.security.NoSuchAlgorithmException;
-//import java.util.List;
-//
-///**
-// * @author : lingfeng
-// * @time : 2022-06-07
-// * @description : 用户token管理
-// */
-//@Slf4j
-//@Service
-//public class UserTokenServiceImpl extends ServiceImpl<UserTokenMapper, UserToken> implements IUserTokenService {
-//
-//    @Autowired
-//    private RedisUtils<UserToken> redisUtils;
-//
-//    /**
-//     * 通过用户设备获取token详情
-//     *
-//     * @param userId     : 用户id
-//     * @param deviceType : 设备类型
-//     * @return : 返回token
-//     */
-//    @Override
-//    public UserTokenDTO getTokenInfoByUserDevice(Long userId, String deviceType) {
-//        //查询缓存信息
-//        String key = this.getUserTokenKey(userId, deviceType);
-//        UserToken userToken = redisUtils.getCache(key);
-//        if (userToken != null) {
-//            return BeanUtils.copy(userToken, UserTokenDTO.class);
-//        }
-//        //缓存不存在, 查询数据库
-//        userToken = super.getOne(new LambdaQueryWrapper<UserToken>()
-//                .eq(UserToken::getUserId, userId)
-//                .eq(UserToken::getDeviceType, deviceType));
-//        if (userToken == null) {
-//            return null;
-//        }
-//        return BeanUtils.copy(userToken, UserTokenDTO.class);
-//    }
-//
-//    /**
-//     * 获取用户token
-//     *
-//     * @param userId     : 用户id
-//     * @param deviceType : 设备类型
-//     * @return : 返回token
-//     */
-//    @Override
-//    public String getUserToken(Long userId, String deviceType) {
-//        //获取token
-//        String token = this.createToken(userId, deviceType);
-//        //查询数据库token信息
-//        UserToken userToken = super.getOne(new LambdaQueryWrapper<UserToken>()
-//                .eq(UserToken::getUserId, userId)
-//                .eq(UserToken::getDeviceType, deviceType));
-//        //不存在token数据, 直接创建
-//        if (userToken == null) {
-//            userToken = new UserToken(userId, token, deviceType);
-//            super.save(userToken);
-//        } else {
-//            //梗系数据库
-//            userToken.updateToken(token);
-//            super.updateById(userToken);
-//        }
-//        //设置用户缓存
-//        String userTokenKey = this.getUserTokenKey(userId, deviceType);
-//        redisUtils.setCache(userTokenKey, userToken, ExpireTimeEnum.ONE_WEEK.getTime());
-//        //设置token详情缓存
-//        String tokenInfoKey = this.getTokenInfoKey(token, deviceType);
-//        redisUtils.setCache(tokenInfoKey, userToken, ExpireTimeEnum.ONE_WEEK.getTime());
-//        //返回token
-//        return token;
-//    }
-//
-//    /**
-//     * 删除用户token
-//     *
-//     * @param userId : 用户id
-//     */
-//    @Override
-//    public void deleteUserToken(Long userId) {
-//        List<UserToken> userTokenList = super.list(new LambdaQueryWrapper<UserToken>()
-//                .eq(UserToken::getUserId, userId));
-//        if (CollectionUtils.isEmpty(userTokenList)) {
-//            return;
-//        }
-//        userTokenList.forEach(userToken -> {
-//            //根据主键删除数据库
-//            super.removeById(userToken.getId());
-//            //删除缓存
-//            String userTokenKey = this.getUserTokenKey(userId, userToken.getDeviceType());
-//            redisUtils.deleteCache(userTokenKey);
-//            String tokenInfoKey = this.getTokenInfoKey(userToken.getToken(), userToken.getDeviceType());
-//            redisUtils.deleteCache(tokenInfoKey);
-//        });
-//    }
-//
-//    /**
-//     * 创建token
-//     *
-//     * @param userId     : 用户id
-//     * @param deviceType : 设备类型
-//     * @return : 返回token
-//     */
-//    private String createToken(Long userId, String deviceType) {
-//        //生成随机数
-//        String random = userId + deviceType + UUID.randomUUID().toString() + System.currentTimeMillis();
-//        //创建token
-//        try {
-//            return MD5Utils.md5Hex(MD5Utils.md5Hex(random.getBytes()).getBytes());
-//        } catch (NoSuchAlgorithmException e) {
-//            e.printStackTrace();
-//            throw new BaseException("生成token异常");
-//        }
-//    }
-//
-//    /**
-//     * 拼接用户token缓存key
-//     *
-//     * @param userId     : 用户id
-//     * @param deviceType : 设备类型
-//     * @return : 返回用户token的缓存key
-//     */
-//    private String getUserTokenKey(Long userId, String deviceType) {
-//        return RedisKeyConstant.USER_TOKEN_KEY + "_" + userId + "_" + deviceType;
-//    }
-//
-//    /**
-//     * 拼接用户token缓存key
-//     *
-//     * @param token      : 用户token
-//     * @param deviceType : 设备类型
-//     * @return : 返回用户token的缓存key
-//     */
-//    private String getTokenInfoKey(String token, String deviceType) {
-//        return RedisKeyConstant.TOKEN_INFO_KEY + "_" + token + "_" + deviceType;
-//    }
-//}
+package com.zanxiang.sdk.service.Impl;
+
+import com.alibaba.nacos.common.utils.CollectionUtils;
+import com.alibaba.nacos.common.utils.MD5Utils;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.zanxiang.common.enums.ExpireTimeEnum;
+import com.zanxiang.common.exception.BaseException;
+import com.zanxiang.sdk.utils.RedisUtils;
+import com.zanxiang.common.text.UUID;
+import com.zanxiang.common.utils.bean.BeanUtils;
+import com.zanxiang.sdk.constant.RedisKeyConstant;
+import com.zanxiang.sdk.domain.dto.UserTokenDTO;
+import com.zanxiang.sdk.domain.entity.UserToken;
+import com.zanxiang.sdk.mapper.UserTokenMapper;
+import com.zanxiang.sdk.service.IUserTokenService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.security.NoSuchAlgorithmException;
+import java.util.List;
+
+/**
+ * @author : lingfeng
+ * @time : 2022-06-07
+ * @description : 用户token管理
+ */
+@Slf4j
+@Service
+public class UserTokenServiceImpl extends ServiceImpl<UserTokenMapper, UserToken> implements IUserTokenService {
+
+    @Autowired
+    private RedisUtils<UserToken> redisUtils;
+
+    /**
+     * 通过token设备获取token详情
+     *
+     * @param token      : 用户token
+     * @param deviceType : 设备类型
+     * @return : 返回用户token详情
+     */
+    @Override
+    public UserTokenDTO getTokenInfoByTokenDevice(String token, String deviceType) {
+        //查询缓存信息
+        String tokenInfoKey = this.getTokenInfoKey(token, deviceType);
+        UserToken userToken = redisUtils.getCache(tokenInfoKey);
+        if (userToken != null) {
+            return BeanUtils.copy(userToken, UserTokenDTO.class);
+        }
+        //缓存不存在, 查询数据库
+        userToken = super.getOne(new LambdaQueryWrapper<UserToken>()
+                .eq(UserToken::getToken, token)
+                .eq(UserToken::getDeviceType, deviceType));
+        if (userToken == null) {
+            return null;
+        }
+        //设置token详情缓存
+        redisUtils.setCache(tokenInfoKey, userToken, ExpireTimeEnum.ONE_DAY.getTime());
+        //设置用户缓存
+        String userTokenKey = this.getUserTokenKey(userToken.getUserId(), deviceType);
+        redisUtils.setCache(userTokenKey, userToken, ExpireTimeEnum.ONE_DAY.getTime());
+        //返回数据
+        return BeanUtils.copy(userToken, UserTokenDTO.class);
+    }
+
+    /**
+     * 通过用户设备获取token详情
+     *
+     * @param userId     : 用户id
+     * @param deviceType : 设备类型
+     * @return : 返回token
+     */
+    @Override
+    public UserTokenDTO getTokenInfoByUserDevice(Long userId, String deviceType) {
+        //查询缓存信息
+        String userTokenKey = this.getUserTokenKey(userId, deviceType);
+        UserToken userToken = redisUtils.getCache(userTokenKey);
+        if (userToken != null) {
+            return BeanUtils.copy(userToken, UserTokenDTO.class);
+        }
+        //缓存不存在, 查询数据库
+        userToken = super.getOne(new LambdaQueryWrapper<UserToken>()
+                .eq(UserToken::getUserId, userId)
+                .eq(UserToken::getDeviceType, deviceType));
+        if (userToken == null) {
+            return null;
+        }
+        //设置token详情缓存
+        String tokenInfoKey = this.getTokenInfoKey(userToken.getToken(), deviceType);
+        redisUtils.setCache(tokenInfoKey, userToken, ExpireTimeEnum.ONE_DAY.getTime());
+        //设置用户缓存
+        redisUtils.setCache(userTokenKey, userToken, ExpireTimeEnum.ONE_DAY.getTime());
+        //返回数据
+        return BeanUtils.copy(userToken, UserTokenDTO.class);
+    }
+
+    /**
+     * 获取用户token
+     *
+     * @param userId     : 用户id
+     * @param deviceType : 设备类型
+     * @return : 返回token
+     */
+    @Override
+    public String getUserToken(Long userId, String deviceType) {
+        //获取token
+        String token = this.createToken(userId, deviceType);
+        //查询数据库token信息
+        UserToken userToken = super.getOne(new LambdaQueryWrapper<UserToken>()
+                .eq(UserToken::getUserId, userId)
+                .eq(UserToken::getDeviceType, deviceType));
+        //不存在token数据, 直接创建
+        if (userToken == null) {
+            userToken = new UserToken(userId, token, deviceType);
+            super.save(userToken);
+        } else {
+            //梗系数据库
+            userToken.updateToken(token);
+            super.updateById(userToken);
+        }
+        //设置用户缓存
+        String userTokenKey = this.getUserTokenKey(userId, deviceType);
+        redisUtils.setCache(userTokenKey, userToken, ExpireTimeEnum.ONE_DAY.getTime());
+        //设置token详情缓存
+        String tokenInfoKey = this.getTokenInfoKey(token, deviceType);
+        redisUtils.setCache(tokenInfoKey, userToken, ExpireTimeEnum.ONE_DAY.getTime());
+        //返回token
+        return token;
+    }
+
+    /**
+     * 删除用户token
+     *
+     * @param userId : 用户id
+     */
+    @Override
+    public void deleteUserToken(Long userId) {
+        List<UserToken> userTokenList = super.list(new LambdaQueryWrapper<UserToken>()
+                .eq(UserToken::getUserId, userId));
+        if (CollectionUtils.isEmpty(userTokenList)) {
+            return;
+        }
+        userTokenList.forEach(userToken -> {
+            //根据主键删除数据库
+            super.removeById(userToken.getId());
+            //删除缓存
+            String userTokenKey = this.getUserTokenKey(userId, userToken.getDeviceType());
+            redisUtils.deleteCache(userTokenKey);
+            String tokenInfoKey = this.getTokenInfoKey(userToken.getToken(), userToken.getDeviceType());
+            redisUtils.deleteCache(tokenInfoKey);
+        });
+    }
+
+    /**
+     * 创建token
+     *
+     * @param userId     : 用户id
+     * @param deviceType : 设备类型
+     * @return : 返回token
+     */
+    private String createToken(Long userId, String deviceType) {
+        //生成随机数
+        String random = userId + deviceType + UUID.randomUUID().toString() + System.currentTimeMillis();
+        //创建token
+        try {
+            return MD5Utils.md5Hex(MD5Utils.md5Hex(random.getBytes()).getBytes());
+        } catch (NoSuchAlgorithmException e) {
+            e.printStackTrace();
+            throw new BaseException("生成token异常");
+        }
+    }
+
+    /**
+     * 拼接用户token缓存key
+     *
+     * @param userId     : 用户id
+     * @param deviceType : 设备类型
+     * @return : 返回用户token的缓存key
+     */
+    private String getUserTokenKey(Long userId, String deviceType) {
+        return RedisKeyConstant.USER_TOKEN_KEY + "_" + userId + "_" + deviceType;
+    }
+
+    /**
+     * 拼接用户token缓存key
+     *
+     * @param token      : 用户token
+     * @param deviceType : 设备类型
+     * @return : 返回用户token的缓存key
+     */
+    private String getTokenInfoKey(String token, String deviceType) {
+        return RedisKeyConstant.TOKEN_INFO_KEY + "_" + token + "_" + deviceType;
+    }
+}

+ 1 - 1
game-module/game-common-redis/src/main/java/com/zanxiang/common/redis/utils/RedisUtils.java → game-module/game-sdk/src/main/java/com/zanxiang/sdk/utils/RedisUtils.java

@@ -1,4 +1,4 @@
-package com.zanxiang.common.redis.utils;
+package com.zanxiang.sdk.utils;
 
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;

+ 11 - 0
game-module/game-sdk/src/main/resources/bootstrap.yml

@@ -31,6 +31,11 @@ spring:
         shared-dataids: application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
         max-retry: 10
 
+  #redis数据库配置
+  redis:
+    host: 118.178.187.109
+    port: 6379
+    password: zx$2020ddd
   #数据库配置
   datasource:
     driver-class-name: com.mysql.cj.jdbc.Driver
@@ -38,6 +43,12 @@ spring:
     username: root
     password: zxdev3306
 
+ali-sms:
+  accessKeyId: LTAI4G5ZxxRe4SFBua4KmMdC
+  accessKeySecret: mPPmaPVDxfMfmtrM3vsDJHTmud9SZn
+  defaultSignName:
+  defaultVerifyCodeTemplate: SMS_232080189
+
 logging:
   level:
     root: warn