Przeglądaj źródła

Merge remote-tracking branch 'origin/package' into package

Letianhua 1 rok temu
rodzic
commit
bdbfe8d3f5

+ 4 - 6
game-module/game-module-mybatis/src/main/java/com/zanxiang/game/module/mybatis/entity/GameUserRole.java

@@ -95,11 +95,6 @@ public class GameUserRole implements Serializable {
      */
     private LocalDateTime lastRechargeTime;
 
-    /**
-     * 扩展信息
-     */
-    private String ext;
-
     /**
      * 操作系统
      */
@@ -125,5 +120,8 @@ public class GameUserRole implements Serializable {
      */
     private LocalDateTime updateTime;
 
-
+    /**
+     * 角色拓展属性
+     */
+    private String extra;
 }

+ 1 - 1
game-module/game-module-sdk/src/main/java/com/zanxiang/game/module/sdk/SDKApplication.java

@@ -23,7 +23,7 @@ public class SDKApplication {
 
     public static void main(String[] args) {
         SpringApplication.run(SDKApplication.class, args);
-        System.out.println("赞象SDK服务启动成功 <壳包屏蔽省份22> ( ´・・)ノ(._.`) \n" +
+        System.out.println("赞象SDK服务启动成功 <国家属性老数据更新, 日志整理> ( ´・・)ノ(._.`) \n" +
                 " ___________ _   __\n" +
                 "/  ___|  _  \\ | / /\n" +
                 "\\ `--.| | | | |/ / \n" +

+ 82 - 3
game-module/game-module-sdk/src/main/java/com/zanxiang/game/module/sdk/config/KafkaConfig.java

@@ -1,15 +1,24 @@
 package com.zanxiang.game.module.sdk.config;
 
 import lombok.extern.slf4j.Slf4j;
-import org.apache.kafka.clients.producer.KafkaProducer;
-import org.apache.kafka.clients.producer.ProducerConfig;
+import org.apache.kafka.clients.consumer.OffsetAndMetadata;
+import org.apache.kafka.clients.producer.*;
+import org.apache.kafka.common.Metric;
+import org.apache.kafka.common.MetricName;
+import org.apache.kafka.common.PartitionInfo;
+import org.apache.kafka.common.TopicPartition;
+import org.apache.kafka.common.errors.ProducerFencedException;
 import org.apache.kafka.common.serialization.StringSerializer;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 
 import java.net.InetAddress;
+import java.time.Duration;
+import java.util.List;
+import java.util.Map;
 import java.util.Properties;
+import java.util.concurrent.Future;
 
 /**
  * @author : lingfeng
@@ -23,8 +32,14 @@ public class KafkaConfig {
     @Value("${spring.kafka.game-sdk.bootstrap-servers}")
     private String gameSdkKafkaSevers;
 
+    @Value("${server.domain}")
+    private String serverUrl;
+
     @Bean("gameSdkKafkaProducer")
-    public KafkaProducer<String, String> gameKafkaProducer() {
+    public Producer<String, String> gameKafkaProducer() {
+        if (this.serverUrl.contains("test")) {
+            return new TempKafkaProducer<>();
+        }
         String clientId = "UNKNOWN";
         try {
             clientId = InetAddress.getLocalHost().getHostAddress();
@@ -38,4 +53,68 @@ public class KafkaConfig {
         props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class);
         return new KafkaProducer<>(props);
     }
+
+    public static class TempKafkaProducer<K, V> implements Producer<K, V> {
+
+        @Override
+        public void initTransactions() {
+
+        }
+
+        @Override
+        public void beginTransaction() throws ProducerFencedException {
+
+        }
+
+        @Override
+        public void sendOffsetsToTransaction(Map<TopicPartition, OffsetAndMetadata> map, String s) throws ProducerFencedException {
+
+        }
+
+        @Override
+        public void commitTransaction() throws ProducerFencedException {
+
+        }
+
+        @Override
+        public void abortTransaction() throws ProducerFencedException {
+
+        }
+
+        @Override
+        public Future<RecordMetadata> send(ProducerRecord<K, V> producerRecord) {
+            return null;
+        }
+
+        @Override
+        public Future<RecordMetadata> send(ProducerRecord<K, V> producerRecord, Callback callback) {
+            return null;
+        }
+
+        @Override
+        public void flush() {
+
+        }
+
+        @Override
+        public List<PartitionInfo> partitionsFor(String s) {
+            return null;
+        }
+
+        @Override
+        public Map<MetricName, ? extends Metric> metrics() {
+            return null;
+        }
+
+        @Override
+        public void close() {
+
+        }
+
+        @Override
+        public void close(Duration duration) {
+
+        }
+    }
+
 }

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

@@ -32,6 +32,11 @@ public class RedisKeyConstant {
      */
     public static final String ROLE_UPDATE_KEY = RedisKeyConstant.REDIS_PREFIX + "role_update";
 
+    /**
+     * 角色信息更新
+     */
+    public static final String ROLE_LEVEL_UP = RedisKeyConstant.REDIS_PREFIX + "role_level_up_";
+
     /**
      * 小程序token
      */

+ 9 - 0
game-module/game-module-sdk/src/main/java/com/zanxiang/game/module/sdk/controller/UserController.java

@@ -47,6 +47,9 @@ public class UserController {
     @Autowired
     private IGameShellLogService gameShellLogService;
 
+    @Autowired
+    private IMsgSceneCheckService msgSceneCheckService;
+
     @ApiOperation(value = "游戏分享信息")
     @GetMapping("/share/game")
     @ApiResponses(value = {@ApiResponse(code = 200, message = "成功", response = GameShareVO.class)})
@@ -123,4 +126,10 @@ public class UserController {
         return ResultVO.ok(gameShellLogService.gameShellLogAdd(param, request));
     }
 
+    @ApiOperation(value = "敏感词检测")
+    @PostMapping("/msg/check")
+    @ApiResponses(value = {@ApiResponse(code = 200, message = "成功", response = String.class)})
+    public ResultVO<String> msgCheck(@Validated @RequestBody MsgSceneCheckParam param, @ValidLogin UserData userData) {
+        return ResultVO.ok(msgSceneCheckService.msgCheck(param, userData));
+    }
 }

+ 6 - 0
game-module/game-module-sdk/src/main/java/com/zanxiang/game/module/sdk/pojo/param/GameUserRoleUpdateParam.java

@@ -99,4 +99,10 @@ public class GameUserRoleUpdateParam {
      */
     @ApiModelProperty("游戏在线时长")
     private Long totalOnlineTime;
+
+    /**
+     * 角色拓展属性
+     */
+    @ApiModelProperty("角色拓展属性")
+    private Object extra;
 }

+ 31 - 0
game-module/game-module-sdk/src/main/java/com/zanxiang/game/module/sdk/pojo/param/MsgSceneCheckParam.java

@@ -0,0 +1,31 @@
+package com.zanxiang.game.module.sdk.pojo.param;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+
+/**
+ * @author : lingfeng
+ * @time : 2023-11-13
+ * @description : 消息检测参数
+ */
+@Data
+public class MsgSceneCheckParam {
+
+    /**
+     * 文本内容
+     */
+    @NotBlank(message = "文本内容不可为空")
+    @ApiModelProperty(notes = "文本内容")
+    private String content;
+
+    /**
+     * 场景
+     */
+    @NotNull(message = "场景值不可为空")
+    @ApiModelProperty(notes = "场景枚举值(1 资料;2 评论;3 论坛;4 社交日志)")
+    private Integer scene;
+
+}

+ 21 - 0
game-module/game-module-sdk/src/main/java/com/zanxiang/game/module/sdk/service/IMsgSceneCheckService.java

@@ -0,0 +1,21 @@
+package com.zanxiang.game.module.sdk.service;
+
+import com.zanxiang.game.module.sdk.pojo.param.MsgSceneCheckParam;
+import com.zanxiang.game.module.sdk.pojo.param.UserData;
+
+/**
+ * @author : lingfeng
+ * @time : 2023-11-13
+ * @description : 小程序安全检测
+ */
+public interface IMsgSceneCheckService {
+
+    /**
+     * 消息检测
+     *
+     * @param param    : 检测参数
+     * @param userData : 用户信息
+     * @return : 返回检测结果
+     */
+    String msgCheck(MsgSceneCheckParam param, UserData userData);
+}

+ 15 - 3
game-module/game-module-sdk/src/main/java/com/zanxiang/game/module/sdk/service/impl/GameUserRoleServiceImpl.java

@@ -19,7 +19,7 @@ import com.zanxiang.module.redis.service.IDistributedLockComponent;
 import com.zanxiang.module.util.DateUtil;
 import com.zanxiang.module.util.JsonUtil;
 import lombok.extern.slf4j.Slf4j;
-import org.apache.kafka.clients.producer.KafkaProducer;
+import org.apache.kafka.clients.producer.Producer;
 import org.apache.kafka.clients.producer.ProducerRecord;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Qualifier;
@@ -61,14 +61,16 @@ public class GameUserRoleServiceImpl extends ServiceImpl<GameUserRoleMapper, Gam
     @Value("${spring.kafka.game-sdk.gameRoleActiveTopic}")
     private String gameRoleActiveTopic;
 
+    @Value("${server.domain}")
+    private String serverUrl;
+
     @Autowired
     @Qualifier("gameSdkKafkaProducer")
-    private KafkaProducer<String, String> kafkaProducer;
+    private Producer<String, String> kafkaProducer;
 
     @Override
     @Transactional(rollbackFor = Exception.class)
     public Boolean updateUserGameRole(GameUserRoleUpdateParam param, UserData userData) {
-        log.error("上报用户信息, param : {}", JsonUtil.toString(param));
         //上报类型
         Integer dataType = param.getDataType();
         //选择服务器
@@ -99,6 +101,10 @@ public class GameUserRoleServiceImpl extends ServiceImpl<GameUserRoleMapper, Gam
         }
         //等级提升更新
         if (Objects.equals(dataType, DataTypeEnum.TYPE_LEVEL_UP.getDateType())) {
+            //更新频率限制, 20秒更新一次, 避免游戏实时战力高频上报
+            if (!distributedLockComponent.doLock(RedisKeyConstant.ROLE_LEVEL_UP + userData.getUserId(), 0L, 20L, TimeUnit.SECONDS)) {
+                return Boolean.TRUE;
+            }
             return super.update(new LambdaUpdateWrapper<GameUserRole>()
                     .set(GameUserRole::getRoleName, param.getRoleName())
                     .set(GameUserRole::getRoleLevel, param.getRoleLevel())
@@ -107,6 +113,7 @@ public class GameUserRoleServiceImpl extends ServiceImpl<GameUserRoleMapper, Gam
                     .set(param.getRoleVipLevel() != null, GameUserRole::getRoleVipLevel, param.getRoleVipLevel())
                     .set(param.getRolePower() != null, GameUserRole::getRolePower, param.getRolePower())
                     .set(GameUserRole::getUpdateTime, param.getRoleGradeUpdateTime() == null || param.getRoleGradeUpdateTime() <= 0 ? LocalDateTime.now() : DateUtil.secondToLocalDateTime(param.getRoleGradeUpdateTime()))
+                    .set(param.getExtra() != null, GameUserRole :: getExtra, JsonUtil.toString(param.getExtra()))
                     .eq(GameUserRole::getUserId, userData.getUserId())
                     .eq(GameUserRole::getGameId, userData.getGameId())
                     .eq(GameUserRole::getRoleId, param.getRoleId()));
@@ -153,6 +160,7 @@ public class GameUserRoleServiceImpl extends ServiceImpl<GameUserRoleMapper, Gam
                 .createTime(param.getRoleGradeUpdateTime() == null || param.getRoleGradeUpdateTime() <= 0 ? LocalDateTime.now() : DateUtil.secondToLocalDateTime(param.getRoleGradeUpdateTime()))
                 .updateTime(LocalDateTime.now())
                 .lastLoginTime(LocalDateTime.now())
+                .extra(param.getExtra() == null ? null : JsonUtil.toString(param.getExtra()))
                 .build();
         super.save(userRole);
         //更新玩家创角数
@@ -246,6 +254,10 @@ public class GameUserRoleServiceImpl extends ServiceImpl<GameUserRoleMapper, Gam
             userTokenService.userTokenUpdateCheck(userData);
         } catch (Exception ignored) {
         }
+        //测试环境不使用kafka
+        if (this.serverUrl.contains("test")) {
+            return Boolean.TRUE;
+        }
         //活跃提交
         Map<String, Object> activeParamMap = new HashMap<>(6);
         activeParamMap.put("userId", userData.getUserId());

+ 64 - 0
game-module/game-module-sdk/src/main/java/com/zanxiang/game/module/sdk/service/impl/MsgSceneCheckServiceImpl.java

@@ -0,0 +1,64 @@
+package com.zanxiang.game.module.sdk.service.impl;
+
+import com.zanxiang.game.module.mybatis.entity.User;
+import com.zanxiang.game.module.sdk.pojo.dto.GameAppletDTO;
+import com.zanxiang.game.module.sdk.pojo.param.MsgSceneCheckParam;
+import com.zanxiang.game.module.sdk.pojo.param.UserData;
+import com.zanxiang.game.module.sdk.service.IGameAppletService;
+import com.zanxiang.game.module.sdk.service.IMsgSceneCheckService;
+import com.zanxiang.game.module.sdk.service.IUserService;
+import com.zanxiang.game.module.sdk.service.api.WxApiService;
+import com.zanxiang.module.util.JsonUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.web.client.RestTemplate;
+import org.springframework.web.util.UriComponentsBuilder;
+
+import java.net.URI;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author : lingfeng
+ * @time : 2023-11-13
+ * @description : 小程序安全检测
+ */
+@Slf4j
+@Service
+public class MsgSceneCheckServiceImpl implements IMsgSceneCheckService {
+
+    @Autowired
+    private WxApiService wxApiService;
+
+    @Autowired
+    private IGameAppletService gameAppletService;
+
+    @Autowired
+    private IUserService userService;
+
+    @Autowired
+    private RestTemplate restTemplate;
+
+    @Override
+    public String msgCheck(MsgSceneCheckParam param, UserData userData) {
+        User user = userService.getById(userData.getUserId());
+        GameAppletDTO gameAppletDTO = gameAppletService.getByGameId(userData.getGameId());
+        String accessToken = wxApiService.getAccessToken(gameAppletDTO.getAppId(), gameAppletDTO.getAppSecret());
+        Map<String, Object> paramMap = new HashMap<>(4);
+        paramMap.put("content", param.getContent());
+        paramMap.put("version", 2);
+        paramMap.put("scene", param.getScene());
+        paramMap.put("openid", user.getOpenId());
+        URI uri = UriComponentsBuilder.fromHttpUrl("https://api.weixin.qq.com/wxa/msg_sec_check")
+                .queryParam("access_token", accessToken)
+                .build().toUri();
+        String result = null;
+        try {
+            result = restTemplate.postForObject(uri, paramMap, String.class);
+        } catch (Exception e) {
+            log.error("消息检测腾讯接口异常, param : {}, userData : {}", JsonUtil.toString(param), JsonUtil.toString(userData));
+        }
+        return result;
+    }
+}