feat(REQ-3282): messageApiV2实现

This commit is contained in:
zhanghonghao 2024-12-25 14:05:00 +08:00
parent 1a77c14233
commit 9218cd3dbc
13 changed files with 514 additions and 3 deletions

View File

@ -189,6 +189,10 @@
<version>3.5.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>cn.axzo.msgcenter</groupId>
<artifactId>msg-center-api-v2</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,36 @@
package cn.axzo.msg.center.inside.notices.service.impl.v2;
import cn.axzo.foundation.result.ApiResult;
import cn.axzo.msg.center.api.request.v3.MessageSendReqV3;
import cn.axzo.msg.center.api.response.v3.MessageSendRespV3;
import cn.axzo.msg.center.api.v2.message.feign.MessageApiV2;
import cn.axzo.msg.center.api.v2.message.req.MessageSendV2Req;
import cn.axzo.msg.center.api.v2.message.resp.MessageSendV2Resp;
import cn.axzo.msg.center.inside.notices.service.MessageServiceV3;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.web.bind.annotation.RestController;
/**
* @author : zhanghonghao@axzo.cn
* @since : 2024/12/13
*/
@Slf4j
@RestController
@RequiredArgsConstructor
public class MessageApiV2Controller implements MessageApiV2 {
private final MessageServiceV3 messageServiceV3;
@Override
public ApiResult<MessageSendV2Resp> send(MessageSendV2Req req) {
log.info("MessageAPIV3Controller.send req={}", req);
MessageSendReqV3 sendReqV3 = new MessageSendReqV3();
BeanUtils.copyProperties(req, sendReqV3);
MessageSendRespV3 sendRespV3 = messageServiceV3.send(sendReqV3);
MessageSendV2Resp sendV2Resp = new MessageSendV2Resp();
BeanUtils.copyProperties(sendRespV3, sendV2Resp);
return ApiResult.success(sendV2Resp);
}
}

View File

@ -8,7 +8,7 @@ import cn.axzo.msg.center.domain.entity.MessageGroupNode;
import cn.axzo.msg.center.domain.persistence.BaseEntityExt;
import cn.axzo.msg.center.inside.notices.config.PendingMessageBizConfig;
import cn.axzo.msg.center.service.enums.AppTerminalTypeEnum;
import cn.axzo.orggateway.api.orgteamourelation.OrgTeamOuRelationFeignApi;
import cn.axzo.orggateway.api.orgteamourelation.OrgTeamOuRelationApi;
import cn.axzo.orggateway.api.orgteamourelation.resp.OrgTeamOuRelationResp;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@ -39,7 +39,7 @@ import static java.util.stream.Collectors.toSet;
@RequiredArgsConstructor
public class PendingMessageNewServiceImpl {
private final OrgTeamOuRelationFeignApi orgTeamOuRelationFeignApi;
private final OrgTeamOuRelationApi orgTeamOuRelationApi;
private final PendingMessageBizConfig pendingMessageBizConfig;
private final MessageGroupNodeDao messageGroupNodeDao;
@ -83,7 +83,7 @@ public class PendingMessageNewServiceImpl {
// 2. 查询ouId下面所有的平台班组id当成ouId
if (ouId != 0) {
ApiResult<List<OrgTeamOuRelationResp>> resp =
orgTeamOuRelationFeignApi.teamOuRelationList(ouId);
orgTeamOuRelationApi.teamOuRelationList(ouId);
List<OrgTeamOuRelationResp> relations =
BizAssertions.assertResponse(resp, "获取平台班组id失败");
relations.stream()

47
msg-center-api-v2/pom.xml Normal file
View File

@ -0,0 +1,47 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>msg-center</artifactId>
<groupId>cn.axzo.msgcenter</groupId>
<version>${revision}</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>msg-center-api-v2</artifactId>
<version>${msg-center-api-v2-version}</version>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>cn.axzo.foundation</groupId>
<artifactId>common-lib</artifactId>
<version>2.0.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
</dependency>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,14 @@
package cn.axzo.msg.center.api.v2.config;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.Configuration;
/**
* @author : zhanghonghao@axzo.cn
* @since : 2024/12/10
*/
@Configuration
@EnableFeignClients(basePackages = "cn.axzo.msg.center.api.v2.**.feign")
public class MsgCenterApiV2Config {
}

View File

@ -0,0 +1,20 @@
package cn.axzo.msg.center.api.v2.message.feign;
import cn.axzo.foundation.result.ApiResult;
import cn.axzo.msg.center.api.v2.message.req.MessageSendV2Req;
import cn.axzo.msg.center.api.v2.message.resp.MessageSendV2Resp;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import javax.validation.Valid;
@FeignClient(
value = "msg-center",
url = "${axzo.service.msg-center:http://msg-center:8080}")
public interface MessageApiV2 {
@PostMapping(value = "api/message/v2/send")
ApiResult<MessageSendV2Resp> send(@RequestBody @Valid MessageSendV2Req req);
}

View File

@ -0,0 +1,167 @@
package cn.axzo.msg.center.api.v2.message.req;
import cn.axzo.basics.common.util.AssertUtil;
import com.alibaba.fastjson.JSONObject;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
/**
* @author yanglin
*/
@Setter
@Getter
@Slf4j
public class MessageSendV2Req implements Serializable {
/**
* 发送待办时, channelParams key, 传值 {@link PendingSendInfo}
*/
public static final String CHANNEL_PENDING = "channel_pending";
/**
* 发起者
* <p>如果是平台则发起人为空
*/
private PersonV2DTO sender;
/**
* 接收者列表
*/
@NotNull(message = "接收者列表不能为空")
private List<PersonV2DTO> receivers;
/**
* 业务事件code
* oms->消息模板 配置
*/
@NotBlank(message = "业务事件code不能为空")
private String bizEventMappingCode;
/**
* 关联业务唯一标识
* 例如: 请假申请的编号
*/
private String bizCode;
/**
* 业务扩展参数-JSON字符串格式
*/
private JSONObject bizExtParams;
/**
* 路由参数-JSON字符串格式
*/
private JSONObject routerParams;
/**
* 发送者项目部ID
*/
private Long senderWorkspaceId;
/**
* 发送者企业ID
*/
private Long senderOuId;
/**
* 接收者项目部ID
*/
private Long receiversWorkspaceId;
/**
* 接收者企业ID
* <p>如果是工人则所在企业可以为空其它均必传
*/
private Long receiversOuId;
/**
* 接收者(消息)所属组织类型
*/
private Integer receiversOrgType;
/**
* 副标题
*/
private String subtitle;
/**
* 渠道参数
*/
private JSONObject channelParams;
public void addChannelParam(String key, Object object) {
if (channelParams == null) {
channelParams = new JSONObject();
}
channelParams.put(key, object);
}
public <T> T getChannelParam(String key, Class<T> asType) {
if (channelParams == null) {
return null;
}
if (!channelParams.containsKey(key)) {
return null;
}
return channelParams.getObject(key, asType);
}
public Collection<PersonV2DTO> distinctReceivers() {
if (receivers == null) {
return Collections.emptySet();
}
HashMap<Long, PersonV2DTO> personId2Person = new HashMap<>();
for (PersonV2DTO receiver : receivers) {
if (!personId2Person.containsKey(receiver.getId())) {
personId2Person.put(receiver.getId(), receiver);
}
}
return personId2Person.values();
}
public List<PersonV2DTO> receivers() {
if (receivers == null) {
return Collections.emptyList();
}
return receivers;
}
public Long determineReceiversOuId() {
return receiversOuId == null ? 0L : receiversOuId;
}
public Long determineReceiversWorkspaceId() {
return receiversWorkspaceId == null ? 0L : receiversWorkspaceId;
}
public String determineBizCode() {
return bizCode == null ? "" : bizCode;
}
public void validate() {
AssertUtil.notNull(bizEventMappingCode, "bizEventCode不能为空");
AssertUtil.notEmpty(receivers, "receivers不能为空");
for (PersonV2DTO receiver : receivers) {
AssertUtil.notNull(receiver.getId(), "接收者ID不能为空");
if (receiver.getId() <= 0)
log.warn("接收者ID <= 0, request={}", this);
// 去掉这个校验
//AssertUtil.isFalse(receiver.getId() <= 0, "接收者ID必须>=0");
}
}
@Override
public String toString() {
return JSONObject.toJSONString(this);
}
}

View File

@ -0,0 +1,59 @@
package cn.axzo.msg.center.api.v2.message.req;
import lombok.*;
import java.io.Serializable;
/**
* @author yanglin
*/
@Getter
@Setter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class PersonV2DTO implements Serializable {
private static final long serialVersionUID = 1231840051925115741L;
public PersonV2DTO(Long id) {
this.id = id;
}
public PersonV2DTO(Long id, String name) {
this.id = id;
this.name = name;
}
/**
* 自然人id
*/
private Long id;
/**
* 姓名
*/
private String name;
/**
* IM消息接收模型, 可以为空
* <p>优先使用这里的ouId, 如果这里没有传, 就使用 {@link cn.axzo.msg.center.api.request.v3.MessageSendReqV3} 中的相应的信息
*/
private ReceiveModel imReceiveModel;
@Data
@NoArgsConstructor
@AllArgsConstructor
public static class ReceiveModel {
/**
* 接收者单位id
*/
private Long ouId;
/**
* 接收者项目部id
*/
private Long workspaceId;
}
}

View File

@ -0,0 +1,33 @@
package cn.axzo.msg.center.api.v2.message.resp;
import com.alibaba.fastjson.JSON;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import java.io.Serializable;
/**
* @author yanglin
*/
@Setter
@Getter
@NoArgsConstructor
@AllArgsConstructor
public class MessageSendResultV2 implements Serializable {
/**
* 接收者id
*/
private Long receiverPersonId;
/**
* 渠道结果id
*/
private Long resultId;
@Override
public String toString() {
return JSON.toJSONString(this);
}
}

View File

@ -0,0 +1,48 @@
package cn.axzo.msg.center.api.v2.message.resp;
import com.alibaba.fastjson.JSON;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.*;
/**
* @author yanglin
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class MessageSendV2Resp implements Serializable {
/**
* 这次批量发送的批次号, 如果配置了多个模版多个渠道, 可以用批次号串联起来
*/
private String batchNo;
/**
* 模版code -> 模版发送结果
*/
private Map<String, TemplateSendV2Result> templateCode2SendResult;
public void addResult(TemplateSendV2Result result) {
templateCode2SendResult.put(result.getTemplateCode(), result);
}
public Optional<TemplateSendV2Result> findTemplateSendResult(String templateCode) {
return Optional.ofNullable(templateCode2SendResult.get(templateCode));
}
public Set<String> templateCodes() {
return new HashSet<>(templateCode2SendResult.keySet());
}
public Map<String, TemplateSendV2Result> templateSendResults() {
return Collections.unmodifiableMap(templateCode2SendResult);
}
@Override
public String toString() {
return JSON.toJSONString(this);
}
}

View File

@ -0,0 +1,74 @@
package cn.axzo.msg.center.api.v2.message.resp;
import com.alibaba.fastjson.JSON;
import lombok.Data;
import java.io.Serializable;
import java.util.*;
/**
* @author yanglin
*/
@Data
public class TemplateSendV2Result implements Serializable {
/**
* 模版编码
*/
private String templateCode;
/**
* 渠道
* <p>NOTIFICATION: 通知, PENDING: 待办
*/
private String channel;
/**
* 接收者personId -> 接收人发送结果
* key: string, 兼容json的key必须为string类型
*/
private Map<String, MessageSendResultV2> receiverPersonId2SendResult;
@SuppressWarnings("unused")
public TemplateSendV2Result() {
}
public TemplateSendV2Result(String templateCode, String channel) {
this.templateCode = templateCode;
this.channel = channel;
this.receiverPersonId2SendResult = new HashMap<>();
}
public void addResult(MessageSendResultV2 result) {
if (receiverPersonId2SendResult == null)
// 序列化问题
throw new RuntimeException("需要通过构造函数初始化receiverPersonId2SendResult");
String receiverPersonId = String.valueOf(result.getReceiverPersonId());
receiverPersonId2SendResult.put(receiverPersonId, result);
}
public Optional<MessageSendResultV2> findResultByReceiver(Long receiverPersonId) {
if (receiverPersonId2SendResult == null)
return Optional.empty();
if (receiverPersonId == null)
return Optional.empty();
String strReceiverPersonId = String.valueOf(receiverPersonId);
return Optional.ofNullable(receiverPersonId2SendResult.get(strReceiverPersonId));
}
/**
* 返回的数量不一定和发送请求中的receivers数量一致, 发送的时候根据receiver的personId去了重
* <p>推荐使用 {@link #findResultByReceiver}, 根据接收者获取发送结果
*
* @return 所有的发送结果
*/
public Collection<MessageSendResultV2> messageSendResults() {
if (receiverPersonId2SendResult == null)
return Collections.emptyList();
return new ArrayList<>(receiverPersonId2SendResult.values());
}
@Override
public String toString() {
return JSON.toJSONString(receiverPersonId2SendResult);
}
}

View File

@ -0,0 +1,2 @@
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
cn.axzo.msg.center.api.v2.config.MsgCenterApiV2Config

View File

@ -24,6 +24,7 @@
<module>start</module>
<module>msg-center-dal</module>
<module>msg-center-domain</module>
<module>msg-center-api-v2</module>
</modules>
<properties>
@ -32,6 +33,7 @@
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<revision>1.0.0-SNAPSHOT</revision>
<msg-center-api-version>1.0.1-SNAPSHOT</msg-center-api-version>
<msg-center-api-v2-version>1.0.1-SNAPSHOT</msg-center-api-v2-version>
<axzo-bom.version>2.0.0-SNAPSHOT</axzo-bom.version>
<axzo-dependencies.version>2.0.0-SNAPSHOT</axzo-dependencies.version>
<lombok.version>1.18.22</lombok.version>
@ -99,6 +101,11 @@
<artifactId>annotations</artifactId>
<version>${jetbrains.version}</version>
</dependency>
<dependency>
<groupId>cn.axzo.msgcenter</groupId>
<artifactId>msg-center-api-v2</artifactId>
<version>${msg-center-api-v2-version}</version>
</dependency>
</dependencies>
</dependencyManagement>