Quellcode durchsuchen

数据插入异常处理

anderx vor 1 Jahr
Ursprung
Commit
275e8c8bee

+ 1 - 0
pom.xml

@@ -169,6 +169,7 @@
                 <version>${ruoyi.version}</version>
             </dependency>
 
+
         </dependencies>
     </dependencyManagement>
 

+ 10 - 0
ruoyi-admin/src/main/java/com/ruoyi/web/controller/project/ProjectTaskController.java

@@ -401,4 +401,14 @@ public class ProjectTaskController extends BaseController {
         projectStaffRecordService.mateUserRecord(in);
         return AjaxResult.success();
     }
+
+    /**
+     * 项目及日志上传天河链
+     * @param id
+     * @return
+     */
+    @GetMapping("/saveTianhe")
+    public AjaxResult saveTianhe(@RequestParam("id") Long id){
+        return projectTaskService.seveText(id);
+    }
 }

+ 10 - 0
ruoyi-admin/src/main/resources/application-druid-dev.yml

@@ -66,3 +66,13 @@ spring:
                 wall:
                     config:
                         multi-statement-allow: true
+
+tianhe:
+    prefix: yfdk_test
+    appid: tichain024581
+    appkey: 5bc9a2c89b808b7c545a71473710db6e79dcf519
+    add_user_url: https://api.tichain.tianhecloud.com/api/v2/user
+    seve_text_url: https://api.tichain.tianhecloud.com/v1/deposit/text/save
+    seve_file_url: https://api.tichain.tianhecloud.com/v1/deposit/file/save
+    deposit_certificate_url: https://api.tichain.tianhecloud.com/v1/deposit/certificate
+    deposit_query_url: https://api.tichain.tianhecloud.com/v1/deposit/query

+ 10 - 0
ruoyi-admin/src/main/resources/application-druid-prod.yml

@@ -65,3 +65,13 @@ spring:
                 wall:
                     config:
                         multi-statement-allow: true
+
+tianhe:
+    prefix: yfdk_prod
+    appid: tichain024581
+    appkey: 5bc9a2c89b808b7c545a71473710db6e79dcf519
+    add_user_url: https://api.tichain.tianhecloud.com/api/v2/user
+    seve_text_url: https://api.tichain.tianhecloud.com/v1/deposit/text/save
+    seve_file_url: https://api.tichain.tianhecloud.com/v1/deposit/file/save
+    deposit_certificate_url: https://api.tichain.tianhecloud.com/v1/deposit/certificate
+    deposit_query_url: https://api.tichain.tianhecloud.com/v1/deposit/query

+ 10 - 0
ruoyi-common/pom.xml

@@ -135,6 +135,16 @@
             <version>0.2.15</version>
             <scope>compile</scope>
         </dependency>
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>fastjson</artifactId>
+            <version>2.0.28</version>
+        </dependency>
+        <dependency>
+            <groupId>cn.hutool</groupId>
+            <artifactId>hutool-all</artifactId>
+            <version>5.8.15</version>
+        </dependency>
 
     </dependencies>
 

+ 9 - 0
ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysUser.java

@@ -149,6 +149,15 @@ public class SysUser extends BaseEntity
     private Integer projectQuantitySort;
     private Integer durationSort;
     private String ddUserId;
+    private String tianheId;
+
+    public String getTianheId() {
+        return tianheId;
+    }
+
+    public void setTianheId(String tianheId) {
+        this.tianheId = tianheId;
+    }
 
     public String getDdUserId() {
         return ddUserId;

+ 98 - 0
ruoyi-common/src/main/java/com/ruoyi/common/utils/TianheSignUtil.java

@@ -0,0 +1,98 @@
+package com.ruoyi.common.utils;
+
+
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.serializer.SerializerFeature;
+
+import java.nio.charset.StandardCharsets;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @title: 签名工具类
+ * @Author xy
+ * @Date: 2022/9/17 14:41
+ * @Version 1.0
+ */
+public class TianheSignUtil {
+    /**
+     * 对请求参数进行签名处理
+     *
+     * @param path      请求路径,仅截取域名后及 Query 参数前部分,例:"/api/v2/user";
+     * @param query     Query 参数,例:"key1=value1&key2=value2",需转为 Map 格式
+     * @param body      Body 参数,例:"{\"count\": 1, \"operation_id\": \"random_string\"}",需转为 Map 格式
+     * @param timestamp 当前时间戳(毫秒),例:1647751123703
+     * @param apiSecret 应用方的 API Secret,例:"AKIDz8krbsJ5yKBZQpn74WFkmLPc5ab"
+     * @return 返回签名结果
+     */
+    public static String signRequest(String path, Map<String, Object> query, Map<String, Object> body, long timestamp, String apiSecret) {
+        Map<String, Object> paramsMap = new HashMap();
+
+        paramsMap.put("path_url", path);
+
+        if (query != null && !query.isEmpty()) {
+            query.forEach((key, value) ->{
+                if (!key.equals("file")){
+                paramsMap.put("query_" + key, value);
+                }
+            });
+
+        }
+        if (body != null && !body.isEmpty()) {
+            body.forEach((key, value) -> {
+                if (!key.equals("file")){
+                    paramsMap.put("body_" + key, value);
+                }
+            });
+        }
+
+        // 将请求参数序列化为排序后的 JSON 字符串
+        String jsonStr = JSON.toJSONString(paramsMap, SerializerFeature.MapSortField);
+
+        String str=jsonStr + String.valueOf(timestamp) + apiSecret;
+        System.out.println(str);
+        // 执行签名
+        String signature = sha256Sum(str);
+
+        return signature;
+    }
+
+    /**
+     * SHA256 摘要
+     *
+     * @param str
+     * @return
+     */
+    private static String sha256Sum(String str) {
+        MessageDigest digest = null;
+        try {
+            digest = MessageDigest.getInstance("SHA-256");
+        } catch (NoSuchAlgorithmException e) {
+            // Should not happen
+            e.printStackTrace();
+        }
+        byte[] encodedHash = digest.digest(str.getBytes(StandardCharsets.UTF_8));
+        return bytesToHex(encodedHash);
+    }
+
+    /**
+     * 将 bytes 转为 Hex
+     *
+     * @param hash
+     * @return
+     */
+    private static String bytesToHex(byte[] hash) {
+        StringBuilder hexString = new StringBuilder(2 * hash.length);
+        for (int i = 0; i < hash.length; i++) {
+            String hex = Integer.toHexString(0xff & hash[i]);
+            if (hex.length() == 1) {
+                hexString.append('0');
+            }
+            hexString.append(hex);
+        }
+        return hexString.toString();
+    }
+}

+ 1 - 0
ruoyi-system/src/main/java/com/ruoyi/project/service/ProjectTaskService.java

@@ -25,5 +25,6 @@ public interface ProjectTaskService {
 
     boolean checkProjectNumber(ProjectTask projectTask);
 
+    AjaxResult seveText(Long id);
 
 }

+ 76 - 3
ruoyi-system/src/main/java/com/ruoyi/project/service/impl/ProjectTaskServiceImpl.java

@@ -1,9 +1,12 @@
 package com.ruoyi.project.service.impl;
 
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
 import com.ruoyi.common.core.domain.AjaxResult;
 import com.ruoyi.common.core.domain.entity.SysUser;
 import com.ruoyi.common.enums.UserRolesType;
 import com.ruoyi.common.exception.ServiceException;
+import com.ruoyi.common.utils.DateUtils;
 import com.ruoyi.common.utils.PageUtils;
 import com.ruoyi.common.utils.SecurityUtils;
 import com.ruoyi.common.utils.StringUtils;
@@ -24,16 +27,17 @@ import com.ruoyi.system.service.ISysDeptService;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
 import org.springframework.stereotype.Service;
 
 import javax.servlet.http.HttpServletResponse;
 import javax.validation.Validator;
 import java.io.ByteArrayOutputStream;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
+import java.util.*;
 import java.util.zip.ZipOutputStream;
 
+import static java.lang.Thread.sleep;
+
 @Service
 public class ProjectTaskServiceImpl   implements ProjectTaskService {
 
@@ -50,6 +54,8 @@ public class ProjectTaskServiceImpl   implements ProjectTaskService {
     private SysUserMapper userMapper;
     @Autowired
     private ProjectStaffRecordMapper projectStaffRecordMapper;
+    @Autowired
+    private TianheService tianheService;
 
     @Override
     public AjaxResult addProjectTask(ProjectTask projectTask) {
@@ -271,6 +277,8 @@ public class ProjectTaskServiceImpl   implements ProjectTaskService {
         return false;
     }
 
+
+
     private void addStaffAndDelete(  ProjectTaskListOut p) {
         String[] split = p.getStaffName().split(",");
         List<ProjectStaff> projectStaffs = projectStaffMapper.selectByPid(p.getId());
@@ -327,4 +335,69 @@ public class ProjectTaskServiceImpl   implements ProjectTaskService {
     }
 
 
+    @Override
+    public AjaxResult seveText(Long id) {
+        ProjectTask projectTask = projectTaskMapper.selectByPrimaryKey(id);
+        List<ProjectStaffRecord> projectStaffRecords = projectStaffRecordMapper.selectByPidAndAid(id, null);
+        Map<String,Object> map=new HashMap<>();
+        map.put("projectTask",projectTask);
+        map.put("projectStaffRecords",projectStaffRecords);
+        map.put("date", DateUtils.getTime());
+        String json = JSONObject.toJSONString(map);
+        String address = getAddress();
+        String  operateId = DateUtils.dateTimeNow();
+        String s = tianheService.seveText(address, json, operateId);
+        JSONObject res = JSONObject.parseObject(s);
+        Integer code = (Integer) res.get("code");
+        String tianheCloudUrl=null;
+        if (code== HttpStatus.OK.value()){
+            try {
+                sleep(1000);
+            } catch (InterruptedException e) {
+                throw new RuntimeException(e);
+            }
+            String certificate = tianheService.getCertificate(address, operateId);
+            JSONObject certificateData = JSONObject.parseObject(certificate);
+            String tianheCloudId=res.getString("data");
+            log.debug(certificateData.toJSONString());
+            tianheCloudUrl=certificateData.getString("data");
+            
+        }
+        return AjaxResult.success(tianheCloudUrl);
+    }
+
+    private String getAddress() {
+        String address = null;
+        SysUser user = SecurityUtils.getLoginUser().getUser();
+        if (user.getTianheId()==null){
+            SysUser sysUser = userMapper.selectUserById(user.getUserId());
+            if (sysUser.getTianheId()==null){
+                try {
+                    String userId=user.getUserId().toString();
+                    String s = tianheService.addUser( userId, "123456");
+                    JSONObject jsonObject = JSONObject.parseObject(s);
+                    JSONObject data = (JSONObject) jsonObject.get("data");
+                    JSONObject pubKey = (JSONObject) data.get("pubKey");
+                    address= (String) pubKey.get("address");
+                }catch (Exception e ){
+                    log.error("天河账号创建失败!");
+                    throw  new RuntimeException("天河账号创建失败");
+                }
+                if (address!=null){
+                    user.setTianheId(address);
+                    userMapper.updateUser(user);
+                }
+            }else {
+                address = sysUser.getTianheId();
+            }
+        }else {
+
+            address = user.getTianheId();
+        }
+        if (address==null){
+            throw new ServiceException("天河账号不存在,请稍后再试");
+        }
+        return address;
+    }
+
 }

+ 188 - 0
ruoyi-system/src/main/java/com/ruoyi/project/service/impl/TianheService.java

@@ -0,0 +1,188 @@
+package com.ruoyi.project.service.impl;
+
+import cn.hutool.http.HttpRequest;
+import cn.hutool.json.JSONObject;
+import cn.hutool.json.JSONUtil;
+import com.ruoyi.common.utils.TianheSignUtil;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Calendar;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author tangrui
+ * @version 1.0
+ * @description: depositTest
+ * @date: 2023/3/21 17:12
+ */
+@Service("TianheService")
+public class TianheService {
+    @Value("${tianhe.appid}")
+    private String appid;
+    @Value("${tianhe.appkey}")
+    private String appkey;
+    //    测试环境
+//    final static String test_address = "0xa7cf21881211d7b353b3acdf92453e99dccc4212";
+//    final static String test_publicKey="04e8860b97ac4806bdda1debdb59847bf12b6fb5847bbab63a92bd2b5ad8d3cb67210f23c4b4ff0852e55ee4bc6fd7c9ea69128dd0caa69561dd0f59e963dfd48a";
+//    // 正式环境 anderx账号
+//    final static String address = "0x4cc4951ba7af50ddab07d417c4633522043d0984";
+//    final static String publicKey="0465cbb9872e84c3d5cdc526020bff5b30a5bc9cf3855cfd61ea603e0aa3168ddf5555191f4f60fff31f2396fd7bca8e886204481aba4e74ec1cea04cd8db0f95d";
+    @Value("${tianhe.add_user_url}")
+    private String add_user_url ;
+    @Value("${tianhe.seve_text_url}")
+    private String seve_text_url;
+    @Value("${tianhe.seve_file_url}")
+    private String seve_file_url;
+    @Value("${tianhe.deposit_certificate_url}")
+    private String deposit_certificate_url;
+    @Value("${tianhe.deposit_query_url}")
+    private String deposit_query_url;
+    @Value("${tianhe.prefix}")
+    private String prefix;
+
+
+    public  String addUser(String  userId,String userKey) {
+        Map<String, Object> body = new HashMap<>();
+        body.put("appId",appid);
+        body.put("appKey",appkey);
+        body.put("userId",prefix+userId);
+        body.put("userKey",userKey);
+        JSONObject jsonObject= JSONUtil.createObj();
+        jsonObject.putAll(body);
+
+        String post = HttpRequest.post(add_user_url).header("Content-Type", "application/json")
+                .body(jsonObject.toString()).execute().body();
+        return post;
+    }
+
+    public  String seveText(String address,String text,String operateId) {
+        //step1 拼接body
+        Map<String, Object> body = new HashMap<>();
+        body.put("text", text);
+        body.put("address", address);
+        body.put("operateId", operateId);
+        body.put("noDigest", false);
+        JSONObject jsonObject = JSONUtil.createObj();
+        jsonObject.putAll(body);
+        long timestamp = System.currentTimeMillis();
+        // 请求路径,仅截取域名后及 Query 参数前部分,例:"/v1/deposit/query";
+        String uri = "/v1/deposit/text/save";
+        //接口签名
+        String signature = TianheSignUtil.signRequest(uri, null, body, timestamp, appkey);
+        //hutool.http
+        String result2 = HttpRequest.post(seve_text_url)
+                .header("ti-appid", appid)
+                .header("ti-timestamp", String.valueOf(timestamp))
+                .header("ti-signature", signature)
+                .body(jsonObject.toString())
+                .execute().body();
+        System.out.println(result2);
+        return result2;
+        /**
+         * {"code":200,"success":true,"data":"aasdas121245","msg":"操作成功"}
+         */
+    }
+    public  String seveFile(String address,String operateId,File file) {
+        //step1 拼接body
+        Map<String, Object> body = new HashMap<>();
+        Map<String, Object> query = new HashMap<>();
+        body.put("file", file);
+        body.put("address", address);
+        body.put("operateId", operateId);
+        long timestamp = System.currentTimeMillis();
+        System.out.println(timestamp);
+        // 请求路径,仅截取域名后及 Query 参数前部分,例:"/v1/deposit/query";
+        String uri = "/v1/deposit/file/save";
+        //接口签名
+        String signature = TianheSignUtil.signRequest(uri, body,query , timestamp, appkey);
+        System.out.println(signature);
+        //hutool.http
+        String result2 = HttpRequest.post(seve_file_url)
+                .header("ti-appid", appid)
+                .header("ti-timestamp", String.valueOf(timestamp))
+                .header("ti-signature", signature)
+//                .header("Content-Type","application/form-data")
+                .form(body)
+                .execute().body();
+        System.out.println(result2);
+        return result2;
+        /**
+         * {"code":200,"success":true,"data":"aasdas121245","msg":"操作成功"}
+         */
+    }
+    public  String seveFile(String address,String operateId,MultipartFile multipartFile) throws IOException {
+        File file=null;
+        String originalFilename = multipartFile.getOriginalFilename();
+        String [] fileName =originalFilename.split("\\.");
+        file=File.createTempFile(fileName[0],fileName[1]);
+        multipartFile.transferTo(file);
+        return seveFile(address,operateId,file);
+    }
+
+
+
+    public  String depositQuery(String address,String operateId) {
+        //天河链控制台获取
+
+        Map<String, Object> query = new HashMap<>();
+        query.put("address", address);
+        query.put("operateId", operateId);
+        //step1 拼接body
+        Map<String, Object> body = new HashMap<>();
+
+        long timestamp = System.currentTimeMillis();
+        // 请求路径,仅截取域名后及 Query 参数前部分,例:"/v1/deposit/query";
+        String uri = "/v1/deposit/query";
+        //接口签名
+        String signature = TianheSignUtil.signRequest(uri, query, body, timestamp, appkey);
+        //hutool.http
+        String result2 = HttpRequest.get(deposit_query_url + "?address="+address+"&operateId="+operateId)
+                .header("ti-appid", appid)
+                .header("ti-timestamp", timestamp + "")
+                .header("ti-signature", signature)
+                .execute().body();
+        System.out.println(result2);
+        /**
+         * {"code":200,"success":true,"data":{"operateId":"aasdas121245","status":1,
+         * "depositContent":"这是一个测试文档数据","type":"TEXT","digest":"673b36d75cc544a07f706bfa734ed95bfab3123124985ec5306d0ab1190d5041",
+         * "txHash":"0x95abd4d4d138d32d121ff0afcd11e77d5746b61cd68815128aa5caa23f2abad4","createTime":"Mon Oct 16 14:43:03 CST 2023",
+         * "blockNumber":1803291,"blockHash":"0x3130f3cd927f74535b4d2ba1355a8dc54745f1b344c362804db543e25b511f47"},"msg":"操作成功"}
+         */
+        return result2;
+    }
+
+    public  String getCertificate(String address,String operateId) {
+        //天河链控制台获取
+        Map<String, Object> query = new HashMap<>();
+        query.put("address", address);
+        query.put("operateId", operateId);
+        //step1 拼接body
+        Map<String, Object> body = new HashMap<>();
+
+        long timestamp = System.currentTimeMillis();
+        // 请求路径,仅截取域名后及 Query 参数前部分,例:"/v1/deposit/query";
+        String uri = "/v1/deposit/certificate";
+        //接口签名
+        String signature = TianheSignUtil.signRequest(uri, query, body, timestamp, appkey);
+        //hutool.http
+        String result2 = HttpRequest.get(deposit_certificate_url + "?address="+address+"&operateId="+operateId)
+                .header("ti-appid", appid)
+                .header("ti-timestamp", timestamp + "")
+                .header("ti-signature", signature)
+                .execute().body();
+        System.out.println(result2);
+        return result2;
+        /**
+         * {"code":200,"success":true,"data":"https://test.tichain.tianhecloud.com/#/certificate?
+         * depositContent=这是一个测试文档数据&type=TEXT&digest=673b36d75cc544a07f706bfa734ed95bfab3123124985ec5306d0ab1190d5041&
+         * txHash=0x95abd4d4d138d32d121ff0afcd11e77d5746b61cd68815128aa5caa23f2abad4&address=0xa7cf21881211d7b353b3acdf92453e99dccc4212&
+         * createTime=1697438585000","msg":"操作成功"}
+         */
+
+    }
+}

+ 5 - 1
ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml

@@ -32,6 +32,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 		<result property="roleId"       column="roleId"       />
 		<result property="duration"       column="duration"       />
 		<result property="ddUserId"       column="dd_user_id"       />
+		<result property="tianheId"       column="tianhe_id"       />
 		<result property="postName"       column="post_name"       />
 		<result property="roleName"       column="roleName"       />
 		<result property="deptName"  column="dept_name"   />
@@ -66,7 +67,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         select u.user_id, u.dept_id, u.user_name, u.nick_name, u.email, u.avatar, u.phonenumber, u.password, u.sex, u.status, u.del_flag, u.login_ip, u.login_date, u.create_by, u.create_time, u.remark,
         d.dept_id, d.parent_id, d.ancestors, d.dept_name, d.order_num, d.leader, d.status as dept_status,d.ancestors,d.max_duration,u.open_id,d.company_id,
         r.role_id, r.role_name, r.role_key, r.role_sort, r.data_scope, r.status as role_status,u.superior_id ,su.nick_name superiorName,
-		u.job_number,u.full_job,u.dd_user_id
+		u.job_number,u.full_job,u.dd_user_id,u.tianhe_id
         from sys_user u
 		    left join sys_dept d on u.dept_id = d.dept_id
 		    left join sys_user_role ur on u.user_id = ur.user_id
@@ -242,6 +243,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  			<if test="fullJob != null ">full_job,</if>
  			<if test="duration != null and duration != ''">duration,</if>
  			<if test="ddUserId != null and ddUserId != ''">dd_user_id,</if>
+ 			<if test="tianheId != null and tianheId != ''">tianhe_id,</if>
  			create_time
  		)values(
  			<if test="userId != null and userId != ''">#{userId},</if>
@@ -263,6 +265,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 			<if test="fullJob != null">#{fullJob},</if>
 			<if test="duration != null and duration != ''">#{duration},</if>
 			<if test="ddUserId != null and ddUserId != ''">#{ddUserId},</if>
+			<if test="tianheId != null and tianheId != ''">#{tianheId},</if>
  			sysdate()
  		)
 	</insert>
@@ -290,6 +293,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 			<if test="fullJob != null"> full_job = #{fullJob,jdbcType=INTEGER}, </if>
 			<if test="duration != null and duration != ''">duration=#{duration},</if>
 			<if test="ddUserId != null and ddUserId != ''">dd_user_id=#{ddUserId},</if>
+			<if test="tianheId != null and tianheId != ''">tianhe_id=#{tianheId},</if>
  			update_time = sysdate()
  		</set>
  		where user_id = #{userId}