Explorar o código

完成任务回调接口

xudm hai 2 meses
pai
achega
1476b433e4
Modificáronse 38 ficheiros con 708 adicións e 64 borrados
  1. 9 0
      pom.xml
  2. 32 0
      src/main/java/com/xs/core/common/enums/TaskCallbackLogTypeEnum.java
  3. 73 0
      src/main/java/com/xs/core/config/httpclient/HttpClientConfig.java
  4. 1 1
      src/main/java/com/xs/core/config/redis/FastJson2JsonRedisSerializer.java
  5. 1 1
      src/main/java/com/xs/core/config/redis/RedisConfig.java
  6. 12 6
      src/main/java/com/xs/core/controller/openapi/OpenApiController.java
  7. 16 0
      src/main/java/com/xs/core/mapper/task/TaskCallbackLogMapper.java
  8. 78 0
      src/main/java/com/xs/core/model/task/entity/TaskCallbackLog.java
  9. 9 1
      src/main/java/com/xs/core/model/task/entity/TaskInfo.java
  10. 7 1
      src/main/java/com/xs/core/model/task/entity/UserTaskRecord.java
  11. 1 1
      src/main/java/com/xs/core/service/Impl/RedisServiceImpl.java
  12. 35 0
      src/main/java/com/xs/core/service/Impl/task/TaskCallbackLogServiceImpl.java
  13. 74 0
      src/main/java/com/xs/core/service/Impl/task/TaskCallbackServiceImpl.java
  14. 78 21
      src/main/java/com/xs/core/service/Impl/task/TaskServiceImpl.java
  15. 8 0
      src/main/java/com/xs/core/service/Impl/user/UserServiceImpl.java
  16. 29 0
      src/main/java/com/xs/core/service/task/ITaskCallbackLogService.java
  17. 7 0
      src/main/java/com/xs/core/service/task/TaskCallbackService.java
  18. 9 0
      src/main/java/com/xs/core/service/task/TaskService.java
  19. 8 0
      src/main/java/com/xs/core/service/user/IUserService.java
  20. 67 0
      src/main/java/com/xs/core/utils/HttpClientService.java
  21. 4 4
      src/main/java/com/xs/core/utils/MyGenerator.java
  22. 23 4
      src/main/java/com/xs/core/utils/OpenApiEncryptionUtils.java
  23. 2 2
      src/main/resources/application-dev.yml
  24. 1 1
      src/main/resources/application-prod.yml
  25. 15 0
      src/main/resources/mapper/TaskCallbackLogMapper.xml
  26. 31 10
      src/main/resources/mapper/TaskInfoMapper.xml
  27. 1 0
      src/main/resources/mapper/UserTaskRecordMapper.xml
  28. 7 1
      src/main/resources/messages/messages_en.properties
  29. 7 1
      src/main/resources/messages/messages_es.properties
  30. 7 1
      src/main/resources/messages/messages_fa.properties
  31. 7 1
      src/main/resources/messages/messages_ja.properties
  32. 7 1
      src/main/resources/messages/messages_ko.properties
  33. 7 1
      src/main/resources/messages/messages_pt.properties
  34. 7 1
      src/main/resources/messages/messages_ru.properties
  35. 7 1
      src/main/resources/messages/messages_th.properties
  36. 7 1
      src/main/resources/messages/messages_vi.properties
  37. 7 1
      src/main/resources/messages/messages_zh_CN.properties
  38. 7 1
      src/main/resources/messages/messages_zh_TW.properties

+ 9 - 0
pom.xml

@@ -217,6 +217,13 @@
             </exclusions>
         </dependency>
 
+        <!-- httpclient       -->
+        <dependency>
+            <groupId>org.apache.httpcomponents.client5</groupId>
+            <artifactId>httpclient5</artifactId>
+            <version>5.1.4</version>
+        </dependency>
+
         <dependency>
             <groupId>org.bouncycastle</groupId>
             <artifactId>bcprov-jdk15to18</artifactId>
@@ -242,6 +249,8 @@
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-actuator</artifactId>
         </dependency>
+
+
     </dependencies>
 
     <build>

+ 32 - 0
src/main/java/com/xs/core/common/enums/TaskCallbackLogTypeEnum.java

@@ -0,0 +1,32 @@
+package com.xs.core.common.enums;
+
+/**
+ * 任务回调日志类型枚举
+ */
+public enum TaskCallbackLogTypeEnum {
+    START("start", "开始"),
+    CALLBACK("callback", "回调");
+    private String code;
+    private String desc;
+
+    TaskCallbackLogTypeEnum(String code, String desc) {
+        this.code = code;
+        this.desc = desc;
+    }
+
+    public String getCode() {
+        return code;
+    }
+
+    public void setCode(String code) {
+        this.code = code;
+    }
+
+    public String getDesc() {
+        return desc;
+    }
+
+    public void setDesc(String desc) {
+        this.desc = desc;
+    }
+}

+ 73 - 0
src/main/java/com/xs/core/config/httpclient/HttpClientConfig.java

@@ -0,0 +1,73 @@
+package com.xs.core.config.httpclient;
+
+import org.apache.hc.client5.http.config.RequestConfig;
+import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
+import org.apache.hc.client5.http.impl.classic.HttpClients;
+import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager;
+import org.apache.hc.client5.http.socket.ConnectionSocketFactory;
+import org.apache.hc.client5.http.socket.PlainConnectionSocketFactory;
+import org.apache.hc.client5.http.ssl.NoopHostnameVerifier;
+import org.apache.hc.client5.http.ssl.SSLConnectionSocketFactory;
+import org.apache.hc.core5.http.config.Registry;
+import org.apache.hc.core5.http.config.RegistryBuilder;
+import org.apache.hc.core5.ssl.SSLContexts;
+import org.apache.hc.core5.util.Timeout;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Scope;
+
+import javax.net.ssl.SSLContext;
+import java.security.KeyManagementException;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+
+@Configuration
+public class HttpClientConfig {
+    @Bean
+    @Scope("prototype")//设定多例对象
+    public CloseableHttpClient httpClient(@Qualifier("httpClientConnectionManager") PoolingHttpClientConnectionManager connectionManager) {
+        // 创建并返回一个自定义配置的 CloseableHttpClient 实例
+        return HttpClients.custom()
+                // 设置连接管理器,管理连接池
+                .setConnectionManager(connectionManager)
+                // 设置默认请求配置
+                .setDefaultRequestConfig(
+                        RequestConfig.custom()
+                                // 设置连接超时时间为 30 秒
+                                .setConnectTimeout(Timeout.ofSeconds(30))
+                                // 设置响应超时时间为 30 秒
+                                .setResponseTimeout(Timeout.ofSeconds(30))
+                                .build())
+                .build();
+    }
+
+    /**
+     * 连接池
+     *
+     * @return
+     */
+    @Bean("httpClientConnectionManager")
+    public PoolingHttpClientConnectionManager connectionManager() {
+        try {
+            // 创建一个信任所有证书的自定义 SSLContext
+            SSLContext sslContext = SSLContexts.custom().loadTrustMaterial(null, (chain, authType) -> true).build();
+
+            // 创建 SSLConnectionSocketFactory,使用 NoopHostnameVerifier 来跳过主机名验证
+            SSLConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(sslContext, new String[]{"TLSv1", "TLSv1.1", "TLSv1.2"}, null, NoopHostnameVerifier.INSTANCE);
+            // 注册 HTTP 和 HTTPS 套接字工厂
+            Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
+                    .register("http", PlainConnectionSocketFactory.INSTANCE)
+                    .register("https", sslSocketFactory)
+                    .build();
+
+            PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(registry);
+            connectionManager.setMaxTotal(100);
+            connectionManager.setDefaultMaxPerRoute(20);
+            return connectionManager;
+        } catch (KeyManagementException | NoSuchAlgorithmException | KeyStoreException e) {
+            throw new RuntimeException("创建连接管理器时出错", e);
+        }
+    }
+
+}

+ 1 - 1
src/main/java/com/xs/core/config/FastJson2JsonRedisSerializer.java → src/main/java/com/xs/core/config/redis/FastJson2JsonRedisSerializer.java

@@ -1,5 +1,5 @@
 
-package com.xs.core.config;
+package com.xs.core.config.redis;
 
 import com.alibaba.fastjson2.JSON;
 import com.alibaba.fastjson2.JSONFactory;

+ 1 - 1
src/main/java/com/xs/core/config/RedisConfig.java → src/main/java/com/xs/core/config/redis/RedisConfig.java

@@ -1,4 +1,4 @@
-package com.xs.core.config;
+package com.xs.core.config.redis;
 
 import org.redisson.Redisson;
 import org.redisson.api.RedissonClient;

+ 12 - 6
src/main/java/com/xs/core/controller/openapi/OpenApiController.java

@@ -1,10 +1,13 @@
 package com.xs.core.controller.openapi;
 
-import com.alibaba.fastjson2.JSON;
 import com.alibaba.fastjson2.JSONObject;
 import com.xs.core.common.annotation.EntryIgnore;
+import com.xs.core.model.ResponseResult;
+import com.xs.core.service.task.TaskCallbackService;
+import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.tags.Tag;
 import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
@@ -16,10 +19,13 @@ import org.springframework.web.bind.annotation.RestController;
 @Tag(description = "开放接口", name = "开放接口")
 @EntryIgnore
 public class OpenApiController {
-    @PostMapping("/test")
-    public JSONObject test(@RequestBody JSONObject jsonObject) {
-        String jsonString = JSON.toJSONString(jsonObject);
-        log.info("jsonString:{}", jsonString);
-        return jsonObject;
+    @Autowired
+    private TaskCallbackService callbackService;
+
+    @Operation(summary = "任务回调", description = "任务回调")
+    @PostMapping("/handleTaskCallback")
+    public ResponseResult<?> handleTaskCallback(@RequestBody JSONObject jsonObject) {
+        callbackService.handleTaskCallback(jsonObject);
+        return ResponseResult.success();
     }
 }

+ 16 - 0
src/main/java/com/xs/core/mapper/task/TaskCallbackLogMapper.java

@@ -0,0 +1,16 @@
+package com.xs.core.mapper.task;
+
+import com.xs.core.model.task.entity.TaskCallbackLog;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+ * <p>
+ * 任务回调日志 Mapper 接口
+ * </p>
+ *
+ * @author xudm
+ * @since 2024-12-30
+ */
+public interface TaskCallbackLogMapper extends BaseMapper<TaskCallbackLog> {
+
+}

+ 78 - 0
src/main/java/com/xs/core/model/task/entity/TaskCallbackLog.java

@@ -0,0 +1,78 @@
+package com.xs.core.model.task.entity;
+
+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 com.baomidou.mybatisplus.extension.activerecord.Model;
+import java.io.Serializable;
+import java.time.LocalDateTime;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * <p>
+ * 任务回调日志
+ * </p>
+ *
+ * @author xudm
+ * @since 2024-12-30
+ */
+@Getter
+@Setter
+@TableName("b_task_callback_log")
+public class TaskCallbackLog extends Model<TaskCallbackLog> {
+
+    /**
+     * 主键
+     */
+    @TableId(value = "id", type = IdType.ASSIGN_ID)
+    private String id;
+
+    /**
+     * 任务id
+     */
+    @TableField("task_id")
+    private String taskId;
+
+    /**
+     * 用户id
+     */
+    @TableField("user_id")
+    private String userId;
+
+    /**
+     * 任务地址
+     */
+    @TableField("task_link")
+    private String taskLink;
+
+    /**
+     * 入参
+     */
+    @TableField("input_param")
+    private String inputParam;
+
+    /**
+     * 结果
+     */
+    @TableField("output_param")
+    private String outputParam;
+
+    /**
+     * 日志类型 【start 开始,callback 回调】
+     */
+    @TableField("log_type")
+    private String logType;
+
+    /**
+     * 操作时间
+     */
+    @TableField("operation_time")
+    private LocalDateTime operationTime;
+
+    @Override
+    public Serializable pkVal() {
+        return this.id;
+    }
+}

+ 9 - 1
src/main/java/com/xs/core/model/task/entity/TaskInfo.java

@@ -5,8 +5,10 @@ import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableName;
 import com.baomidou.mybatisplus.extension.activerecord.Model;
+
 import java.io.Serializable;
 import java.time.LocalDateTime;
+
 import lombok.Getter;
 import lombok.Setter;
 
@@ -27,7 +29,7 @@ public class TaskInfo extends Model<TaskInfo> {
      * id
      */
     @TableId(value = "id", type = IdType.ASSIGN_ID)
-    private Long id;
+    private String id;
 
     /**
      * 任务名称
@@ -107,6 +109,12 @@ public class TaskInfo extends Model<TaskInfo> {
     @TableField("task_link")
     private String taskLink;
 
+    /**
+     * 任务接受接口链接
+     */
+    @TableField("task_accept_api_link")
+    private String taskAcceptApiLink;
+
     /**
      * 任务分类编码
      */

+ 7 - 1
src/main/java/com/xs/core/model/task/entity/UserTaskRecord.java

@@ -44,7 +44,7 @@ public class UserTaskRecord extends Model<UserTaskRecord> {
     private String taskId;
 
     /**
-     * 任务状态: 0-未开始, 1-进行中, 2-待领取 3-已领取
+     * 任务状态: 0-未开始, 1-进行中, 2 已领取
      */
     @TableField("status")
     private Integer status;
@@ -67,6 +67,12 @@ public class UserTaskRecord extends Model<UserTaskRecord> {
     @TableField("reward_amount")
     private Integer rewardAmount;
 
+    /**
+     * 回调次数
+     */
+    @TableField("callback_num")
+    private Integer callbackNum;
+
     /**
      * 创建时间
      */

+ 1 - 1
src/main/java/com/xs/core/service/Impl/RedisServiceImpl.java

@@ -1,7 +1,7 @@
 package com.xs.core.service.Impl;
 
 import cn.hutool.json.JSONUtil;
-import com.xs.core.config.FastJson2JsonRedisSerializer;
+import com.xs.core.config.redis.FastJson2JsonRedisSerializer;
 import com.xs.core.service.redis.RedisService;
 import jakarta.annotation.Resource;
 import org.springframework.dao.DataAccessException;

+ 35 - 0
src/main/java/com/xs/core/service/Impl/task/TaskCallbackLogServiceImpl.java

@@ -0,0 +1,35 @@
+package com.xs.core.service.Impl.task;
+
+import com.xs.core.common.enums.TaskCallbackLogTypeEnum;
+import com.xs.core.model.task.entity.TaskCallbackLog;
+import com.xs.core.mapper.task.TaskCallbackLogMapper;
+import com.xs.core.service.task.ITaskCallbackLogService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+
+import java.time.LocalDateTime;
+
+/**
+ * <p>
+ * 任务回调日志 服务实现类
+ * </p>
+ *
+ * @author xudm
+ * @since 2024-12-30
+ */
+@Service
+public class TaskCallbackLogServiceImpl extends ServiceImpl<TaskCallbackLogMapper, TaskCallbackLog> implements ITaskCallbackLogService {
+
+    @Override
+    public void saveCallbackLog(String taskId, Long userId, String taskAcceptApiLink, String inputParam, String outputParam, TaskCallbackLogTypeEnum type) {
+        TaskCallbackLog taskCallbackLog = new TaskCallbackLog();
+        taskCallbackLog.setTaskId(taskId);
+        taskCallbackLog.setUserId(userId + "");
+        taskCallbackLog.setTaskLink(taskAcceptApiLink);
+        taskCallbackLog.setInputParam(inputParam);
+        taskCallbackLog.setOutputParam(outputParam);
+        taskCallbackLog.setLogType(type.getCode());
+        taskCallbackLog.setOperationTime(LocalDateTime.now());
+        save(taskCallbackLog);
+    }
+}

+ 74 - 0
src/main/java/com/xs/core/service/Impl/task/TaskCallbackServiceImpl.java

@@ -0,0 +1,74 @@
+package com.xs.core.service.Impl.task;
+
+import com.alibaba.fastjson2.JSON;
+import com.alibaba.fastjson2.JSONObject;
+import com.xs.core.common.enums.CoinTransactionCategoryEnum;
+import com.xs.core.common.enums.CoinTransactionTypeEnum;
+import com.xs.core.common.enums.TaskCallbackLogTypeEnum;
+import com.xs.core.common.validation.CheckUtils;
+import com.xs.core.model.ResponseResult;
+import com.xs.core.model.task.entity.TaskInfo;
+import com.xs.core.model.task.entity.UserTaskRecord;
+import com.xs.core.service.task.ITaskCallbackLogService;
+import com.xs.core.service.task.ITaskInfoService;
+import com.xs.core.service.task.IUserTaskRecordService;
+import com.xs.core.service.task.TaskCallbackService;
+import com.xs.core.service.user.IUserService;
+import com.xs.core.service.wallet.IUserWalletService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+import java.util.concurrent.CompletableFuture;
+
+@Service
+public class TaskCallbackServiceImpl implements TaskCallbackService {
+
+    @Autowired
+    private IUserTaskRecordService taskRecordService;
+
+    @Autowired
+    private ITaskCallbackLogService taskCallbackLogService;
+
+    @Autowired
+    private ITaskInfoService taskInfoService;
+
+    @Autowired
+    private IUserService userService;
+
+    @Autowired
+    private IUserWalletService walletService;
+
+    @Override
+    @Transactional
+    public void handleTaskCallback(JSONObject jsonObject) {
+        String taskId = jsonObject.getString("taskId");
+        String userId = jsonObject.getString("userId");
+        TaskInfo taskInfo = taskInfoService.getById(taskId);
+        CheckUtils.throwIfNull(taskInfo, "error.task.handle.not.exist");
+        boolean exist = userService.checkUserExist(Long.valueOf(userId));
+        CheckUtils.throwIf(!exist, "error.user.not.exist");
+        //查询任务完成情况
+        UserTaskRecord record = taskRecordService.getByTaskId(taskId, Long.valueOf(userId));
+        if (record != null) {
+            //说明任务已经开始 根据任务状态进行处理
+            Integer status = record.getStatus();
+            if (status == 1) {
+                //说明任务已经已经开始 进入下一步
+                record.setStatus(2);
+                record.setCallbackNum(1);
+                record.setUpdateTime(LocalDateTime.now());
+                record.setCompleteTime(LocalDateTime.now());
+                taskRecordService.updateById(record);
+                //领取奖励
+                walletService.coinTransaction(CoinTransactionTypeEnum.ADD, CoinTransactionCategoryEnum.TASK_REWARDS, "任务奖励", "任务奖励", new BigDecimal(record.getRewardAmount()), Long.valueOf(userId));
+                CompletableFuture.runAsync(() -> {
+                    // 保存回调日志
+                    taskCallbackLogService.saveCallbackLog(taskId, Long.valueOf(userId), taskInfo.getTaskAcceptApiLink(), jsonObject.toJSONString(), JSON.toJSONString(ResponseResult.success()), TaskCallbackLogTypeEnum.CALLBACK);
+                });
+            }
+        }
+    }
+}

+ 78 - 21
src/main/java/com/xs/core/service/Impl/task/TaskServiceImpl.java

@@ -1,19 +1,27 @@
 package com.xs.core.service.Impl.task;
 
 import cn.hutool.core.util.ObjUtil;
+import com.alibaba.fastjson2.JSON;
+import com.alibaba.fastjson2.JSONObject;
 import com.xs.core.common.content.UserContext;
 import com.xs.core.common.content.UserContextHolder;
 import com.xs.core.common.enums.CoinTransactionCategoryEnum;
 import com.xs.core.common.enums.CoinTransactionTypeEnum;
+import com.xs.core.common.enums.TaskCallbackLogTypeEnum;
 import com.xs.core.common.validation.CheckUtils;
 import com.xs.core.model.task.entity.TaskInfo;
 import com.xs.core.model.task.entity.UserTaskRecord;
 import com.xs.core.model.task.req.TaskInfoReq;
 import com.xs.core.model.task.resp.TaskInfoResp;
+import com.xs.core.service.task.ITaskCallbackLogService;
 import com.xs.core.service.task.ITaskInfoService;
 import com.xs.core.service.task.IUserTaskRecordService;
 import com.xs.core.service.task.TaskService;
 import com.xs.core.service.wallet.IUserWalletService;
+import com.xs.core.utils.HttpClientService;
+import com.xs.core.utils.OpenApiEncryptionUtils;
+import com.xs.core.utils.SecurityUtil;
+import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
@@ -21,8 +29,10 @@ import org.springframework.transaction.annotation.Transactional;
 import java.math.BigDecimal;
 import java.time.LocalDateTime;
 import java.util.List;
+import java.util.concurrent.CompletableFuture;
 
 @Service
+@Slf4j
 public class TaskServiceImpl implements TaskService {
     @Autowired
     private ITaskInfoService taskInfoService;
@@ -33,6 +43,12 @@ public class TaskServiceImpl implements TaskService {
     @Autowired
     private IUserWalletService walletService;
 
+    @Autowired
+    private HttpClientService httpClientService;
+
+    @Autowired
+    private ITaskCallbackLogService taskCallbackLogService;
+
 
     @Override
     public List<TaskInfoResp> getTaskInfoList(TaskInfoReq req) {
@@ -44,32 +60,73 @@ public class TaskServiceImpl implements TaskService {
     @Override
     @Transactional
     public void handleTask(TaskInfoReq req, Long userId) {
-        CheckUtils.throwIfNull(req, "error.task.handle.id.is.null");
+        CheckUtils.throwIfBlank(req.getTaskId(), "error.task.handle.id.is.null");
         TaskInfo taskInfo = taskInfoService.getById(req.getTaskId());
         CheckUtils.throwIfNull(taskInfo, "error.task.handle.not.exist");
-        //查询处理记录
+        String categoryCode = taskInfo.getCategoryCode();
+        //查询任务完成情况
         UserTaskRecord record = taskRecordService.getByTaskId(req.getTaskId(), userId);
-        if (ObjUtil.isNull(record)) {
-            //说明任务还没开始 添加任务记录
-            UserTaskRecord newRecord = new UserTaskRecord();
-            newRecord.setTaskId(req.getTaskId());
-            newRecord.setUserId(userId);
-            newRecord.setStatus(1);
-            newRecord.setCreateTime(LocalDateTime.now());
-            newRecord.setStartTime(LocalDateTime.now());
-            newRecord.setRewardAmount(taskInfo.getGoldCoin());
-            taskRecordService.save(newRecord);
+        if (categoryCode.equals("2")) {
+            //说明是回调任务
+            if (ObjUtil.isNull(record)) {
+                //说明任务还没开始 添加任务记录
+                UserTaskRecord newRecord = new UserTaskRecord();
+                newRecord.setTaskId(req.getTaskId());
+                newRecord.setUserId(userId);
+                newRecord.setStatus(1);
+                newRecord.setCreateTime(LocalDateTime.now());
+                newRecord.setStartTime(LocalDateTime.now());
+                newRecord.setRewardAmount(taskInfo.getGoldCoin());
+                taskRecordService.save(newRecord);
+                // 通知任务开始
+                startTaskNotification(taskInfo, userId);
+            }
         } else {
-            //说明任务已经开始 根据任务状态进行处理
-            Integer status = record.getStatus();
-            if (status == 1) {
-                //说明任务已经已经开始 进入下一步
-                record.setStatus(2);
-                record.setUpdateTime(LocalDateTime.now());
-                taskRecordService.updateById(record);
-                //领取奖励
-                walletService.coinTransaction(CoinTransactionTypeEnum.ADD, CoinTransactionCategoryEnum.TASK_REWARDS, "任务奖励", "任务奖励", new BigDecimal(record.getRewardAmount()), userId);
+            //说明是普通任务
+            if (ObjUtil.isNull(record)) {
+                //说明任务还没开始 添加任务记录
+                UserTaskRecord newRecord = new UserTaskRecord();
+                newRecord.setTaskId(req.getTaskId());
+                newRecord.setUserId(userId);
+                newRecord.setStatus(1);
+                newRecord.setCreateTime(LocalDateTime.now());
+                newRecord.setStartTime(LocalDateTime.now());
+                newRecord.setRewardAmount(taskInfo.getGoldCoin());
+                taskRecordService.save(newRecord);
+            } else {
+                //说明任务已经开始 根据任务状态进行处理
+                Integer status = record.getStatus();
+                if (status == 1) {
+                    //说明任务已经已经开始 进入下一步
+                    record.setStatus(2);
+                    record.setUpdateTime(LocalDateTime.now());
+                    record.setCompleteTime(LocalDateTime.now());
+                    taskRecordService.updateById(record);
+                    //领取奖励
+                    walletService.coinTransaction(CoinTransactionTypeEnum.ADD, CoinTransactionCategoryEnum.TASK_REWARDS, "任务奖励", "任务奖励", new BigDecimal(record.getRewardAmount()), userId);
+                }
             }
         }
     }
+
+    @Override
+    public void startTaskNotification(TaskInfo taskInfo, Long userId) {
+        // 通知任务开始
+        // 调用第三方接口通知第三方任务开始
+        String taskAcceptApiLink = taskInfo.getTaskAcceptApiLink();
+        CheckUtils.throwIfBlank(taskAcceptApiLink, "error.task.accept.api.link.is.null");
+        String taskId = taskInfo.getId();
+
+        JSONObject jsonObject = new JSONObject();
+        jsonObject.put("taskId", taskId);
+        jsonObject.put("userId", userId + "");
+        JSONObject entry = new JSONObject();
+        String jsonString = JSON.toJSONString(jsonObject);
+        String aesEncrypt = OpenApiEncryptionUtils.aesEncrypt(jsonString);
+        entry.put("encryptData", aesEncrypt);
+        entry.put("identifying", SecurityUtil.getSign(aesEncrypt));
+        String postJson = httpClientService.postJson(taskAcceptApiLink, JSON.toJSONString(entry), null);
+        //记录回调日志
+        CompletableFuture.runAsync(() -> taskCallbackLogService.saveCallbackLog(taskId, userId, taskAcceptApiLink, jsonString, postJson, TaskCallbackLogTypeEnum.START));
+    }
 }

+ 8 - 0
src/main/java/com/xs/core/service/Impl/user/UserServiceImpl.java

@@ -80,6 +80,14 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IU
         return count(queryWrapper);
     }
 
+    @Override
+    public boolean checkUserExist(Long aLong) {
+        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
+        queryWrapper.eq(User::getId, aLong);
+        User user = getOne(queryWrapper);
+        return ObjUtil.isNotNull(user);
+    }
+
     @Override
     @Transactional
     public User registerToSys(AppLoginReq loginReq) {

+ 29 - 0
src/main/java/com/xs/core/service/task/ITaskCallbackLogService.java

@@ -0,0 +1,29 @@
+package com.xs.core.service.task;
+
+import com.xs.core.common.enums.TaskCallbackLogTypeEnum;
+import com.xs.core.model.task.entity.TaskCallbackLog;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * <p>
+ * 任务回调日志 服务类
+ * </p>
+ *
+ * @author xudm
+ * @since 2024-12-30
+ */
+public interface ITaskCallbackLogService extends IService<TaskCallbackLog> {
+
+    /**
+     * 保存回调日志
+     *
+     * @param taskId            任务id
+     * @param userId            用户id
+     * @param taskAcceptApiLink 任务地址
+     * @param inputParam        入参
+     * @param outputParam       结果
+     * @param type              类型
+     */
+    void saveCallbackLog(String taskId, Long userId, String taskAcceptApiLink, String inputParam, String outputParam, TaskCallbackLogTypeEnum type);
+
+}

+ 7 - 0
src/main/java/com/xs/core/service/task/TaskCallbackService.java

@@ -0,0 +1,7 @@
+package com.xs.core.service.task;
+
+import com.alibaba.fastjson2.JSONObject;
+
+public interface TaskCallbackService {
+    void handleTaskCallback(JSONObject jsonObject);
+}

+ 9 - 0
src/main/java/com/xs/core/service/task/TaskService.java

@@ -1,5 +1,6 @@
 package com.xs.core.service.task;
 
+import com.xs.core.model.task.entity.TaskInfo;
 import com.xs.core.model.task.req.TaskInfoReq;
 import com.xs.core.model.task.resp.TaskInfoResp;
 
@@ -20,4 +21,12 @@ public interface TaskService {
      * @param id  任务id
      */
     void handleTask(TaskInfoReq req, Long id);
+
+    /**
+     * 开始任务通知 调用第三方接口通知第三方任务开始
+     *
+     * @param taskInfo 请求参数
+     * @param id  任务id
+     */
+    void startTaskNotification(TaskInfo taskInfo, Long id);
 }

+ 8 - 0
src/main/java/com/xs/core/service/user/IUserService.java

@@ -52,4 +52,12 @@ public interface IUserService extends IService<User> {
      * @return
      */
     User registerToSys(AppLoginReq loginReq);
+
+    /**
+     * 检查用户是否存在
+     *
+     * @param aLong
+     * @return
+     */
+    boolean checkUserExist(Long aLong);
 }

+ 67 - 0
src/main/java/com/xs/core/utils/HttpClientService.java

@@ -0,0 +1,67 @@
+package com.xs.core.utils;
+
+import cn.hutool.core.text.UnicodeUtil;
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.hc.client5.http.classic.methods.HttpGet;
+import org.apache.hc.client5.http.classic.methods.HttpPost;
+import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
+import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
+import org.apache.hc.core5.http.ContentType;
+import org.apache.hc.core5.http.HttpStatus;
+import org.apache.hc.core5.http.ParseException;
+import org.apache.hc.core5.http.io.entity.EntityUtils;
+import org.apache.hc.core5.http.io.entity.StringEntity;
+import org.springframework.stereotype.Service;
+
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.util.Map;
+
+@Service
+@Slf4j
+@AllArgsConstructor
+public class HttpClientService {
+    private final CloseableHttpClient httpClient;
+
+    public String sendGet(String url, Map<String, String> headers) {
+        HttpGet request = new HttpGet(url);
+        String result = null;
+        if (headers != null) {
+            headers.forEach(request::addHeader);
+        }
+        try (CloseableHttpResponse response = httpClient.execute(request)) {
+            result = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
+        } catch (IOException | ParseException e) {
+            log.error("sendGetRequest error", e);
+        }
+        return result;
+    }
+
+    /**
+     * 发送 post 请求
+     *
+     * @param url         请求地址
+     * @param jsonPayload 请求体
+     * @return 请求结果
+     */
+    public String postJson(String url, String jsonPayload, Map<String, String> headers) {
+        HttpPost request = new HttpPost(url);
+        log.info("sendPostRequest url: {}, jsonPayload: {}", url, jsonPayload);
+        if (headers != null) {
+            headers.forEach(request::addHeader);
+        }
+        String result = null;
+        request.setEntity(new StringEntity(jsonPayload, ContentType.APPLICATION_JSON));
+        try (CloseableHttpResponse response = httpClient.execute(request)) {
+            if (response.getCode() == HttpStatus.SC_OK) {
+                result = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
+                // 解码响应结果
+                log.info("sendPostRequest result: {}", UnicodeUtil.toString(result));
+            }
+        } catch (IOException | ParseException e) {
+            log.error("sendPostRequest error", e);
+        }
+        return result;
+    }
+}

+ 4 - 4
src/main/java/com/xs/core/utils/MyGenerator.java

@@ -25,7 +25,7 @@ import java.util.Map;
 public class MyGenerator {
 
     //数据库连接信息
-    static String url = "jdbc:mysql://192.168.241.132:3306/continew?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai",
+    static String url = "jdbc:mysql://192.168.241.133:3306/continew?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai",
             username = "continew",
             password = "continew123456";
 
@@ -57,7 +57,7 @@ public class MyGenerator {
 
     public static void main(String[] args) {
         // 项目名 例如app  web
-        generatorByBusinessModule("log", new String[]{"b_sys_app_log"});
+        generatorByBusinessModule("task", new String[]{"b_task_callback_log"});
     }
 
     /**
@@ -98,10 +98,10 @@ public class MyGenerator {
                         return DbColumnType.INTEGER;
                     }
                     if (typeCode == Types.BIGINT) {
-                        return DbColumnType.LONG;
+                        return DbColumnType.STRING;
                     }
                     if (typeCode == Types.TINYINT) {
-                        return DbColumnType.BOOLEAN;
+                        return DbColumnType.INTEGER;
                     }
                     return typeRegistry.getColumnType(metaInfo);
 

+ 23 - 4
src/main/java/com/xs/core/utils/OpenApiEncryptionUtils.java

@@ -6,6 +6,8 @@ import cn.hutool.crypto.SecureUtil;
 import cn.hutool.crypto.asymmetric.KeyType;
 import cn.hutool.crypto.asymmetric.RSA;
 import cn.hutool.crypto.symmetric.AES;
+import com.alibaba.fastjson2.JSON;
+import com.alibaba.fastjson2.JSONObject;
 import org.apache.commons.lang3.StringUtils;
 
 import java.util.HashMap;
@@ -101,7 +103,7 @@ public class OpenApiEncryptionUtils {
      * @return 加密后的数据
      */
     public static String aesEncrypt(String data) {
-        return aes.encryptHex(data);
+        return aes.encryptBase64(data);
     }
 
     /**
@@ -155,9 +157,26 @@ public class OpenApiEncryptionUtils {
         // 加密为16进制表示
 //        String encryptHex = aes.encryptHex(content);
 //        System.out.println(encryptHex);
-        String encryptHex = "a7d2a41eb3637c54d91fbadd287d18907a46d84cd7694572f6e1ac84f980db949fd49eb8c1f975e279c1e845720f18521e8d5b9d914a83903757ab60b1c8d923e853cf4cdd3e83e7e171799ba1e48313423fac8bba682822d02b06643eeb0cc52daedb7df9d4aa8f215761be59aca92f36dc85ad2a49f781057d6b8faec0f5aed8e8698e41cfdaadbc264511a0e337933730ca5180c2d2361915650898f7ef46";
-        String decryptStr = aes.decryptStr(encryptHex);
-        System.out.println(decryptStr);
+//        String encryptHex = "2xhEy/BFb4S9VjbesIz4RiIfMJb4icTermB4rb18iJHrsan9DC+viVPVDlUYC79T+OSoIPVUa0ih1KQrg/iaWZGijL4VETckTX2d+F1qjTSpaSb2iPPvWDEAyEbfRLbBOru4KuvgtE0gl/xnfmKx+pmxyWGC3yGMxOxt/hIW4aY=";
+        JSONObject basicData = new JSONObject();
+        basicData.put("timeStamp", 1735286552000L);
+        basicData.put("messageId", "94ddc40b-71e9-4f06-8de3-3c0b6638b3c8");
+
+        JSONObject bizData = new JSONObject();
+        basicData.put("taskId", "11110222");
+        basicData.put("userId", "661872378673905665");
+
+        JSONObject jsonObject = new JSONObject();
+        jsonObject.put("basicData", basicData);
+        jsonObject.put("bizData", bizData);
+        String jsonString = JSON.toJSONString(jsonObject);
+
+        String encryptBase64 = aes.encryptBase64(jsonString);
+        String sign = SecurityUtil.getSign(encryptBase64);
+//        String aesEncrypt = aes.encryptBase64(decryptStr);
+//        System.out.println(aesEncrypt);
+        System.out.println(encryptBase64);
+        System.out.println(sign);
 
     }
 }

+ 2 - 2
src/main/resources/application-dev.yml

@@ -138,7 +138,7 @@ sa-token:
 
 # 配置请求是否加密
 encryption:
-  isEncryption: false
+  isEncryption: true
   requestPrivateKey: 14FDF4948E60F856524FBB1175E83716558B8CBF71A68318875F506B9C6D2A4A
   requestPublicKey: 04F36CD10986CE214D0E5C540C30E0552DC8499B64E5B2709245D03BF2CADAA0CCA3C2BC2C8DB511012A50FAA1E43FCD4B8ABC521418EAB2D96F0075AD940EB25F
   responsePrivateKey: 00C83135E19EBD958593091F42A3442DE3D03D975A5DBD4CE19F85C9FBF2D364B7
@@ -156,7 +156,7 @@ xssFilter:
 # 接口日志配置
 interfaceLog:
   # 是否开启接口日志
-  openInterfaceLog: false
+  openInterfaceLog: true
 
 # openapi
 openapi:

+ 1 - 1
src/main/resources/application-prod.yml

@@ -138,7 +138,7 @@ sa-token:
 
 # 配置请求是否加密
 encryption:
-  isEncryption: false
+  isEncryption: true
   requestPrivateKey: 14FDF4948E60F856524FBB1175E83716558B8CBF71A68318875F506B9C6D2A4A
   requestPublicKey: 04F36CD10986CE214D0E5C540C30E0552DC8499B64E5B2709245D03BF2CADAA0CCA3C2BC2C8DB511012A50FAA1E43FCD4B8ABC521418EAB2D96F0075AD940EB25F
   responsePrivateKey: 00C83135E19EBD958593091F42A3442DE3D03D975A5DBD4CE19F85C9FBF2D364B7

+ 15 - 0
src/main/resources/mapper/TaskCallbackLogMapper.xml

@@ -0,0 +1,15 @@
+<?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.xs.core.mapper.task.TaskCallbackLogMapper">
+    <!-- 通用查询映射结果 -->
+    <resultMap id="BaseResultMap" type="com.xs.core.model.task.entity.TaskCallbackLog">
+        <id column="id" property="id"/>
+        <result column="task_id" property="taskId"/>
+        <result column="user_id" property="userId"/>
+        <result column="task_link" property="taskLink"/>
+        <result column="input_param" property="inputParam"/>
+        <result column="output_param" property="outputParam"/>
+        <result column="log_type" property="logType"/>
+        <result column="operation_time" property="operationTime"/>
+    </resultMap>
+</mapper>

+ 31 - 10
src/main/resources/mapper/TaskInfoMapper.xml

@@ -17,6 +17,7 @@
         <result column="instruction" property="instruction"/>
         <result column="task_icon" property="taskIcon"/>
         <result column="task_link" property="taskLink"/>
+        <result column="task_accept_api_link" property="taskAcceptApiLink"/>
         <result column="category_code" property="categoryCode"/>
         <result column="status" property="status"/>
         <result column="gold_coin" property="goldCoin"/>
@@ -44,16 +45,36 @@
         SELECT
         ti.id,
         <choose>
-            <when test="userLang == 'ja'">ti.name_ja</when>
-            <when test="userLang == 'ko'">ti.name_ko</when>
-            <when test="userLang == 'th'">ti.name_th</when>
-            <when test="userLang == 'vi'">ti.name_vi</when>
-            <when test="userLang == 'ru'">ti.name_ru</when>
-            <when test="userLang == 'en'">ti.name_en</when>
-            <when test="userLang == 'pt'">ti.name_pt</when>
-            <when test="userLang == 'fa'">ti.name_fa</when>
-            <when test="userLang == 'es'">ti.name_es</when>
-            <otherwise>ti.name</otherwise>
+            <when test="userLang == 'ja'">
+                ti.name_ja
+            </when>
+            <when test="userLang == 'ko'">
+                ti.name_ko
+            </when>
+            <when test="userLang == 'th'">
+                ti.name_th
+            </when>
+            <when test="userLang == 'vi'">
+                ti.name_vi
+            </when>
+            <when test="userLang == 'ru'">
+                ti.name_ru
+            </when>
+            <when test="userLang == 'en'">
+                ti.name_en
+            </when>
+            <when test="userLang == 'pt'">
+                ti.name_pt
+            </when>
+            <when test="userLang == 'fa'">
+                ti.name_fa
+            </when>
+            <when test="userLang == 'es'">
+                ti.name_es
+            </when>
+            <otherwise>
+                ti.name
+            </otherwise>
         </choose>
         AS task_name,
         ti.instruction,

+ 1 - 0
src/main/resources/mapper/UserTaskRecordMapper.xml

@@ -10,6 +10,7 @@
         <result column="start_time" property="startTime"/>
         <result column="complete_time" property="completeTime"/>
         <result column="reward_amount" property="rewardAmount"/>
+        <result column="callback_num" property="callbackNum"/>
         <result column="create_time" property="createTime"/>
         <result column="update_time" property="updateTime"/>
     </resultMap>

+ 7 - 1
src/main/resources/messages/messages_en.properties

@@ -33,4 +33,10 @@ error.team.invite.reward.task.claim.previous.not.claim=Previous level invitation
 error.team.invite.reward.task.claim.not.enough=Current invitation task not completed, insufficient number of invited friends
 error.team.invite.reward.task.claim.not.found=Invitation reward rule not found
 error.task.handle.id.is.null=Task ID cannot be empty
-error.task.handle.not.exist=Task does not exist
+error.task.handle.not.exist=Task does not exist
+response.error.sign=Signature error
+response.formatting.error=Request parameter format error
+response.error.timeout=Request timeout
+response.error.repeat=Please do not repeat the request
+error.task.accept.api.link.is.null=Task acceptance API link cannot be empty
+error.user.not.exist=User does not exist

+ 7 - 1
src/main/resources/messages/messages_es.properties

@@ -33,4 +33,10 @@ error.team.invite.reward.task.claim.previous.not.claim=La recompensa de invitaci
 error.team.invite.reward.task.claim.not.enough=Tarea de invitación actual no completada, número insuficiente de amigos invitados
 error.team.invite.reward.task.claim.not.found=Regla de recompensa de invitación no encontrada
 error.task.handle.id.is.null=El ID de la tarea no puede estar vacío
-error.task.handle.not.exist=La tarea no existe
+error.task.handle.not.exist=La tarea no existe
+response.error.sign=Error de firma
+response.formatting.error=Error de formato de parámetros de solicitud
+response.error.timeout=Tiempo de espera de solicitud agotado
+response.error.repeat=Por favor no repita la solicitud
+error.task.accept.api.link.is.null=El enlace de la API de aceptación de tareas no puede estar vacío
+error.user.not.exist=El usuario no existe

+ 7 - 1
src/main/resources/messages/messages_fa.properties

@@ -33,4 +33,10 @@ error.team.invite.reward.task.claim.previous.not.claim=پاداش دعوت سط
 error.team.invite.reward.task.claim.not.enough=وظیفه دعوت فعلی تکمیل نشده است، تعداد دوستان دعوت شده ناکافی است
 error.team.invite.reward.task.claim.not.found=قانون پاداش دعوت یافت نشد
 error.task.handle.id.is.null=شناسه وظیفه نمی‌تواند خالی باشد
-error.task.handle.not.exist=وظیفه وجود ندارد
+error.task.handle.not.exist=وظیفه وجود ندارد
+response.error.sign=خطای امضا
+response.formatting.error=خطای قالب پارامتر درخواست
+response.error.timeout=پایان مهلت درخواست
+response.error.repeat=لطفا درخواست را تکرار نکنید
+error.task.accept.api.link.is.null=لینک API پذیرش وظیفه نمی‌تواند خالی باشد
+error.user.not.exist=کاربر وجود ندارد

+ 7 - 1
src/main/resources/messages/messages_ja.properties

@@ -33,4 +33,10 @@ error.team.invite.reward.task.claim.previous.not.claim=前のレベルの招待
 error.team.invite.reward.task.claim.not.enough=現在の招待タスクが完了していません。招待した友達の数が不足しています
 error.team.invite.reward.task.claim.not.found=招待報酬ルールが見つかりません
 error.task.handle.id.is.null=タスクIDを空にすることはできません
-error.task.handle.not.exist=タスクが存在しません
+error.task.handle.not.exist=タスクが存在しません
+response.error.sign=署名エラー
+response.formatting.error=リクエストパラメータのフォーマットエラー
+response.error.timeout=リクエストタイムアウト
+response.error.repeat=リクエストを繰り返さないでください
+error.task.accept.api.link.is.null=タスク受け入れAPIリンクは空にできません
+error.user.not.exist=ユーザーが存在しません

+ 7 - 1
src/main/resources/messages/messages_ko.properties

@@ -33,4 +33,10 @@ error.team.invite.reward.task.claim.previous.not.claim=이전 레벨의 초대 
 error.team.invite.reward.task.claim.not.enough=현재 초대 작업이 완료되지 않았습니다. 초대한 친구 수가 부족합니다
 error.team.invite.reward.task.claim.not.found=초대 보상 규칙을 찾을 수 없습니다
 error.task.handle.id.is.null=작업 ID는 비워둘 수 없습니다
-error.task.handle.not.exist=작업이 존재하지 않습니다
+error.task.handle.not.exist=작업이 존재하지 않습니다
+response.error.sign=서명 오류
+response.formatting.error=요청 매개변수 형식 오류
+response.error.timeout=요청 시간 초과
+response.error.repeat=요청을 반복하지 마십시오
+error.task.accept.api.link.is.null=작업 수락 API 링크는 비워둘 수 없습니다
+error.user.not.exist=사용자가 존재하지 않습니다

+ 7 - 1
src/main/resources/messages/messages_pt.properties

@@ -33,4 +33,10 @@ error.team.invite.reward.task.claim.previous.not.claim=A recompensa de convite d
 error.team.invite.reward.task.claim.not.enough=Tarefa de convite atual não concluída, número insuficiente de amigos convidados
 error.team.invite.reward.task.claim.not.found=Regra de recompensa de convite não encontrada
 error.task.handle.id.is.null=O ID da tarefa não pode estar vazio
-error.task.handle.not.exist=A tarefa não existe
+error.task.handle.not.exist=A tarefa não existe
+response.error.sign=Erro de assinatura
+response.formatting.error=Erro de formato de parâmetro de solicitação
+response.error.timeout=Tempo limite da solicitação
+response.error.repeat=Por favor, não repita a solicitação
+error.task.accept.api.link.is.null=O link da API de aceitação de tarefa não pode estar vazio
+error.user.not.exist=Usuário não existe

+ 7 - 1
src/main/resources/messages/messages_ru.properties

@@ -33,4 +33,10 @@ error.team.invite.reward.task.claim.previous.not.claim=Награда за пр
 error.team.invite.reward.task.claim.not.enough=Текущая задача приглашения не выполнена, недостаточное количество приглашенных друзей
 error.team.invite.reward.task.claim.not.found=Правило награды за приглашение не найдено
 error.task.handle.id.is.null=ID задачи не может быть пустым
-error.task.handle.not.exist=Задача не существует
+error.task.handle.not.exist=Задача не существует
+response.error.sign=Ошибка подписи
+response.formatting.error=Ошибка формата параметров запроса
+response.error.timeout=Время ожидания запроса истекло
+response.error.repeat=Пожалуйста, не повторяйте запрос
+error.task.accept.api.link.is.null=Ссылка API для принятия задачи не может быть пустой
+error.user.not.exist=Пользователь не существует

+ 7 - 1
src/main/resources/messages/messages_th.properties

@@ -33,4 +33,10 @@ error.team.invite.reward.task.claim.previous.not.claim=รางวัลกา
 error.team.invite.reward.task.claim.not.enough=งานเชิญปัจจุบันยังไม่เสร็จสมบูรณ์ จำนวนเพื่อนที่เชิญไม่เพียงพอ
 error.team.invite.reward.task.claim.not.found=ไม่พบกฎรางวัลการเชิญ
 error.task.handle.id.is.null=ID งานต้องไม่ว่างเปล่า
-error.task.handle.not.exist=งานไม่มีอยู่
+error.task.handle.not.exist=งานไม่มีอยู่
+response.error.sign=ข้อผิดพลาดลายเซ็น
+response.formatting.error=ข้อผิดพลาดรูปแบบพารามิเตอร์คำขอ
+response.error.timeout=หมดเวลาการร้องขอ
+response.error.repeat=โปรดอย่าส่งคำขอซ้ำ
+error.task.accept.api.link.is.null=ลิงก์ API การยอมรับงานต้องไม่ว่างเปล่า
+error.user.not.exist=ไม่พบผู้ใช้

+ 7 - 1
src/main/resources/messages/messages_vi.properties

@@ -33,4 +33,10 @@ error.team.invite.reward.task.claim.previous.not.claim=Phần thưởng mời c
 error.team.invite.reward.task.claim.not.enough=Nhiệm vụ mời hiện tại chưa hoàn thành, số lượng bạn bè được mời không đủ
 error.team.invite.reward.task.claim.not.found=Không tìm thấy quy tắc phần thưởng mời
 error.task.handle.id.is.null=ID nhiệm vụ không thể để trống
-error.task.handle.not.exist=Nhiệm vụ không tồn tại
+error.task.handle.not.exist=Nhiệm vụ không tồn tại
+response.error.sign=Lỗi chữ ký
+response.formatting.error=Lỗi định dạng tham số yêu cầu
+response.error.timeout=Hết thời gian yêu cầu
+response.error.repeat=Vui lòng không lặp lại yêu cầu
+error.task.accept.api.link.is.null=Liên kết API chấp nhận nhiệm vụ không được để trống
+error.user.not.exist=Người dùng không tồn tại

+ 7 - 1
src/main/resources/messages/messages_zh_CN.properties

@@ -33,4 +33,10 @@ error.team.invite.reward.task.claim.previous.not.claim=上一等级的邀请奖
 error.team.invite.reward.task.claim.not.enough=当前邀请任务未完成,邀请好友数不足
 error.team.invite.reward.task.claim.not.found=邀请奖励规则不存在
 error.task.handle.id.is.null=任务id不能为空
-error.task.handle.not.exist=任务不存在
+error.task.handle.not.exist=任务不存在
+response.error.sign=签名错误
+response.formatting.error=请求参数格式错误
+response.error.timeout=请求超时
+response.error.repeat=请勿重复请求
+error.task.accept.api.link.is.null=任务接收接口链接不能为空
+error.user.not.exist=用户不存在

+ 7 - 1
src/main/resources/messages/messages_zh_TW.properties

@@ -33,4 +33,10 @@ error.team.invite.reward.task.claim.previous.not.claim=上一等級的邀請獎
 error.team.invite.reward.task.claim.not.enough=當前邀請任務未完成,邀請好友數不足
 error.team.invite.reward.task.claim.not.found=邀請獎勵規則不存在
 error.task.handle.id.is.null=任務 ID 不能為空
-error.task.handle.not.exist=任務不存在
+error.task.handle.not.exist=任務不存在
+response.error.sign=簽名錯誤
+response.formatting.error=請求參數格式錯誤
+response.error.timeout=請求超時
+response.error.repeat=請勿重複請求
+error.task.accept.api.link.is.null=任務接受API鏈接不能為空
+error.user.not.exist=用戶不存在