Przeglądaj źródła

矿大南湖合并版本修改短信相关

donggaosheng 1 rok temu
rodzic
commit
2f7ba9bdc9
23 zmienionych plików z 1438 dodań i 8 usunięć
  1. 8 0
      zd-api/zd-algorithm-api/src/main/java/com/zd/algorithm/api/alarm/feign/RemoteAlarmService.java
  2. 10 0
      zd-api/zd-algorithm-api/src/main/java/com/zd/algorithm/api/alarm/feign/fallback/RemoteAlarmFallbackFactory.java
  3. 25 0
      zd-api/zd-laboratory-api/src/main/java/com/zd/laboratory/api/constant/SmsMessageConstants.java
  4. 15 0
      zd-api/zd-laboratory-api/src/main/java/com/zd/laboratory/api/feign/RemoteAlarmLogService.java
  5. 36 0
      zd-api/zd-laboratory-api/src/main/java/com/zd/laboratory/api/feign/RemoteSmsService.java
  6. 30 0
      zd-api/zd-laboratory-api/src/main/java/com/zd/laboratory/api/feign/fallback/RemoteAlarmLogFallbackFactory.java
  7. 30 0
      zd-api/zd-laboratory-api/src/main/java/com/zd/laboratory/api/feign/fallback/RemoteSmsFallbackFactory.java
  8. 38 0
      zd-api/zd-laboratory-api/src/main/java/com/zd/laboratory/api/vo/TextMessageVo.java
  9. 56 8
      zd-common/common-core/src/main/java/com/zd/common/core/utils/HttpUtils.java
  10. 107 0
      zd-common/common-core/src/main/java/com/zd/common/core/utils/MD5Utils.java
  11. 20 0
      zd-modules/zd-algorithm/src/main/java/com/zd/alg/alarm/controller/AlarmController.java
  12. 7 0
      zd-modules/zd-algorithm/src/main/java/com/zd/alg/alarm/mapper/AlarmLogMapper.java
  13. 9 0
      zd-modules/zd-algorithm/src/main/java/com/zd/alg/alarm/service/IAlarmLogService.java
  14. 5 0
      zd-modules/zd-algorithm/src/main/java/com/zd/alg/alarm/service/impl/AlarmLogServiceImpl.java
  15. 33 0
      zd-modules/zd-algorithm/src/main/resources/mapper/alarm/AlarmLogMapper.xml
  16. 140 0
      zd-modules/zd-base/src/main/java/com/zd/base/job/task/MessageTask.java
  17. 66 0
      zd-modules/zd-modules-laboratory/src/main/java/com/zd/laboratory/config/MessagePropertiesConfig.java
  18. 41 0
      zd-modules/zd-modules-laboratory/src/main/java/com/zd/laboratory/controller/LabSmsController.java
  19. 19 0
      zd-modules/zd-modules-laboratory/src/main/java/com/zd/laboratory/domain/vo/IotTextMessageVo.java
  20. 51 0
      zd-modules/zd-modules-laboratory/src/main/java/com/zd/laboratory/service/ILabMessageService.java
  21. 88 0
      zd-modules/zd-modules-laboratory/src/main/java/com/zd/laboratory/service/impl/LabMessageServiceImpl.java
  22. 199 0
      zd-modules/zd-modules-laboratory/src/main/java/com/zd/laboratory/utils/StringAssembler.java
  23. 405 0
      zd-modules/zd-modules-laboratory/src/main/java/com/zd/laboratory/utils/TextMessageUtils.java

+ 8 - 0
zd-api/zd-algorithm-api/src/main/java/com/zd/algorithm/api/alarm/feign/RemoteAlarmService.java

@@ -1,13 +1,18 @@
 package com.zd.algorithm.api.alarm.feign;
 
 import com.zd.algorithm.api.alarm.entity.AlarmEntrty;
+import com.zd.algorithm.api.alarm.entity.AlarmLog;
 import com.zd.algorithm.api.alarm.feign.fallback.RemoteAlarmFallbackFactory;
 import com.zd.model.constant.ApplicationConstants;
 import com.zd.model.domain.AjaxResult;
+import com.zd.model.domain.ResultData;
+import com.zd.model.entity.SysFile;
 import org.springframework.cloud.openfeign.FeignClient;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestBody;
 
+import java.util.List;
+
 /**
  * 报警系统Feign调用接口
  *
@@ -18,4 +23,7 @@ public interface RemoteAlarmService {
 
     @PostMapping("/alarm/send")
     public AjaxResult send(@RequestBody AlarmEntrty alarmEntrty);
+
+    @PostMapping("/alarm/addBatch")
+    public ResultData<SysFile> addBatch(@RequestBody List<AlarmLog> list);
 }

+ 10 - 0
zd-api/zd-algorithm-api/src/main/java/com/zd/algorithm/api/alarm/feign/fallback/RemoteAlarmFallbackFactory.java

@@ -1,13 +1,18 @@
 package com.zd.algorithm.api.alarm.feign.fallback;
 
 import com.zd.algorithm.api.alarm.entity.AlarmEntrty;
+import com.zd.algorithm.api.alarm.entity.AlarmLog;
 import com.zd.algorithm.api.alarm.feign.RemoteAlarmService;
 import com.zd.model.domain.AjaxResult;
+import com.zd.model.domain.ResultData;
+import com.zd.model.entity.SysFile;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.cloud.openfeign.FallbackFactory;
 import org.springframework.stereotype.Component;
 
+import java.util.List;
+
 /**
  * 报警服务降级处理
  * @author liubo
@@ -24,6 +29,11 @@ public class RemoteAlarmFallbackFactory implements FallbackFactory<RemoteAlarmSe
             public AjaxResult send(AlarmEntrty alarmEntrty) {
                 return AjaxResult.error("发送语音报警失败:" + throwable.getMessage());
             }
+
+            @Override
+            public ResultData<SysFile> addBatch(List<AlarmLog> list) {
+                return ResultData.fail("批量报警日志添加失败"+throwable.getMessage());
+            }
         };
     }
 }

+ 25 - 0
zd-api/zd-laboratory-api/src/main/java/com/zd/laboratory/api/constant/SmsMessageConstants.java

@@ -0,0 +1,25 @@
+package com.zd.laboratory.api.constant;
+
+/**
+ * @Author donggaosheng
+ * @Date 2024-04-03
+ * @description
+ **/
+public interface SmsMessageConstants {
+
+    /**
+     * 助通短信key
+     */
+    String ZT_MESSAGE_KEY = "zt_message_key:";
+
+    /**
+     * 助通语音key
+     */
+    String ZT_VOICE_KEY = "zt_voice_key:";
+
+    /**
+     * 助通语音返回成功
+     */
+    String ZT_VOICE_SUCCESS="DELIVRD";
+
+}

+ 15 - 0
zd-api/zd-laboratory-api/src/main/java/com/zd/laboratory/api/feign/RemoteAlarmLogService.java

@@ -0,0 +1,15 @@
+package com.zd.laboratory.api.feign;
+
+import com.zd.laboratory.api.feign.fallback.RemoteSmsFallbackFactory;
+import com.zd.model.constant.ApplicationConstants;
+import org.springframework.cloud.openfeign.FeignClient;
+
+/**
+ * @Author donggaosheng
+ * @Date 2024-04-03
+ * @description
+ **/
+@FeignClient(contextId = "remoteAlarmLogService", value = ApplicationConstants.LABORATORY_SERVICE, fallbackFactory = RemoteSmsFallbackFactory.class)
+public class RemoteAlarmLogService {
+
+}

+ 36 - 0
zd-api/zd-laboratory-api/src/main/java/com/zd/laboratory/api/feign/RemoteSmsService.java

@@ -0,0 +1,36 @@
+package com.zd.laboratory.api.feign;
+
+import com.zd.laboratory.api.feign.fallback.RemoteSmsFallbackFactory;
+import com.zd.model.constant.ApplicationConstants;
+import com.zd.model.domain.ResultData;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @Author donggaosheng
+ * @Date 2024-04-03
+ * @description
+ **/
+@FeignClient(contextId = "remoteSmsService", value = ApplicationConstants.LABORATORY_SERVICE, fallbackFactory = RemoteSmsFallbackFactory.class)
+public interface RemoteSmsService {
+
+    /**
+     * 获取短信回执报告
+     * @return
+     */
+    @GetMapping("/getMessageReport")
+    ResultData getMessageReport();
+
+    /**
+     * 获取语音回执报告
+     * @return
+     */
+    @GetMapping("/getVoiceReport")
+    ResultData getVoiceReport();
+
+}

+ 30 - 0
zd-api/zd-laboratory-api/src/main/java/com/zd/laboratory/api/feign/fallback/RemoteAlarmLogFallbackFactory.java

@@ -0,0 +1,30 @@
+package com.zd.laboratory.api.feign.fallback;
+
+import com.zd.laboratory.api.feign.RemoteSmsService;
+import com.zd.model.domain.ResultData;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.cloud.openfeign.FallbackFactory;
+import org.springframework.stereotype.Component;
+
+@Component
+public class RemoteAlarmLogFallbackFactory implements FallbackFactory<RemoteSmsService> {
+
+    private static final Logger log = LoggerFactory.getLogger(RemoteAlarmLogFallbackFactory.class);
+
+    @Override
+    public RemoteSmsService create(Throwable cause) {
+        log.error("短信服务调用失败:{}", cause.getMessage());
+        return new RemoteSmsService() {
+            @Override
+            public ResultData getMessageReport() {
+                return ResultData.fail("短信回执调用失败!");
+            }
+
+            @Override
+            public ResultData getVoiceReport() {
+                return ResultData.fail("语音回执调用失败 !");
+            }
+        };
+    }
+}

+ 30 - 0
zd-api/zd-laboratory-api/src/main/java/com/zd/laboratory/api/feign/fallback/RemoteSmsFallbackFactory.java

@@ -0,0 +1,30 @@
+package com.zd.laboratory.api.feign.fallback;
+
+import com.zd.laboratory.api.feign.RemoteSmsService;
+import com.zd.model.domain.ResultData;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.cloud.openfeign.FallbackFactory;
+import org.springframework.stereotype.Component;
+
+@Component
+public class RemoteSmsFallbackFactory implements FallbackFactory<RemoteSmsService> {
+
+    private static final Logger log = LoggerFactory.getLogger(RemoteSmsFallbackFactory.class);
+
+    @Override
+    public RemoteSmsService create(Throwable cause) {
+        log.error("短信服务调用失败:{}", cause.getMessage());
+        return new RemoteSmsService() {
+            @Override
+            public ResultData getMessageReport() {
+                return ResultData.fail("短信回执调用失败!");
+            }
+
+            @Override
+            public ResultData getVoiceReport() {
+                return ResultData.fail("语音回执调用失败 !");
+            }
+        };
+    }
+}

+ 38 - 0
zd-api/zd-laboratory-api/src/main/java/com/zd/laboratory/api/vo/TextMessageVo.java

@@ -0,0 +1,38 @@
+package com.zd.laboratory.api.vo;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * @Author donggaosheng
+ * @Date 2024-02-21
+ * @description
+ **/
+@Data
+public class TextMessageVo {
+    @ApiModelProperty("模版名称")
+    private String tempName;
+
+    @ApiModelProperty("模版内容")
+    private String tempContent;
+
+    @ApiModelProperty("变量集合")
+    private List<String> variableList;
+
+    @ApiModelProperty("电话集合")
+    private List<String> phoneList;
+
+    @ApiModelProperty("模版编号")
+    private String tempId;
+
+    @ApiModelProperty("用户名")
+    private String userName;
+
+    @ApiModelProperty("密码")
+    private String passWord;
+
+    @ApiModelProperty("签名")
+    private String signature;
+}

+ 56 - 8
zd-common/common-core/src/main/java/com/zd/common/core/utils/HttpUtils.java

@@ -1,5 +1,6 @@
 package com.zd.common.core.utils;
 
+import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.codec.binary.Hex;
 
 import java.io.BufferedReader;
@@ -14,20 +15,67 @@ import java.util.Map;
 
 /**
 * <p>Http工具类</p>
-* 
-* @author lft  
+*
+* @author lft
 * @date 2018年8月28日
 * @since jdk1.8
 * @version 1.0
  */
+@Slf4j
 public class HttpUtils {
 
-	private final static int CONNECT_TIMEOUT = 5000;
+	private final static int CONNECT_TIMEOUT = 10000;
     private final static String DEFAULT_ENCODING = "UTF-8";
 
+
     /**
      * 发送POST请求
-     * 
+     *
+     * @param urlStr
+     * @param data
+     * @param contentType
+     * @return
+     */
+    public static String sendPost(String urlStr, String data, String contentType) {
+        BufferedReader reader = null;
+        StringBuilder sbui = new StringBuilder();
+        try {
+            URL url = new URL(urlStr);
+            URLConnection conn = url.openConnection();
+            conn.setDoOutput(true);
+            conn.setConnectTimeout(CONNECT_TIMEOUT);
+            conn.setReadTimeout(CONNECT_TIMEOUT);
+            conn.setRequestProperty("User-Agent", "Linux; U");
+            conn.setRequestProperty("content-type", contentType);
+            conn.setRequestProperty("timestamp", String.valueOf(System.currentTimeMillis()));
+            OutputStreamWriter writer = new OutputStreamWriter(conn.getOutputStream(), DEFAULT_ENCODING);
+            if (data == null)
+                data = "";
+            writer.write(data);
+            writer.flush();
+            writer.close();
+            reader = new BufferedReader(new InputStreamReader(conn.getInputStream(), DEFAULT_ENCODING));
+            String line = null;
+            while ((line = reader.readLine()) != null) {
+                sbui.append(line);
+                sbui.append("\r\n");
+            }
+        } catch (IOException e) {
+            log.error("【Http服务工具】发送POST请求异常,异常原因: {}", e.getMessage());
+        } finally {
+            try {
+                if (reader != null)
+                    reader.close();
+            } catch (IOException e) {
+            }
+        }
+        return sbui.toString();
+    }
+
+
+    /**
+     * 发送POST请求
+     *
      * @param urlStr
      * @param data
      * @param contentType
@@ -79,14 +127,14 @@ public class HttpUtils {
     }
     /**
      * 发起Get请确认
-     * 
+     *
      * @param url
      * @return
      */
     public static String sendGet(String url){
     	return sendGet(url, null);
     }
-    
+
     public static String sendGet(String url,Integer timeOut){
  		String result="";//访问返回结果
  		BufferedReader read=null;//读取访问结果
@@ -125,7 +173,7 @@ public class HttpUtils {
  		   }
  		   return result;
  	}
-    
+
     /**
 	 * SHA1 哈希计算
 	 */
@@ -139,7 +187,7 @@ public class HttpUtils {
             throw new RuntimeException(ex);
         }
     }
-    
+
     public static String byteToHexString(byte[] bytes) {
         return String.valueOf(Hex.encodeHex(bytes));
     }

+ 107 - 0
zd-common/common-core/src/main/java/com/zd/common/core/utils/MD5Utils.java

@@ -0,0 +1,107 @@
+package com.zd.common.core.utils;
+
+import java.security.MessageDigest;
+
+/**
+ * <p>MD5加密解密</p>
+ *
+ * @author lft
+ * @version 1.0
+ * @since JDK1.8
+ * @see
+ */
+public class MD5Utils {
+
+	/***
+	 * MD5加码 生成32位md5码
+	 */
+	public static String encrypt(String inStr){
+		try {
+            byte[] btInput = inStr.getBytes("utf-8");
+            MessageDigest mdInst = MessageDigest.getInstance("MD5");
+            mdInst.update(btInput);
+            byte[] md = mdInst.digest();
+            StringBuffer sb = new StringBuffer();
+            for (int i = 0; i < md.length; i++) {
+                int val = ((int) md[i]) & 0xff;
+                if (val < 16){
+                	sb.append("0");
+                }
+                sb.append(Integer.toHexString(val));
+            }
+            return sb.toString();
+        } catch (Exception e) {
+            return null;
+        }
+	}
+
+	/**
+	 * 加密解密算法 执行一次加密,两次解密
+	 */
+	public static String convertMD5(String inStr){
+		char[] a = inStr.toCharArray();
+		for (int i = 0; i < a.length; i++){
+			a[i] = (char) (a[i] ^ 't');
+		}
+		String s = new String(a);
+		return s;
+
+	}
+
+	/**
+	 * 生成随机字符串
+	 *
+	 * @param origin
+	 * @param charsetname
+	 * @return
+	 */
+	public static String MD5Encode(String origin, String charsetname) {
+		String resultString = null;
+		try {
+			resultString = new String(origin);
+			MessageDigest md = MessageDigest.getInstance("MD5");
+			if (charsetname == null || "".equals(charsetname))
+				resultString = byteArrayToHexString(md.digest(resultString
+						.getBytes()));
+			else
+				resultString = byteArrayToHexString(md.digest(resultString
+						.getBytes(charsetname)));
+		} catch (Exception exception) {
+			resultString = null;
+		}
+		return resultString;
+	}
+
+	private static String byteArrayToHexString(byte b[]) {
+		StringBuffer resultSb = new StringBuffer();
+		for (int i = 0; i < b.length; i++)
+			resultSb.append(byteToHexString(b[i]));
+
+		return resultSb.toString();
+	}
+
+	private static String byteToHexString(byte b) {
+		int n = b;
+		if (n < 0)
+			n += 256;
+		int d1 = n / 16;
+		int d2 = n % 16;
+		return hexDigits[d1] + hexDigits[d2];
+	}
+
+	private static final String hexDigits[] = { "0", "1", "2", "3", "4", "5",
+			"6", "7", "8", "9", "a", "b", "c", "d", "e", "f" };
+
+	/**
+	 * 测试主函数
+	 * @param args
+	 */
+	public static void main(String[] args) {
+		String s = "zd123456";
+		System.out.println("原始:" + s);
+		System.out.println("MD5后:" + encrypt(s));
+		System.out.println("MD5后2:" + encrypt(encrypt(s)));
+		System.out.println("加密的:" + convertMD5(s));
+		System.out.println("解密的:" + convertMD5(convertMD5(s)));
+	}
+}

+ 20 - 0
zd-modules/zd-algorithm/src/main/java/com/zd/alg/alarm/controller/AlarmController.java

@@ -9,13 +9,16 @@ import com.zd.algorithm.api.alarm.entity.AlarmLog;
 import com.zd.algorithm.api.alarm.entity.SendTypes;
 import com.zd.base.api.feign.RemoteMessageService;
 import com.zd.common.core.annotation.PreAuthorize;
+import com.zd.common.core.exception.ServiceException;
 import com.zd.common.core.utils.DateUtils;
 import com.zd.common.core.web.controller.BaseController;
 import com.zd.model.constant.HttpStatus;
 import com.zd.model.domain.DTO.UserPhoneInfo;
+import com.zd.model.domain.R;
 import com.zd.model.domain.ResultData;
 import com.zd.model.domain.per.PerFun;
 import com.zd.model.domain.per.PerPrefix;
+import com.zd.model.entity.SysFile;
 import com.zd.model.page.TableDataInfo;
 import io.swagger.annotations.ApiOperation;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -23,6 +26,8 @@ import org.springframework.beans.factory.annotation.Value;
 import org.springframework.scheduling.annotation.Async;
 import org.springframework.web.bind.annotation.*;
 
+import javax.xml.transform.Result;
+import java.io.IOException;
 import java.util.*;
 import java.util.stream.Collectors;
 
@@ -126,6 +131,21 @@ public class AlarmController extends BaseController {
         }
     }
 
+    /**
+     * 电话预警集合
+     * @param list
+     * @return
+     */
+    @RequestMapping("/addBatch")
+    public ResultData<SysFile> addBatch(@RequestBody List<AlarmLog> list) {
+        int num=alarmLogService.insertBatchAlarmLog(list);
+        if(num>0){
+            return ResultData.success();
+        }
+        return ResultData.fail();
+    }
+
+
     private void sendSMS(AlarmEntrty alarmEntrty) {
         List<UserPhoneInfo> userPhoneInfoList = alarmEntrty.getUserPhoneInfo();
         LinkedHashMap<String, List<UserPhoneInfo>> userPhoneInfoMap = Optional.ofNullable(userPhoneInfoList).orElseGet(Collections::emptyList).stream().collect(Collectors.groupingBy(UserPhoneInfo::getPhone, LinkedHashMap::new, Collectors.toList()));

+ 7 - 0
zd-modules/zd-algorithm/src/main/java/com/zd/alg/alarm/mapper/AlarmLogMapper.java

@@ -62,4 +62,11 @@ public interface AlarmLogMapper {
     public int deleteAlarmLogByIds(Long[] ids);
 
     List<AlarmLog> selectNoBackAlarmLogList(Map<String, Object> params);
+
+    /**
+     * 电话报警日志批量插入
+     * @param alarmLog
+     * @return
+     */
+    int insertBatchAlarmLog(List<AlarmLog> alarmLog);
 }

+ 9 - 0
zd-modules/zd-algorithm/src/main/java/com/zd/alg/alarm/service/IAlarmLogService.java

@@ -36,6 +36,15 @@ public interface IAlarmLogService {
      */
     public int insertAlarmLog(AlarmLog alarmLog);
 
+
+    /**
+     * 批量电话报警推送日志
+     * @param alarmLog
+     * @return
+     */
+    public int insertBatchAlarmLog(List<AlarmLog> alarmLog);
+
+
     /**
      * 修改电话报警推送日志
      *

+ 5 - 0
zd-modules/zd-algorithm/src/main/java/com/zd/alg/alarm/service/impl/AlarmLogServiceImpl.java

@@ -53,6 +53,11 @@ public class AlarmLogServiceImpl implements IAlarmLogService {
         return alarmLogMapper.insertAlarmLog(alarmLog);
     }
 
+    @Override
+    public int insertBatchAlarmLog(List<AlarmLog> alarmLog) {
+        return alarmLogMapper.insertBatchAlarmLog(alarmLog);
+    }
+
     /**
      * 修改电话报警推送日志
      *

+ 33 - 0
zd-modules/zd-algorithm/src/main/resources/mapper/alarm/AlarmLogMapper.xml

@@ -105,6 +105,39 @@
         </trim>
     </insert>
 
+    <insert id="insertBatchAlarmLog" parameterType="java.util.List" useGeneratedKeys="true" keyProperty="id">
+        insert into alarm_log
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="keyId != null">key_id,</if>
+            <if test="createTime != null">create_time,</if>
+            <if test="updateTime != null">update_time,</if>
+            <if test="nickName != null">nick_name,</if>
+            <if test="roleName != null">role_name,</if>
+            <if test="phone != null">phone,</if>
+            <if test="status != null">status,</if>
+            <if test="notice != null">notice,</if>
+            <if test="method != null">method,</if>
+            <if test="isBack != null">is_back,</if>
+            <if test="remark != null">remark,</if>
+        </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <foreach collection ="list" item="alarmLog" separator =",">
+            <if test="keyId != null">#{alarmLog.keyId},</if>
+            <if test="createTime != null">#{alarmLog.createTime},</if>
+            <if test="updateTime != null">#{alarmLog.updateTime},</if>
+            <if test="nickName != null">#{alarmLog.nickName},</if>
+            <if test="roleName != null">#{alarmLog.roleName},</if>
+            <if test="phone != null">#{alarmLog.phone},</if>
+            <if test="status != null">#{alarmLog.status},</if>
+            <if test="notice != null">#{alarmLog.notice},</if>
+            <if test="method != null">#{alarmLog.method},</if>
+            <if test="isBack != null">#{alarmLog.isBack},</if>
+            <if test="remark != null">#{alarmLog.remark},</if>
+            </foreach >
+        </trim>
+
+    </insert>
+
     <update id="updateAlarmLog" parameterType="com.zd.algorithm.api.alarm.entity.AlarmLog">
         update alarm_log
         <trim prefix="SET" suffixOverrides=",">

+ 140 - 0
zd-modules/zd-base/src/main/java/com/zd/base/job/task/MessageTask.java

@@ -0,0 +1,140 @@
+package com.zd.base.job.task;
+
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.zd.algorithm.api.alarm.entity.AlarmLog;
+import com.zd.algorithm.api.alarm.feign.RemoteAlarmService;
+import com.zd.common.core.redis.RedisService;
+import com.zd.common.core.utils.DateUtils;
+import com.zd.laboratory.api.constant.SmsMessageConstants;
+import com.zd.laboratory.api.feign.RemoteSmsService;
+import com.zd.model.domain.ResultData;
+import org.apache.http.HttpStatus;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * @Author donggaosheng
+ * @Date 2024-04-03
+ * @description
+ **/
+@Component("messageTask")
+public class MessageTask {
+
+    private static final Logger log = LoggerFactory.getLogger(MessageTask.class);
+
+    @Autowired
+    private RedisService redisService;
+    @Autowired
+    private RemoteSmsService remoteSmsService;
+    @Autowired
+    private RemoteAlarmService remoteAlarmService;
+
+    public void monitorMessageReceipt() {
+        Collection<String> messageKeys = redisService.keys(SmsMessageConstants.ZT_MESSAGE_KEY + "*");
+        if (messageKeys.size() > 0) {
+            List<String> messageIds = new ArrayList<>();
+            messageKeys.forEach(e -> {
+                messageIds.add(e.split(":")[1]);
+            });
+            ResultData resultData = remoteSmsService.getMessageReport();
+            if(resultData.getCode()==HttpStatus.SC_OK){
+                 JSONObject jsonObject=(JSONObject)resultData.getData();
+                 if(jsonObject.getIntValue("code") == HttpStatus.SC_OK){
+                     JSONArray jsonArray = jsonObject.getJSONArray("records");
+                     List<AlarmLog> messageList = new ArrayList();
+                     jsonArray.forEach(json -> {
+                         JSONObject object = (JSONObject) json;
+                         messageKeys.forEach(e -> {
+                             if (object.getString("msg_id").equals(e)) {
+                                 JSONObject jsonKey = redisService.getCacheObject(e);
+                                 AlarmLog alarmLog = new AlarmLog();
+                                 if (object.getString("code").equals(SmsMessageConstants.ZT_VOICE_SUCCESS)) {
+                                     alarmLog.setStatus("成功");
+                                 } else {
+                                     alarmLog.setStatus("失败,"+object.getString("msg"));
+                                 }
+                                 alarmLog.setMethod("短信");
+                                 alarmLog.setCreateTime(DateUtils.getNowDate());
+                                 alarmLog.setPhone(jsonKey.getString("receiver"));
+                                 alarmLog.setIsBack(1);
+                                 alarmLog.setNotice(jsonKey.getString("content"));
+                                 messageList.add(alarmLog);
+                                 String msgIds = object.getString("msg_id");
+                                 boolean isTrue = redisService.deleteObject(SmsMessageConstants.ZT_MESSAGE_KEY + msgIds);
+                                 if (isTrue) {
+                                     log.info(SmsMessageConstants.ZT_MESSAGE_KEY + msgIds + "清理完成");
+                                 }
+                             }
+                         });
+                     });
+                     ResultData result = remoteAlarmService.addBatch(messageList);
+                     if (result.getCode()==HttpStatus.SC_OK) {
+                         log.info("短信回执日志插入成功!");
+                     } else {
+                         log.info("短信回执日志插入失败!");
+                     }
+                 }
+            }else{
+                log.info("短信回执调用失败!");
+            }
+        }
+
+        //语音回执
+        Collection<String> voiceKeys = redisService.keys(SmsMessageConstants.ZT_VOICE_KEY + "*");
+        if (voiceKeys.size() > 0) {
+            List<String> voiceIds = new ArrayList<>();
+            voiceKeys.forEach(e -> {
+                voiceIds.add(e.split(":")[1]);
+            });
+            ResultData resultData = remoteSmsService.getVoiceReport();
+            if(resultData.getCode()==HttpStatus.SC_OK){
+                JSONObject voiceJson=(JSONObject)resultData.getData();
+                if(voiceJson.getIntValue("code") == HttpStatus.SC_OK){
+                    JSONArray voiceArray = voiceJson.getJSONArray("data");
+                    List<AlarmLog> iotVoiceList = new ArrayList();
+                    voiceArray.forEach(json -> {
+                        JSONObject object = (JSONObject) json;
+                        voiceKeys.forEach(e -> {
+                            if (object.getString("msgId").equals(e)) {
+                                JSONObject keyJson = redisService.getCacheObject(e);
+                                //添加日志记录
+                                AlarmLog alarmLog = new AlarmLog();
+                                if (object.getString("code").equals(SmsMessageConstants.ZT_VOICE_SUCCESS)) {
+                                    alarmLog.setStatus("接听成功");
+                                } else {
+                                    alarmLog.setStatus("接听失败,"+object.getString("codeMsg"));
+                                }
+                                String msgId = object.getString("msgId");
+                                alarmLog.setMethod("电话");
+                                alarmLog.setNotice(keyJson.getString("content"));
+                                alarmLog.setPhone(keyJson.getString("receiver"));
+                                alarmLog.setCreateTime(DateUtils.getNowDate());
+                                iotVoiceList.add(alarmLog);
+                                //删除redis的key
+                                boolean isTrue = redisService.deleteObject(SmsMessageConstants.ZT_VOICE_KEY + msgId);
+                                if (isTrue) {
+                                    log.info(SmsMessageConstants.ZT_VOICE_KEY + msgId + "清理完成");
+                                }
+                            }
+                        });
+                    });
+                    ResultData result = remoteAlarmService.addBatch(iotVoiceList);
+                    if (result.getCode()==HttpStatus.SC_OK) {
+                        log.info("语音回执日志插入成功!");
+                    } else {
+                        log.info("语音回执日志插入失败!");
+                    }
+                }else{
+                    log.info("语音回执调用失败!");
+                }
+            }
+        }
+   }
+}

+ 66 - 0
zd-modules/zd-modules-laboratory/src/main/java/com/zd/laboratory/config/MessagePropertiesConfig.java

@@ -0,0 +1,66 @@
+package com.zd.laboratory.config;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.cloud.context.config.annotation.RefreshScope;
+
+/**
+ * @Author donggaosheng
+ * @Date 2024-04-02
+ * @description
+ **/
+@RefreshScope
+@ConfigurationProperties(prefix = "zhutong.sms")
+@EnableConfigurationProperties(MessagePropertiesConfig.class)
+public class MessagePropertiesConfig {
+    //用户名
+    private String userName;
+    //密码
+    private String passWord;
+    //签名
+    private String signature;
+    //第三方模版id
+    private String agentId;
+    //模版内容
+    private String tempContent;
+
+    public String getUserName() {
+        return userName;
+    }
+
+    public void setUserName(String userName) {
+        this.userName = userName;
+    }
+
+    public String getPassWord() {
+        return passWord;
+    }
+
+    public void setPassWord(String passWord) {
+        this.passWord = passWord;
+    }
+
+    public String getSignature() {
+        return signature;
+    }
+
+    public void setSignature(String signature) {
+        this.signature = signature;
+    }
+
+    public String getAgentId() {
+        return agentId;
+    }
+
+    public void setAgentId(String agentId) {
+        this.agentId = agentId;
+    }
+
+    public String getTempContent() {
+        return tempContent;
+    }
+
+    public void setTempContent(String tempContent) {
+        this.tempContent = tempContent;
+    }
+}

+ 41 - 0
zd-modules/zd-modules-laboratory/src/main/java/com/zd/laboratory/controller/LabSmsController.java

@@ -0,0 +1,41 @@
+package com.zd.laboratory.controller;
+
+import com.zd.laboratory.service.ILabMessageService;
+import com.zd.model.domain.ResultData;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * @Author donggaosheng
+ * @Date 2024-04-03
+ * @description
+ **/
+@RestController
+@RequestMapping("/sms")
+public class LabSmsController {
+
+    @Autowired
+    private ILabMessageService labMessageService;
+
+    /**
+     * 获取短信回执报告
+     */
+    @GetMapping("/getMessageReport")
+    @ApiOperation(value = "获取短信回执报告")
+    public ResultData getMessageReport() {
+        return ResultData.success(labMessageService.getMessageReport());
+    }
+
+
+    /**
+     * 获取短信回执报告
+     */
+    @GetMapping("/getVoiceReport")
+    @ApiOperation(value = "获取语音回执报告")
+    public ResultData getVoiceReport() {
+        return ResultData.success(labMessageService.getVoiceReport());
+    }
+}

+ 19 - 0
zd-modules/zd-modules-laboratory/src/main/java/com/zd/laboratory/domain/vo/IotTextMessageVo.java

@@ -0,0 +1,19 @@
+package com.zd.laboratory.domain.vo;
+
+import lombok.Data;
+
+/**
+ * @Author donggaosheng
+ * @Date 2024-02-05
+ * @description
+ **/
+@Data
+public class IotTextMessageVo {
+    //短信变量
+    private String variable;
+    //是否链接
+    private Boolean isUrl;
+    //短信变量值
+    private String value;
+
+}

+ 51 - 0
zd-modules/zd-modules-laboratory/src/main/java/com/zd/laboratory/service/ILabMessageService.java

@@ -0,0 +1,51 @@
+package com.zd.laboratory.service;
+
+import com.alibaba.fastjson.JSONObject;
+import com.zd.laboratory.api.vo.TextMessageVo;
+
+/**
+ * @Author donggaosheng
+ * @Date 2024-02-21
+ * @description
+ **/
+public interface ILabMessageService {
+
+    /**
+     * 发送模版消息
+     * @param textMessageBo
+     * @return
+     */
+     JSONObject sendMessageTemp(TextMessageVo textMessageBo);
+
+
+    /**
+     * 发送语音通知
+     * @param textMessageBo
+     * @return
+     */
+     JSONObject sendMessageVoice(TextMessageVo textMessageBo);
+
+
+
+    /**
+     * 获取余额
+     * @return
+     */
+     JSONObject getMessageBalance();
+
+
+    /**
+     * 获取短信下行报告
+     * @return
+     */
+    JSONObject getMessageReport();
+
+
+    /**
+     * 获取语音下发下行报告
+     * @return
+     */
+    JSONObject getVoiceReport();
+
+
+}

+ 88 - 0
zd-modules/zd-modules-laboratory/src/main/java/com/zd/laboratory/service/impl/LabMessageServiceImpl.java

@@ -0,0 +1,88 @@
+package com.zd.laboratory.service.impl;
+
+import com.alibaba.fastjson.JSONObject;
+import com.zd.common.core.redis.RedisService;
+import com.zd.laboratory.api.vo.TextMessageVo;
+import com.zd.laboratory.config.MessagePropertiesConfig;
+import com.zd.laboratory.service.ILabMessageService;
+import com.zd.laboratory.utils.TextMessageUtils;
+import org.apache.http.HttpStatus;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+/**
+ * @Author donggaosheng
+ * @Date 2024-02-21
+ * @description
+ **/
+@Service
+public class LabMessageServiceImpl implements ILabMessageService {
+
+    private static final Logger log = LoggerFactory.getLogger(LabMessageServiceImpl.class);
+
+    @Autowired
+    private RedisService redisService;
+
+    @Autowired
+    private MessagePropertiesConfig messagePropertiesConfig;
+
+    @Override
+    public JSONObject sendMessageTemp(TextMessageVo textMessageBo) {
+        JSONObject jsonObject= TextMessageUtils.sendSimpleMessageTemp(messagePropertiesConfig.getUserName(),messagePropertiesConfig.getPassWord(),messagePropertiesConfig.getSignature(),messagePropertiesConfig.getAgentId(),messagePropertiesConfig.getTempContent(),textMessageBo.getPhoneList(),textMessageBo.getVariableList());
+        boolean state = Boolean.FALSE;
+        if(jsonObject.getIntValue("code")== HttpStatus.SC_OK){
+            state = Boolean.TRUE;
+            JSONObject redisJson=new JSONObject();
+            redisJson.put("msgId",jsonObject.getString("msgId"));
+//            redisJson.put("title",iotAlarmTemplate.getTemplateName());
+//            redisJson.put("receiver",iotAlarmTemplate.getReceiver());
+            String tempContent=TextMessageUtils.getSimpleTemplateContent(messagePropertiesConfig.getUserName(),messagePropertiesConfig.getPassWord(),messagePropertiesConfig.getTempContent(),textMessageBo.getVariableList());
+            redisJson.put("content",tempContent);
+           // redisService.setCacheObject(IotConstant.ZT_MESSAGE_KEY+jsonObject.getString("msgId"),redisJson);
+        }
+        //添加消息日志
+        String receiver = textMessageBo.getPhoneList().toString();
+        //iotAlarmLogService.addAlarmMessageLog(AlarmTypeEnum.Type.SMS, receiver, null, iotAlarmTemplate.getContent(), null, state, !state ? jsonObject.toJSONString() : null);
+        return jsonObject;
+    }
+
+    @Override
+    public JSONObject sendMessageVoice(TextMessageVo textMessageBo) {
+        JSONObject jsonObject=TextMessageUtils.sendMessageVoice(messagePropertiesConfig.getUserName(),messagePropertiesConfig.getPassWord(),textMessageBo.getTempContent(),textMessageBo.getPhoneList());
+        boolean state = Boolean.FALSE;
+        if(jsonObject.getIntValue("code")== HttpStatus.SC_OK){
+            state = Boolean.TRUE;
+            String msgId=jsonObject.getJSONObject("data").getString("msgId");
+            JSONObject object=new JSONObject();
+            object.put("receiver",textMessageBo.getPhoneList());
+            object.put("content",textMessageBo.getTempContent());
+            object.put("msgId",msgId);
+            //redisService.setCacheObject(IotConstant.ZT_VOICE_KEY+msgId,object);
+        }
+        //添加消息日志
+        // String receiver = textMessageBo.getPhoneList().toString();
+        //iotAlarmLogService.addAlarmMessageLog(AlarmTypeEnum.Type.PHONE, receiver, null, textMessageBo.getTempContent(), null, state, !state ? jsonObject.toJSONString() : null);
+        return jsonObject;
+    }
+
+
+    @Override
+    public JSONObject getMessageBalance() {
+        return TextMessageUtils.getMessageBalance(messagePropertiesConfig.getUserName(),messagePropertiesConfig.getPassWord());
+    }
+
+
+    @Override
+    public JSONObject getMessageReport() {
+        return TextMessageUtils.getMessageReport(messagePropertiesConfig.getUserName(),messagePropertiesConfig.getPassWord());
+    }
+
+    @Override
+    public JSONObject getVoiceReport() {
+        return TextMessageUtils.getVoiceReport(messagePropertiesConfig.getUserName(),messagePropertiesConfig.getPassWord());
+    }
+}

+ 199 - 0
zd-modules/zd-modules-laboratory/src/main/java/com/zd/laboratory/utils/StringAssembler.java

@@ -0,0 +1,199 @@
+package com.zd.laboratory.utils;
+
+import com.zd.laboratory.domain.vo.IotTextMessageVo;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * @Author donggaosheng
+ * @Date 2024-02-05
+ * @description 装配 {} 表达式的值
+ **/
+public class StringAssembler {
+
+    private static final Pattern PLACEHOLDER_PATTERN = Pattern.compile("\\{([^{}]*)\\}");
+
+    //private static final Pattern PATTERN = Pattern.compile("\\$\\{(.+?)\\}");
+
+    public interface Assemble {
+        /**
+         * 装配过程中需要通过{}里面的表达式找到对应的值
+         * @param key {}里面的表达式
+         * @return {}里面的表达式对应的值
+         */
+        String getStringByKey(String key);
+    }
+
+    /**
+     * 装配 {} 格式的字符串
+     * @param str 原始字符串
+     * @param assemble 装配过程中获取值的接口
+     * @return 装配好之后的字符串
+     */
+    public static String assemble(String str, Assemble assemble) {
+        String pattern = "\\{[^}]+}";
+        Pattern r = Pattern.compile(pattern);
+        while (true) {
+            Matcher m = r.matcher(str);
+            if (m.find()) {
+                String key = getKey(m.group());
+                str = m.replaceFirst(assemble.getStringByKey(key));
+            } else {
+                break;
+            }
+        }
+        return str;
+    }
+    /**
+     * 获取 {} 里面的值
+     * @param g {} 表达式
+     * @return {} 里面的值
+     */
+    public static String getKey(String g) {
+        return g.substring(2, g.length() - 1);
+    }
+
+    /**
+     * 替换数据
+     * @param template
+     * @param values
+     * @return
+     */
+    public static String replacePlaceholders(String template, List<Object> values,String domain) {
+            StringBuilder builder = new StringBuilder(template);
+            for (int i = 0; i < values.size(); i++) {
+                String placeholder = "{" + values.get(i).toString() + "}";
+                String value = "{"+values.get(i).toString()+"}";
+                if(placeholder.contains(domain)){
+                    placeholder=values.get(i).toString().replace(domain,"");
+                    value=values.get(i).toString();
+                }
+                int index = builder.indexOf(placeholder);
+                while (index != -1) {
+                    builder.replace(index, index+placeholder.length(), value);
+                    index = builder.indexOf(placeholder, index + value.length());
+                }
+            }
+            return builder.toString();
+        }
+
+    /**
+     * 占位替换
+     * @param template
+     * @param values
+     * @return
+     */
+    public static String replacePlaceholders(String template, List<IotTextMessageVo> values) {
+        if (template == null || values == null) {
+            return template;
+        }
+        StringBuilder builder = new StringBuilder(template);
+        for (int i = 0; i < values.size(); i++) {
+            String placeholder = "{" + values.get(i).getVariable() + "}";
+            String value = values.get(i).getValue();
+            int index = builder.indexOf(placeholder);
+            while (index != -1) {
+                builder.replace(index, index + placeholder.length(), value);
+                index = builder.indexOf(placeholder, index + value.length());
+            }
+        }
+        return builder.toString();
+    }
+    /**
+     * 提取占位符中的值
+     * @param input
+     * @return
+     */
+    public static List<String> extractPlaceholders(String input) {
+        List<String> placeholders = new ArrayList<>();
+        Matcher matcher = PLACEHOLDER_PATTERN.matcher(input);
+        while (matcher.find()) {
+            placeholders.add(matcher.group(1));
+        }
+        return placeholders;
+      }
+
+    public static String commonMatching(String template, List<String> params) {
+        Matcher matcher = PLACEHOLDER_PATTERN.matcher(template);
+        List<String> variables = new ArrayList<>();
+        StringBuffer buffer = new StringBuffer();
+        while (matcher.find()) {
+            String place = matcher.group(1);
+            variables.add(place);
+            matcher.appendReplacement(buffer, place);
+        }
+        matcher.appendTail(buffer);
+        //替换
+        if (!variables.isEmpty() && params != null && !params.isEmpty()) {
+            String temp = buffer.toString();
+            int i = 0;
+            for (String str:variables) {
+                if (i + 1 <= params.size()) {
+                    temp = temp.replace(str, params.get(i));
+                } else {
+                    temp = temp.replace(str, "{"+ str +"}");
+                }
+                i++;
+            }
+            return temp;
+        }
+        return template;
+    }
+
+    /**
+     * 模板变量按变量名精准匹配
+     *
+     * @param template
+     * @param params
+     * @return
+     */
+    public static String preciseMatching(String template, Map<String, String> params) {
+        Matcher matcher = PLACEHOLDER_PATTERN.matcher(template);
+        List<String> variables = new ArrayList<>();
+        StringBuffer buffer = new StringBuffer();
+        while (matcher.find()) {
+            String place = matcher.group(1);
+            variables.add(place);
+            matcher.appendReplacement(buffer, place);
+        }
+        matcher.appendTail(buffer);
+        //替换
+        if (!variables.isEmpty() && params != null && !params.isEmpty()) {
+            String temp = buffer.toString();
+            for (String str:variables) {
+                String param = params.get(str);
+                if (param != null && param.length() > 0) {
+                    temp = temp.replace(str, param);
+                } else {
+                    temp = temp.replace(str, "{"+ str +"}");
+                }
+            }
+            return temp;
+        }
+        return template;
+    }
+
+    public static void main(String[] args) {
+        /*String[] arr = {"实验室发生风险预案","2024-02-28 15:02:25", "111111"};
+        String temp = "${params} 时间 ${time} 描述 ${desc}, 这是一条来自钉钉的告警";
+        String result = commonMatching(temp, Arrays.asList(arr));
+        System.out.println("result : "+ result);*/
+
+        /*String temp = "${params} 时间 ${time} 描述 ${desc}, 这是一条来自钉钉的告警";
+        Map<String, String> map = new HashMap<>();
+        map.put("params", "实验室发生风险预案");
+        map.put("time", "2024-02-28 15:02:25");
+        //map.put("desc", "B101烟感超标");
+        String result = preciseMatching(temp, map);
+        System.out.println("result : "+ result);*/
+
+        String temp = "${params} 时间 ${time} 描述 ${desc}, 这是一条来自钉钉的告警";
+        List<String> list = extractPlaceholders(temp);
+        System.out.println(Arrays.asList(list));
+    }
+}

+ 405 - 0
zd-modules/zd-modules-laboratory/src/main/java/com/zd/laboratory/utils/TextMessageUtils.java

@@ -0,0 +1,405 @@
+package com.zd.laboratory.utils;
+
+import cn.hutool.http.HttpRequest;
+import cn.hutool.http.HttpResponse;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.zd.common.core.utils.HttpUtils;
+import com.zd.common.core.utils.MD5Utils;
+import com.zd.laboratory.domain.vo.IotTextMessageVo;
+import org.apache.http.HttpStatus;
+
+import java.time.ZonedDateTime;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @Author donggaosheng
+ * @Date 2024-02-05
+ * @description 短信发送类
+ **/
+public class TextMessageUtils {
+
+    //将长链接转换成短链
+    private static final String URL_CONVERT="https://api.mix2.zthysms.com/v1/shortLink/add";
+
+    //客户报备需要发送的短信模板,审核通过之后可以直接通过模板进行发送
+    private static final String TEMPLATE_URL="https://api.mix2.zthysms.com/sms/v2/template";
+
+    //通过已报备的短信模板进行发送。
+    private static final String SEND_TEMPLATE_URL="https://api.mix2.zthysms.com/v2/sendSmsTp";
+
+    //接口发送语音通知需要通过此接口发送
+    private static final String VOICE_URL="https://api-gateway.zthysms.com/voice/v1/notice/send";
+
+    //获取账号的语音验证码余额
+    private static final String BALANCE_URL="https://api-gateway.zthysms.com/voice/v1/captcha/balance";
+
+    //短信模板查询列表接口
+    private static final String TEMPLATE_LIST_URL="https://api.mix2.zthysms.com/sms/v2/template/list";
+
+    //查询模版查询接口
+    private static final String TEMPLATE_QUERY_URL="https://api.mix2.zthysms.com/sms/v2/template/query";
+
+    //客户主动抓取短信下行状态报告。通过本接口长短信可以抓取多条状态报告
+    private static final String MESSAGE_BATCH_REPORT="https://api.mix2.zthysms.com/v2/batchReport";
+
+    //获取语音短信回执信息接口。
+    private static final String VOICE_BATCH_REPORT="https://api-gateway.zthysms.com/voice/v1/report";
+
+    //短连接域名
+    private static final String DOMAIN_URL="zt81.cn/";
+
+    //请求数据格式
+    private static final String JSON_TYPE="application/json";
+
+    /**
+     * 将长连接转换成短连接
+     * @param url
+     * @return
+     */
+    public static String convertUrl(String userName,String passWord,String url){
+        JSONObject jsonObject=getCommon(userName,passWord);;
+        jsonObject.put("originalUrl",url);
+        String data=HttpUtils.sendPost(URL_CONVERT,jsonObject.toJSONString(),JSON_TYPE);
+        JSONObject jsonData=JSONObject.parseObject(data);
+        if(jsonData.getIntValue("code")== HttpStatus.SC_OK){
+            return jsonData.getString("shortCode");
+        }
+        return null;
+    }
+
+
+    /**
+     * 客户主动抓取短信下行状态报告。通过本接口长短信可以抓取多条状态报告
+     * @return
+     */
+    public static JSONObject getMessageReport(String userName,String passWord){
+        JSONObject jsonObject=getCommon(userName,passWord);;
+        String data=HttpUtils.sendPost(MESSAGE_BATCH_REPORT,jsonObject.toJSONString(),JSON_TYPE);
+        JSONObject jsonData=JSONObject.parseObject(data);
+        return jsonData;
+    }
+
+
+    /**
+     * 获取语音短信回执信息接口。
+     * @return
+     */
+    public static JSONObject getVoiceReport(String userName,String passWord){
+        HttpResponse reponse = HttpRequest.get(VOICE_BATCH_REPORT)
+                .basicAuth(userName,passWord)
+                .header("Content-Type", "application/json")
+                .charset("utf-8")
+                .execute();
+        System.out.println(reponse.toString());
+        return JSONObject.parseObject(reponse.body());
+    }
+
+
+
+    /**
+     * 通用参数处理方法
+     * @param userName
+     * @param passWord
+     * @return
+     */
+    private static JSONObject getCommon(String userName,String passWord) {
+        String timeStamp = String.valueOf(ZonedDateTime.now().toEpochSecond());
+        String passWd=passwordEncrypt(passWord,timeStamp);
+        JSONObject jsonObject=new JSONObject();
+        jsonObject.put("username",userName);
+        jsonObject.put("password",passWd);
+        jsonObject.put("tKey",timeStamp);
+        return jsonObject;
+    }
+
+    /**
+     * 根据模版信息查询模版内容
+     * @param userName
+     * @param passWord
+     * @param tempId
+     * @return
+     */
+    public static JSONObject queryMessageTemp(String userName,String passWord,Long tempId){
+        JSONObject jsonObject=getCommon(userName,passWord);
+        jsonObject.put("temId",tempId);
+        String data=HttpUtils.sendPost(TEMPLATE_QUERY_URL,jsonObject.toJSONString(),JSON_TYPE);
+        return JSONObject.parseObject(data);
+    }
+
+
+
+    /**
+     * 创建模版
+     * @param tempName
+     * @param tempContent
+     * @param variableList
+     * @return
+     */
+    public static JSONObject createMessageTemp(String userName,String passWord,String tempName, String tempContent, List<IotTextMessageVo> variableList){
+        JSONObject jsonObject=getCommon(userName,passWord);
+        jsonObject.put("temName",tempName);
+        jsonObject.put("temType",2);
+        JSONObject paramJson=new JSONObject();
+        List<Object> textList=new ArrayList<>();
+        variableList.forEach(variable->{
+            paramJson.put(variable.getVariable(),"others");
+            if(variable.getIsUrl()){
+                String url=DOMAIN_URL+"{"+variable.getVariable()+"}";
+                textList.add(url);
+            }else{
+                textList.add(variable.getVariable());
+            }
+        });
+        tempContent=StringAssembler.replacePlaceholders(tempContent,textList,DOMAIN_URL);
+        jsonObject.put("temContent",tempContent);
+        jsonObject.put("paramJson",paramJson);
+        jsonObject.put("remark",tempName);
+        String data=HttpUtils.sendPost(TEMPLATE_URL,jsonObject.toJSONString(),JSON_TYPE);
+        return JSONObject.parseObject(data);
+    }
+
+    /**
+     * 获取模版真实内容
+     * @param tempContent
+     * @param variableList
+     * @return
+     */
+    public static String getTemplateContent(String userName,String passWord,String tempContent,List<IotTextMessageVo> variableList){
+        variableList.forEach(variable->{
+            if(variable.getIsUrl()){
+                String shortUrl= convertUrl(userName,passWord,variable.getValue());
+                variable.setValue(shortUrl);
+            }
+        });
+        tempContent=StringAssembler.replacePlaceholders(tempContent,variableList);
+        return tempContent;
+    }
+
+    /**
+     *
+     * @param userName
+     * @param passWord
+     * @param tempContent
+     * @param variableStrList
+     * @return
+     */
+    public static String getSimpleTemplateContent(String userName,String passWord,String tempContent,List<String> variableStrList){
+        List<IotTextMessageVo> variableList= getCommonList(tempContent,variableStrList);
+        variableList.forEach(variable->{
+            if(variable.getIsUrl()){
+                String shortUrl= convertUrl(userName,passWord,variable.getValue());
+                variable.setValue(shortUrl);
+            }
+        });
+        tempContent=StringAssembler.replacePlaceholders(tempContent,variableList);
+        return tempContent;
+    }
+
+
+    /**
+     * 通用的方法转换
+     * @param tempContent
+     * @param variableStrList
+     * @return
+     */
+    private static List<IotTextMessageVo> getCommonList(String tempContent, List<String> variableStrList){
+        List<IotTextMessageVo> variableList=new ArrayList<>();
+        List<String> tempList=StringAssembler.extractPlaceholders(tempContent);
+        System.out.println("tempList:"+tempList);
+        for(int i=0;i<variableStrList.size();i++){
+            IotTextMessageVo messageVo=new IotTextMessageVo();
+            String value=variableStrList.get(i);
+            if(value.contains("http") || value.contains("https")){
+                messageVo.setIsUrl(Boolean.TRUE);
+            }else{
+                messageVo.setIsUrl(Boolean.FALSE);
+            }
+            messageVo.setVariable(tempList.get(i));
+            messageVo.setValue(value);
+            variableList.add(messageVo);
+        }
+        return variableList;
+    }
+
+
+
+
+    /***
+     * 发送模版消息
+     * @param tpId
+     * @param phoneList
+     * @param variableList
+     * @return
+     */
+    public static JSONObject sendMessageTemp(String userName,String passWord,String signature,String tpId,List<String> phoneList,List<IotTextMessageVo> variableList){
+        JSONObject jsonObject=getCommon(userName,passWord);
+        jsonObject.put("tpId",tpId);
+        jsonObject.put("signature",signature);
+        jsonObject.put("ext","");
+        jsonObject.put("extend","");
+        JSONArray jsonArray=new JSONArray();
+        variableList.forEach(variable->{
+            if(variable.getIsUrl()){
+                variable.setValue(convertUrl(userName,passWord,variable.getValue()));
+            }
+        });
+        phoneList.forEach(phone->{
+            StringBuilder stringBuilder=new StringBuilder("{");
+            JSONObject phoneObject=new JSONObject();
+            phoneObject.put("mobile",phone);
+            variableList.forEach(variable->{
+                String content="\""+variable.getVariable()+"\""+":"+"\""+variable.getValue()+"\"";
+                stringBuilder.append(content).append(",");
+            });
+            stringBuilder.append("}");
+            String strBuilder=stringBuilder.toString();
+            if(strBuilder.length()>2){
+                strBuilder=strBuilder.replace(",}","}");
+            }
+            JSONObject jsonBuilder=JSONObject.parseObject(strBuilder);
+            phoneObject.put("tpContent",jsonBuilder);
+            jsonArray.add(phoneObject);
+        });
+        jsonObject.put("records",jsonArray);
+        String data=HttpUtils.sendPost(SEND_TEMPLATE_URL,jsonObject.toJSONString(),JSON_TYPE);
+        return JSONObject.parseObject(data);
+    }
+
+
+    /***
+     * 发送模版消息
+     * @param tpId
+     * @param phoneList
+     * @param variableStrList
+     * @return
+     */
+    public static JSONObject sendSimpleMessageTemp(String userName,String passWord,String signature,String tpId,String tempContent,List<String> phoneList,List<String> variableStrList) {
+        List<IotTextMessageVo> variableList=getCommonList(tempContent,variableStrList);
+        return sendMessageTemp(userName,passWord,signature,tpId,phoneList,variableList);
+    }
+
+    /**
+     * 发送语音通知
+     * @param content
+     * @param phoneList
+     * @return
+     */
+    public static JSONObject sendMessageVoice(String userName,String passWord,String content,List<String> phoneList){
+        JSONObject jsonObject=new JSONObject();
+        jsonObject.put("content",content);
+        String phoneStr="";
+        for(String phone:phoneList){
+            phoneStr+=phone+",";
+        }
+        if(phoneStr.length()>0){
+            phoneStr=phoneStr.substring(0,phoneStr.length()-1);
+        }
+        jsonObject.put("phone",phoneStr);
+        HttpResponse reponse = HttpRequest.get(VOICE_URL)
+                .basicAuth(userName,passWord).body(jsonObject.toString())
+                .header("Content-Type", "application/json")
+                .charset("utf-8")
+                .execute();
+        System.out.println(reponse.toString());
+        return JSONObject.parseObject(reponse.body());
+    }
+
+    /***
+     * 获取模版列表(只获取审核通过的模版)
+     * @param page
+     * @param size
+     * @return
+     */
+    public static JSONObject getTemplateList(String userName,String passWord,Integer page,Integer size){
+        JSONObject jsonObject=getCommon(userName,passWord);
+        jsonObject.put("page",page);
+        jsonObject.put("size",size);
+        jsonObject.put("auditResult",2);
+        String data=HttpUtils.sendPost(TEMPLATE_LIST_URL,jsonObject.toJSONString(),JSON_TYPE);
+        return JSONObject.parseObject(data);
+    }
+
+
+    /**
+     * 获取短信余额
+     * @return
+     */
+    public static JSONObject getMessageBalance(String userName,String passWord){
+        HttpResponse reponse = HttpRequest.get(BALANCE_URL)
+                .basicAuth(userName,passWord)
+                .header("Content-Type", "application/json")
+                .charset("utf-8")
+                .execute();
+        return JSONObject.parseObject(reponse.body());
+    }
+
+
+
+    /**
+     * 公共的密码加密方式
+     * @param password
+     * @param timeKey
+     * @return
+     */
+    private static String passwordEncrypt(String password,String timeKey){
+        return MD5Utils.encrypt(MD5Utils.encrypt(password)+timeKey);
+    }
+
+
+
+    public static void main(String[] args) {
+        //String  tempContent="{school}-{lab}-{labno}发生{sennor}安全预警,请尽快处理!具体情况请查看zt81.cn/{url}";
+
+        String  tempContent="{lab}预约审批已经通过详情请查看 https://lab.zjznai.com/{url}";
+        String userName="jszjznkeyxgs";
+        String passWord="Qwerqaz2024!@#$";
+        String signature="【忠江实验室安全管理】";
+        String tipId="137664";
+        List<String> phoneList=new ArrayList<>();
+        phoneList.add("18681887295");
+        List<IotTextMessageVo> iotTextMessageVoList=new ArrayList<>();
+        IotTextMessageVo iotTextMessageVo=new IotTextMessageVo();
+        iotTextMessageVo.setVariable("school");
+        iotTextMessageVo.setValue("交大");
+        iotTextMessageVo.setIsUrl(false);
+        IotTextMessageVo iotTextMessageVo1=new IotTextMessageVo();
+        iotTextMessageVo1.setVariable("lab");
+        iotTextMessageVo1.setValue("c111大气污染实验室");
+        iotTextMessageVo1.setIsUrl(false);
+        IotTextMessageVo iotTextMessageVo2=new IotTextMessageVo();
+        iotTextMessageVo2.setVariable("labno");
+        iotTextMessageVo2.setValue("c111-1");
+        iotTextMessageVo2.setIsUrl(false);
+        IotTextMessageVo iotTextMessageVo3=new IotTextMessageVo();
+        iotTextMessageVo3.setVariable("sennor");
+        iotTextMessageVo3.setValue("大气压");
+        iotTextMessageVo3.setIsUrl(false);
+        IotTextMessageVo iotTextMessageVo4=new IotTextMessageVo();
+        iotTextMessageVo4.setVariable("url");
+        iotTextMessageVo4.setValue("http://www.baidu.com/");
+        iotTextMessageVo4.setIsUrl(true);
+        iotTextMessageVoList.add(iotTextMessageVo);
+        iotTextMessageVoList.add(iotTextMessageVo1);
+        iotTextMessageVoList.add(iotTextMessageVo2);
+        iotTextMessageVoList.add(iotTextMessageVo3);
+        iotTextMessageVoList.add(iotTextMessageVo4);
+        //sendMessageTemp(userName,passWord,signature,tipId,phoneList,iotTextMessageVoList);
+        String tempContents="{school}-{lab}-{labno}发生{sennor}安全预警,请尽快处理!具体情况请查看zt81.cn/{url}";
+        //System.out.println(getTemplateContent(userName,passWord,tempContents,iotTextMessageVoList));
+        List<String> variable=new ArrayList<>();
+//        variable.add("交大");
+//        variable.add("b102化工实验室");
+//        variable.add("b102-105263");
+//        variable.add("防爆烟雾");
+//        variable.add("http://www.baidu.com");
+//        System.out.println("variable:"+variable);
+
+        variable.add("b102化工实验室");
+        variable.add("http://www.baidu.com");
+
+        System.out.println(sendSimpleMessageTemp(userName,passWord,signature,tipId,tempContent,phoneList,variable));
+    }
+
+}