Browse Source

新增了站内信相关代码

dev
vincent 2 months ago
parent
commit
2ad2cc89c7
  1. 55
      zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/common/config/SiqConfig.java
  2. 64
      zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/common/util/siq/SIQHttpUtil.java
  3. 107
      zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/common/util/siq/SIQSignUtil.java
  4. 6
      zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/controller/app/enforcement/AppEnforcementRegistrationController.java
  5. 25
      zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/domain/bo/thirdparty/SIQMsgParamBo.java
  6. 25
      zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/domain/bo/thirdparty/SIQSendMsgBo.java
  7. 17
      zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/domain/bo/thirdparty/ToUserMetaBo.java
  8. 14
      zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/domain/vo/siq/AnalyzeResultVo.java
  9. 12
      zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/domain/vo/siq/LimitPeriod.java
  10. 29
      zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/domain/vo/siq/MessageDetailVo.java
  11. 15
      zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/domain/vo/siq/MessageTaskItemVo.java
  12. 7
      zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/domain/vo/siq/SIQResult.java
  13. 15
      zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/domain/vo/siq/SIQTaskQueryBo.java
  14. 56
      zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/domain/vo/siq/SIQTemplateVo.java
  15. 10
      zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/domain/vo/siq/SendMsgDataVo.java
  16. 17
      zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/domain/vo/siq/SendMsgVo.java
  17. 32
      zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/domain/vo/siq/TaskQueryResultVo.java
  18. 18
      zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/domain/vo/siq/TemplateVariable.java
  19. 5
      zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/service/enterprise/impl/AppEnterpriseLoginServiceImpl.java
  20. 32
      zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/service/thirdparty/ISIQService.java
  21. 116
      zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/service/thirdparty/impl/SIQServiceImpl.java
  22. 1
      zdxt-modules/zdxt-system/src/main/java/org/dromara/system/mapper/SysUserMapper.java
  23. 8
      zdxt-modules/zdxt-system/src/main/java/org/dromara/system/service/ISysUserService.java
  24. 5
      zdxt-modules/zdxt-system/src/main/java/org/dromara/system/service/impl/SysUserServiceImpl.java
  25. 2
      zdxt-modules/zdxt-system/src/main/resources/mapper/system/SysUserMapper.xml
  26. 5
      zdxt-web-server/zdxt-admin-web-server/src/main/resources/application-dev.yml
  27. 118
      zdxt-web-server/zdxt-admin-web-server/src/test/java/com/zdxt/rest/test/siq/SiqControllerTest.java

55
zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/common/config/SiqConfig.java

@ -16,12 +16,27 @@ public class SiqConfig
/** 深i企对接URL */ /** 深i企对接URL */
private String siqUrl; private String siqUrl;
/** 深i企对接URL */
private String siqBaseUrl;
/** 深i企对接code */ /** 深i企对接code */
private String code; private String code;
/** 深i企对接密钥 */ /** 深i企对接密钥 */
private String secretKey; private String secretKey;
/** 深i企应用编号 */
private String appId;
/** 深i企消息应用编号 */
private String msgAppId;
/** 深i企消息应用密钥 */
private String msgSecretKey;
/** 深i企消息模板ID */
private String msgTemplateId;
/** 模拟数据开关 */ /** 模拟数据开关 */
private MockConfig mock = new MockConfig(); private MockConfig mock = new MockConfig();
@ -65,6 +80,38 @@ public class SiqConfig
this.secretKey = secretKey; this.secretKey = secretKey;
} }
public String getAppId() {
return appId;
}
public void setAppId(String appId) {
this.appId = appId;
}
public String getMsgAppId() {
return msgAppId;
}
public void setMsgAppId(String msgAppId) {
this.msgAppId = msgAppId;
}
public String getMsgSecretKey() {
return msgSecretKey;
}
public void setMsgSecretKey(String msgSecretKey) {
this.msgSecretKey = msgSecretKey;
}
public String getMsgTemplateId() {
return msgTemplateId;
}
public void setMsgTemplateId(String msgTemplateId) {
this.msgTemplateId = msgTemplateId;
}
public MockConfig getMock() { public MockConfig getMock() {
return mock; return mock;
} }
@ -72,4 +119,12 @@ public class SiqConfig
public void setMock(MockConfig mock) { public void setMock(MockConfig mock) {
this.mock = mock; this.mock = mock;
} }
public String getSiqBaseUrl() {
return siqBaseUrl;
}
public void setSiqBaseUrl(String siqBaseUrl) {
this.siqBaseUrl = siqBaseUrl;
}
} }

64
zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/common/util/siq/SIQHttpUtil.java

@ -0,0 +1,64 @@
package com.zdxt.enforcementcode.common.util.siq;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import com.alibaba.fastjson.JSONObject;
import com.esotericsoftware.minlog.Log;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Component
public class SIQHttpUtil {
/**
* POST带签名通用请求
* @param url 完整地址
* @param bodyJson 请求体无参数传 ""
* @param secretKey 平台分配的密钥
* @param appId 应用编号
* @return 响应字符串
*/
public static String postWithSign(String url, String bodyJson, String secretKey, String appId) throws Exception {
Log.info("请求URL:{}", url);
Log.info("请求参数:{}", bodyJson);
SIQSignUtil.SignInfo signInfo = SIQSignUtil.generateSign(secretKey, appId, bodyJson);
HttpRequest request = HttpRequest.post(url);
request.header("App-Id", signInfo.getAppId());
request.header("App-Secret", signInfo.getAppSecret());
request.header("Timestamp", String.valueOf(signInfo.getTimestamp()));
request.header("Nonce", signInfo.getNonce());
request.header("Signature", signInfo.getSignature());
request.header("Content-Type", "application/json;charset=utf-8");
request.body(bodyJson);
Map<String, String> headerMap = new HashMap<>();
request.headers().forEach((key, values) -> {
if (values != null && !values.isEmpty()) {
headerMap.put(key, String.join(", ", values));
}
});
System.out.println("========== 完整请求头 ==========");
System.out.println(JSONObject.toJSONString(headerMap, true));
System.out.println("========== 请求头结束 ==========");
Log.info("深I企发送请求body:");
Log.info( bodyJson);
Log.info("深I企发送请求:");
System.out.println(JSONObject.toJSONString(request,true));
HttpResponse response = request.execute();
Log.info("深I企返回参数:{}", JSONObject.toJSONString(response));
if (!response.isOk()) {
response.close();
throw new RuntimeException("调用深I企消息中心接口失败,http状态码:" + response.getStatus());
}
String result = response.body();
response.close();
return result;
}
}

107
zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/common/util/siq/SIQSignUtil.java

@ -0,0 +1,107 @@
package com.zdxt.enforcementcode.common.util.siq;
import com.esotericsoftware.minlog.Log;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.SecureRandom;
/**
* 深i企二期开放接口签名工具
*/
public class SIQSignUtil {
/**
* HmacSHA256加密
* @param key hmac密钥文档要求用nonce
* @param msg 待加密原文
* @return 加密字节数组
*/
public static byte[] hmac256(byte[] key, String msg) throws Exception {
Mac mac = Mac.getInstance("HmacSHA256");
SecretKeySpec secretKeySpec = new SecretKeySpec(key, mac.getAlgorithm());
mac.init(secretKeySpec);
return mac.doFinal(msg.getBytes(StandardCharsets.UTF_8));
}
/**
* SHA256 转小写16进制
*/
public static String sha256Hex(String s) throws Exception {
MessageDigest md = MessageDigest.getInstance("SHA-256");
byte[] d = md.digest(s.getBytes(StandardCharsets.UTF_8));
return DatatypeConverter.printHexBinary(d).toLowerCase();
}
/**
* 生成完整签名对象包含timestampnoncesignature
* @param secretKey 平台分配的密钥对应配置 siq.msgSecretKey
* @param appId 应用编号对应配置 siq.msgAppId
* @param requestBody 请求体完整JSON字符串
* @return 签名信息
*/
public static SignInfo generateSign(String secretKey, String appId, String requestBody) throws Exception {
// 1. 秒级时间戳
long timestamp = System.currentTimeMillis() / 1000;
// 2. 6位随机数字Nonce
String nonce = get6RandomNum();
// 3. 请求体sha256
String bodySha256 = sha256Hex(requestBody);
// 4. 拼接原文:secretKey + timestamp + nonce + bodySha256
String hmacSource = secretKey + timestamp + nonce + bodySha256;
// 5. hmac密钥为nonce字节数组
byte[] hmacResult = hmac256(hmacSource.getBytes(StandardCharsets.UTF_8), nonce);
// 6. 转小写16进制签名
String signature = DatatypeConverter.printHexBinary(hmacResult).toLowerCase();
Log.info("Signature: " + signature);
SignInfo info = new SignInfo();
info.setAppId(appId);
info.setAppSecret(secretKey);
info.setTimestamp(timestamp);
info.setNonce(nonce);
info.setSignature(signature);
return info;
}
/**
* 生成6位随机数字字符串
*/
private static String get6RandomNum() {
SecureRandom random = new SecureRandom();
int num = random.nextInt(900000) + 100000;
return String.valueOf(num);
}
/**
* 签名结果实体用于填充HTTP Header
*/
public static class SignInfo {
private String appId;
private long timestamp;
private String nonce;
private String signature;
private String appSecret;
// getter setter
public String getAppId() { return appId; }
public void setAppId(String appId) { this.appId = appId; }
public long getTimestamp() { return timestamp; }
public void setTimestamp(long timestamp) { this.timestamp = timestamp; }
public String getNonce() { return nonce; }
public void setNonce(String nonce) { this.nonce = nonce; }
public String getSignature() { return signature; }
public void setSignature(String signature) { this.signature = signature; }
public String getAppSecret() {
return appSecret;
}
public void setAppSecret(String appSecret) {
this.appSecret = appSecret;
}
}
}

6
zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/controller/app/enforcement/AppEnforcementRegistrationController.java

@ -422,7 +422,7 @@ public class AppEnforcementRegistrationController extends BaseController {
} }
} }
if (!userIds.isEmpty()) { if (!userIds.isEmpty()) {
sysUserVos = sysUserService.selectUserByIds(userIds, null); sysUserVos = sysUserService.selectUserByIds(userIds);
} }
} }
String tmpUserShow = ""; String tmpUserShow = "";
@ -489,7 +489,7 @@ public class AppEnforcementRegistrationController extends BaseController {
} }
} }
if (!userIds.isEmpty()) { if (!userIds.isEmpty()) {
userBeans1 = sysUserService.selectUserByIds(userIds, null); userBeans1 = sysUserService.selectUserByIds(userIds);
} }
} }
String tmpUserShow1 = ""; String tmpUserShow1 = "";
@ -513,7 +513,7 @@ public class AppEnforcementRegistrationController extends BaseController {
} }
} }
if (!userIds.isEmpty()) { if (!userIds.isEmpty()) {
userBeans2 = sysUserService.selectUserByIds(userIds, null); userBeans2 = sysUserService.selectUserByIds(userIds);
} }
} }
String tmpUserShow2 = ""; String tmpUserShow2 = "";

25
zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/domain/bo/thirdparty/SIQMsgParamBo.java

@ -0,0 +1,25 @@
package com.zdxt.enforcementcode.domain.bo.thirdparty;
import lombok.Data;
import java.util.List;
import java.util.Map;
@Data
public class SIQMsgParamBo {
/**
* 创建人
*/
private String createBy;
/**
* 接收人
*/
private String receiveAccount;
/**
* 内容
*/
private Map<String, String> additionalData;
}

25
zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/domain/bo/thirdparty/SIQSendMsgBo.java

@ -0,0 +1,25 @@
package com.zdxt.enforcementcode.domain.bo.thirdparty;
import lombok.Data;
@Data
public class SIQSendMsgBo {
/**
* 消息任务类型delay定时发送planSendTime 不能
* 为空now立即发送planSendTime 为空
*/
private String sendType;
/**
* 通道0短信 1邮件 2企微 3语音 4公众号 5小程序 6站内信
*/
private Integer sendChannel;
/** 模板授权ID */
private String templateId;
/** 超时秒数 */
private Integer expire;
/** 发送人 */
private String createBy;
/** 接收人数组 */
private ToUserMetaBo[] toUser;
}

17
zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/domain/bo/thirdparty/ToUserMetaBo.java

@ -0,0 +1,17 @@
package com.zdxt.enforcementcode.domain.bo.thirdparty;
import lombok.Data;
import java.util.Map;
@Data
public class ToUserMetaBo {
/** 消息序号,业务自行生成唯一 */
private String messageId;
/** 接收账号 */
private String receiveAccount;
/** 模板变量 */
private Map<String, String> variables;
/** 附加业务数据 */
private Map<String, String> additionalData;
}

14
zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/domain/vo/siq/AnalyzeResultVo.java

@ -0,0 +1,14 @@
package com.zdxt.enforcementcode.domain.vo.siq;
import java.util.List;
public class AnalyzeResultVo {
/** 总数量 */
private Integer totalCount;
/** 成功数量 */
private Integer successCount;
/** 失败数量 */
private Integer failedCount;
/** 失败详情 */
private List<Object> failedResults;
}

12
zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/domain/vo/siq/LimitPeriod.java

@ -0,0 +1,12 @@
package com.zdxt.enforcementcode.domain.vo.siq;
import lombok.Data;
@Data
public class LimitPeriod {
/** 周期类型:日/周/月/年等编码 */
private Integer periodType;
/** 周期数值,如type=月、value=1代表每月 */
private Integer periodValue;
}

29
zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/domain/vo/siq/MessageDetailVo.java

@ -0,0 +1,29 @@
package com.zdxt.enforcementcode.domain.vo.siq;
import lombok.Data;
@Data
public class MessageDetailVo {
/** 消息序号 */
private String messageId;
/** 接收时间 */
private Long createTime;
/** 超期时间 */
private Long expireTime;
/** 发送完成时间 */
private Long sendFinishedTime;
/** 消息发送类型:delay/now */
private String sendType;
/** 接收人姓名 */
private String principalName;
/** 接收人账号 */
private String receiveAccount;
/** 解析结果 */
private String analyzeResult;
/** 解析说明 */
private String analyzeRemarks;
/** 发送状态:0待发送 1成功 2正在发送 3异常 4失败 5取消 */
private Integer sendStatus;
/** 发送消息内容 */
private String sendContent;
}

15
zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/domain/vo/siq/MessageTaskItemVo.java

@ -0,0 +1,15 @@
package com.zdxt.enforcementcode.domain.vo.siq;
import lombok.Data;
import java.util.List;
@Data
public class MessageTaskItemVo {
/** 消息任务唯一标示 */
private String taskId;
/** 发送类型:now立即发送,delay定时发送 */
private String sendType;
/** 解析结果 */
private AnalyzeResultVo analyzeResult;
}

7
zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/domain/vo/siq/SIQResult.java

@ -0,0 +1,7 @@
package com.zdxt.enforcementcode.domain.vo.siq;
public class SIQResult {
String errcode; //响应编码
String errmsg ;//响应编码
String data; //返回的数据
}

15
zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/domain/vo/siq/SIQTaskQueryBo.java

@ -0,0 +1,15 @@
package com.zdxt.enforcementcode.domain.vo.siq;
import lombok.Data;
@Data
public class SIQTaskQueryBo {
/** 消息任务唯一标示 */
private String taskId;
/** 消息序号数组,为空则查询该任务下所有消息 */
private String[] messageIds;
/** 页数 */
private Integer pageNo;
/** 每页大小 */
private Integer pageSize;
}

56
zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/domain/vo/siq/SIQTemplateVo.java

@ -0,0 +1,56 @@
package com.zdxt.enforcementcode.domain.vo.siq;
import java.util.List;
public class SIQTemplateVo {
/**
* 模板授权ID
* 唯一标识模板与应用授权匹配关系
*/
private String templateId;
/** 授权模板名称 */
private String templateName;
/**
* 模板归属渠道分类
* 0-短信1-邮件2-企业微信3-语音4-微信公众号5-小程序6-站内信
*/
private Integer sendChannel;
/**
* 模板授权状态
* 1-正常2-禁用3-冻结
*/
private Integer authorizationStatus;
/** 授权开始时间戳(Long类型秒级时间) */
private Long authorizationTimeForm;
/** 授权截止时间戳(Long类型秒级时间) */
private Long authorizationTimeTo;
/** 当前周期内剩余可发送限额次数 */
private Integer limitNumber;
/** 限额统计方式编码 */
private Integer limitType;
/** 限额周期配置对象 */
private LimitPeriod limitPeriod;
/** 模板展示示例文案 */
private String templateDemo;
/** 模板实际发送正文内容 */
private String templateContent;
/** 模板占位变量参数数组 */
private List<TemplateVariable> templateVariable;
/** 授权说明备注,非必填 */
private String authorizationRemarks;
/** 异常/冻结原因说明,非必填 */
private String errorRemarks;
}

10
zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/domain/vo/siq/SendMsgDataVo.java

@ -0,0 +1,10 @@
package com.zdxt.enforcementcode.domain.vo.siq;
import lombok.Data;
import java.util.List;
@Data
public class SendMsgDataVo {
/** 消息任务列表 */
private List<MessageTaskItemVo> list;
}

17
zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/domain/vo/siq/SendMsgVo.java

@ -0,0 +1,17 @@
package com.zdxt.enforcementcode.domain.vo.siq;
import lombok.Data;
@Data
public class SendMsgVo {
/** 响应编码,0表示成功 */
private Integer errcode;
/** 响应消息 */
private String errmsg;
/** 响应数据 */
private Object data;
public boolean isSuccess() {
return errcode == 0;
}
}

32
zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/domain/vo/siq/TaskQueryResultVo.java

@ -0,0 +1,32 @@
package com.zdxt.enforcementcode.domain.vo.siq;
import lombok.Data;
import java.util.List;
@Data
public class TaskQueryResultVo {
/** 消息任务唯一标示 */
private String taskId;
/** 发送状态:0待发送 1成功 2正在发送 3异常 4失败 5取消 */
private Integer sendStatus;
/** 总消息数量 */
private Integer totalCount;
/** 发送成功数量 */
private Integer sendSuccessCount;
/** 发送失败数量 */
private Integer sendFailedCount;
/** 创建人 */
private String createBy;
/** 创建时间 */
private Long createTime;
/** 消息发送类型:DELAY/now */
private String sendType;
/** 预约发送开始时间 */
private Long planSendTime;
/** 发送完成时间 */
private Long sendFinishedTime;
/** 超时时间(秒) */
private Integer expire;
/** 消息详情列表 */
private MessageDetailVo[] messageDetails;
}

18
zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/domain/vo/siq/TemplateVariable.java

@ -0,0 +1,18 @@
package com.zdxt.enforcementcode.domain.vo.siq;
public class TemplateVariable {
/**
* 变量名称模板内占位标识
*/
private String varName;
/**
* 变量业务描述
*/
private String varDesc;
/**
* 变量示例填充值
*/
private String example;
}

5
zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/service/enterprise/impl/AppEnterpriseLoginServiceImpl.java

@ -142,7 +142,7 @@ public class AppEnterpriseLoginServiceImpl implements IAppEnterpriseLoginService
RLock lock = redissonClient.getLock("siq_login_lock:" + lockKey); RLock lock = redissonClient.getLock("siq_login_lock:" + lockKey);
boolean locked = false; boolean locked = false;
try { try {
locked = lock.tryLock(0, 1, TimeUnit.SECONDS); locked = lock.tryLock(5, 60*5, TimeUnit.SECONDS);
if (!locked) { if (!locked) {
log.info("用户正在登录中,用户信息:{}", userInfo.toJSONString()); log.info("用户正在登录中,用户信息:{}", userInfo.toJSONString());
throw new BaseException("用户正在登录中,请稍后再试"); throw new BaseException("用户正在登录中,请稍后再试");
@ -221,8 +221,7 @@ public class AppEnterpriseLoginServiceImpl implements IAppEnterpriseLoginService
} }
LambdaQueryWrapper<EnterpriseUser> queryWrapper = new LambdaQueryWrapper<>(); LambdaQueryWrapper<EnterpriseUser> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(EnterpriseUser::getLoginName, loginName) queryWrapper.eq(EnterpriseUser::getLoginName, loginName);
.eq(EnterpriseUser::getUserType, userType);
EnterpriseUser existUser = enterpriseUserMapper.selectOne(queryWrapper); EnterpriseUser existUser = enterpriseUserMapper.selectOne(queryWrapper);
Long userId; Long userId;

32
zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/service/thirdparty/ISIQService.java

@ -0,0 +1,32 @@
package com.zdxt.enforcementcode.service.thirdparty;
import com.zdxt.enforcementcode.domain.bo.thirdparty.SIQMsgParamBo;
import com.zdxt.enforcementcode.domain.vo.siq.SIQTaskQueryBo;
import com.zdxt.enforcementcode.domain.vo.siq.SIQTemplateVo;
import com.zdxt.enforcementcode.domain.vo.siq.TaskQueryResultVo;
/**
* 投诉事项Service接口
*
* @author Lion Li
* @date 2026-04-17
*/
public interface ISIQService {
/**
*
* @param templateId
* @return
* @throws Exception
*/
SIQTemplateVo getTemplateById(String templateId);
void sendMsg(SIQMsgParamBo paramBo);
/**
* 按批次查询消息发送结果
* @param queryBo 查询参数
* @return 任务查询结果
*/
TaskQueryResultVo queryTaskResult(SIQTaskQueryBo queryBo);
}

116
zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/service/thirdparty/impl/SIQServiceImpl.java

@ -0,0 +1,116 @@
package com.zdxt.enforcementcode.service.thirdparty.impl;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.esotericsoftware.minlog.Log;
import com.zdxt.enforcementcode.common.config.SiqConfig;
import com.zdxt.enforcementcode.common.util.StringUtils;
import com.zdxt.enforcementcode.common.util.siq.SIQHttpUtil;
import com.zdxt.enforcementcode.domain.bo.thirdparty.SIQMsgParamBo;
import com.zdxt.enforcementcode.domain.bo.thirdparty.SIQSendMsgBo;
import com.zdxt.enforcementcode.domain.bo.thirdparty.ToUserMetaBo;
import com.zdxt.enforcementcode.domain.vo.siq.*;
import com.zdxt.enforcementcode.service.thirdparty.ISIQService;
import jakarta.annotation.Resource;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.exception.base.BaseException;
import org.springframework.stereotype.Service;
import java.util.*;
/**
* 投诉事项Service业务层处理
*
* @author Lion Li
* @date 2026-04-17
*/
@Slf4j
@RequiredArgsConstructor
@Service
public class SIQServiceImpl implements ISIQService {
@Resource
private SiqConfig siqConfig;
@Override
public SIQTemplateVo getTemplateById(String templateId) {
try{
// 拼接查询模板详情接口完整地址
String url = siqConfig.getSiqBaseUrl() + "/mpc/api/messageTemplate/v1/" + templateId + "/get";
// 当前接口无业务请求体,固定传入空字符串参与签名计算
String emptyBody = "";
// 发起带签名POST请求
String respJson = SIQHttpUtil.postWithSign(url, emptyBody, siqConfig.getMsgSecretKey(), siqConfig.getMsgAppId());
// JSON字符串转换为实体对象返回
return JSON.parseObject(respJson, SIQTemplateVo.class);
}catch (Exception e){
throw new BaseException("获取模板详情失败");
}
}
@Override
public void sendMsg(SIQMsgParamBo paramBo) {
try {
if (StringUtils.isBlank(paramBo.getReceiveAccount())) {
throw new BaseException("接收账号不能为空");
}
SIQSendMsgBo sendMsgBo = new SIQSendMsgBo();
sendMsgBo.setSendChannel(6);
sendMsgBo.setSendType("now");
sendMsgBo.setTemplateId(siqConfig.getMsgTemplateId());
sendMsgBo.setExpire(120);
sendMsgBo.setCreateBy(paramBo.getCreateBy());
ToUserMetaBo toUserMetaBo = new ToUserMetaBo();
toUserMetaBo.setMessageId(IdUtil.simpleUUID());
toUserMetaBo.setVariables(paramBo.getAdditionalData());
toUserMetaBo.setReceiveAccount(paramBo.getReceiveAccount());
sendMsgBo.setToUser(new ToUserMetaBo[]{toUserMetaBo});
String url = siqConfig.getSiqBaseUrl() + "/egb/api/mpc/api/messageTask/v1/singleCreate";
String body = JSONObject.toJSONString(sendMsgBo);
log.info("单条发送站内信请求参数: {}", body);
String respJson = SIQHttpUtil.postWithSign(url, body, siqConfig.getMsgSecretKey(), siqConfig.getMsgAppId());
log.info("单条发送站内信响应结果: {}", respJson);
SendMsgVo sendMsg = JSON.parseObject(respJson, SendMsgVo.class);
if(sendMsg.isSuccess()){
SendMsgDataVo sendMsgDataVo = JSON.parseObject(JSON.toJSONString(sendMsg.getData()), SendMsgDataVo.class);
List<MessageTaskItemVo> list = sendMsgDataVo.getList();
if(CollectionUtil.isNotEmpty(list)){
MessageTaskItemVo messageTaskItemVo = list.get(0);
log.info("单条发送站内信成功,taskId: {}", messageTaskItemVo.getTaskId());
}
}
} catch (Exception e) {
log.error("单条发送站内信失败", e);
throw new BaseException("单条发送站内信失败");
}
}
@Override
public TaskQueryResultVo queryTaskResult(SIQTaskQueryBo queryBo) {
try {
if (StringUtils.isBlank(queryBo.getTaskId())) {
throw new BaseException("taskId不能为空");
}
String url = siqConfig.getSiqBaseUrl() + "/egb/api/mpc/api/messageTask/v1/byTaskId/get";
String body = JSONObject.toJSONString(queryBo);
log.info("查询消息任务结果请求参数: {}", body);
String respJson = SIQHttpUtil.postWithSign(url, body, siqConfig.getMsgSecretKey(), siqConfig.getMsgAppId());
log.info("查询消息任务结果响应: {}", respJson);
TaskQueryResultVo sendMsgDataVo = null;
SendMsgVo sendMsg = JSON.parseObject(respJson, SendMsgVo.class);
if (sendMsg.isSuccess()) {
sendMsgDataVo = JSON.parseObject(JSON.toJSONString(sendMsg.getData()), TaskQueryResultVo.class);
Log.info("查询消息任务结果成功,消息: {}", JSONObject.toJSONString(sendMsgDataVo));
}
return sendMsgDataVo;
} catch (Exception e) {
log.error("查询消息任务结果失败", e);
throw new BaseException("查询消息任务结果失败");
}
}
}

1
zdxt-modules/zdxt-system/src/main/java/org/dromara/system/mapper/SysUserMapper.java

@ -151,4 +151,5 @@ public interface SysUserMapper extends BaseMapperPlus<SysUser, SysUserVo> {
List<SysUserVo> selectUserByIds(String[] ids); List<SysUserVo> selectUserByIds(String[] ids);
} }

8
zdxt-modules/zdxt-system/src/main/java/org/dromara/system/service/ISysUserService.java

@ -263,4 +263,12 @@ public interface ISysUserService {
* @return 用户信息 * @return 用户信息
*/ */
SysUserVo getCurrentUser(); SysUserVo getCurrentUser();
/**
* 通过用户ID串查询用户
*
* @param userIds 用户ID串
* @return 用户列表信息
*/
List<SysUserVo> selectUserByIds(List<Long> userIds);
} }

5
zdxt-modules/zdxt-system/src/main/java/org/dromara/system/service/impl/SysUserServiceImpl.java

@ -881,6 +881,11 @@ public class SysUserServiceImpl implements ISysUserService, UserService {
return userBean; return userBean;
} }
@Override
public List<SysUserVo> selectUserByIds(List<Long> userIds) {
return this.baseMapper.selectUserByIds(Convert.toStrArray(userIds));
}
/** /**
* 判断是否为机构 * 判断是否为机构
* @param deptBeanDataSource * @param deptBeanDataSource

2
zdxt-modules/zdxt-system/src/main/resources/mapper/system/SysUserMapper.xml

@ -167,7 +167,7 @@
<select id="selectUserByIds" parameterType="string" resultMap="SysUserResult"> <select id="selectUserByIds" parameterType="string" resultMap="SysUserResult">
<include refid="selectUserVo"/> <include refid="selectUserVo"/>
where u.user_id in where u.user_id in
<foreach item="id" collection="array" open="(" separator="," close=")"> <foreach item="id" collection="ids" open="(" separator="," close=")">
#{id} #{id}
</foreach> </foreach>
</select> </select>

5
zdxt-web-server/zdxt-admin-web-server/src/main/resources/application-dev.yml

@ -291,8 +291,13 @@ siq:
# secretKey: SXRpWEhVN3RHM3ZFbzRQcQ== # secretKey: SXRpWEhVN3RHM3ZFbzRQcQ==
#测试 #测试
siqUrl: https://egbpub.siqhz.com/egb/api/thirdauth siqUrl: https://egbpub.siqhz.com/egb/api/thirdauth
siqBaseUrl: https://egbpub.siqhz.com
code: TEST code: TEST
appId: CE07DEE723E241DFB34D80090A569B12
secretKey: ENC(6+WSjXj7UebpPJGq69e7aVZ1ZIrL9wnPcD+rU5XDFCNYGQM8fVvtcQ==) secretKey: ENC(6+WSjXj7UebpPJGq69e7aVZ1ZIrL9wnPcD+rU5XDFCNYGQM8fVvtcQ==)
msgAppId: CE07DEE723E241DFB34D80090A569B12
msgSecretKey: 0C4E08DCC7DD490E86EF2B79E81691D1
msgTemplateId: 2076972618633498625
# 模拟数据开关(true=使用模拟数据,false=调用真实接口) # 模拟数据开关(true=使用模拟数据,false=调用真实接口)
mock: mock:
enabled: false enabled: false

118
zdxt-web-server/zdxt-admin-web-server/src/test/java/com/zdxt/rest/test/siq/SiqControllerTest.java

@ -0,0 +1,118 @@
package com.zdxt.rest.test.siq;
import cn.dev33.satoken.context.mock.SaTokenContextMockUtil;
import cn.dev33.satoken.stp.parameter.SaLoginParameter;
import cn.dev33.satoken.stp.StpUtil;
import com.zdxt.enforcementcode.common.util.siq.SIQHttpUtil;
import com.zdxt.enforcementcode.domain.bo.thirdparty.SIQMsgParamBo;
import com.zdxt.enforcementcode.domain.bo.thirdparty.SIQSendMsgBo;
import com.zdxt.enforcementcode.domain.bo.thirdparty.ToUserMetaBo;
import com.zdxt.enforcementcode.domain.vo.siq.SIQTaskQueryBo;
import com.zdxt.enforcementcode.domain.vo.siq.SIQTemplateVo;
import com.zdxt.enforcementcode.domain.vo.siq.TaskQueryResultVo;
import com.zdxt.enforcementcode.service.thirdparty.ISIQService;
import org.dromara.ZdxtAdminApplication;
import org.dromara.common.core.domain.model.LoginUser;
import org.dromara.common.satoken.utils.LoginHelper;
import org.junit.jupiter.api.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import java.util.*;
import static org.junit.jupiter.api.Assertions.*;
/**
* ISIQService 深i企消息中心接口测试
* <p>
* 包含三类测试
* 1. getTemplateById - 查询模板详情
* 2. sendMsg - 发送单条消息
* 3. queryTaskResult - 按批次查询发送结果
* </p>
*
* @author zdxt
*/
@SpringBootTest(classes = ZdxtAdminApplication.class)
@AutoConfigureMockMvc
@DisplayName("ISIQService 深i企消息中心接口测试")
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class SiqControllerTest {
@Autowired
private ISIQService siqService;
private static final String TEST_CLIENT_ID = "e5cd7e4891bf95d1d19206ce24a7b32e";
@BeforeEach
public void setUp() {
SaTokenContextMockUtil.setMockContext();
MockHttpServletRequest mockRequest = new MockHttpServletRequest();
mockRequest.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36");
RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(mockRequest));
LoginUser loginUser = new LoginUser();
loginUser.setUserId(1L);
loginUser.setUserType("sys_user");
loginUser.setTenantId("000000");
loginUser.setUsername("test_admin");
loginUser.setNickname("测试管理员");
loginUser.setDeptId("103");
loginUser.setDeptName("测试部门");
loginUser.setRolePermission(new HashSet<>());
loginUser.setMenuPermission(new HashSet<>());
SaLoginParameter param = new SaLoginParameter();
param.setExtra(LoginHelper.CLIENT_KEY, TEST_CLIENT_ID);
LoginHelper.login(loginUser, param);
}
@AfterEach
public void tearDown() {
try {
StpUtil.logout();
} catch (Exception ignored) {
}
RequestContextHolder.resetRequestAttributes();
SaTokenContextMockUtil.clearContext();
}
@DisplayName("发送消息 - 固定参数直接请求深I企接口")
@Test
@Order(7)
public void testSendMsg_smsChannel() throws Exception {
SIQMsgParamBo paramBo = new SIQMsgParamBo();
paramBo.setReceiveAccount("3846cbc20dce4140a42e33254414e02f");
Map<String, String> variables = new HashMap<>();
variables.put("enterName", "深圳市腾讯计算机系统有限公司");
variables.put("dept", "深圳市司法局");
variables.put("time", "2026-07-30");
paramBo.setAdditionalData(variables);
siqService.sendMsg(paramBo);
}
//
// @DisplayName("查询任务结果 - 按taskId查询发送状态")
// @Test
// @Order(8)
// public void testQueryTaskResult() throws Exception {
// SIQTaskQueryBo queryBo = new SIQTaskQueryBo();
// queryBo.setTaskId("a3514ac05fd74d9a92abea91cd2395b9");
// queryBo.setPageNo(1);
// queryBo.setPageSize(10);
//
// TaskQueryResultVo result = siqService.queryTaskResult(queryBo);
// assertNotNull(result, "查询结果不应为空");
// System.out.println("任务ID: " + result.getTaskId());
// System.out.println("发送状态: " + result.getSendStatus());
// System.out.println("总数: " + result.getTotalCount());
// System.out.println("成功数: " + result.getSendSuccessCount());
// System.out.println("失败数: " + result.getSendFailedCount());
// }
}
Loading…
Cancel
Save