feat:消息存储

This commit is contained in:
zuoqinbo 2023-10-19 16:51:48 +08:00
parent dbe25e0850
commit 3f9b2b364d
8 changed files with 169 additions and 46 deletions

View File

@ -8,6 +8,8 @@ import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import java.util.List;
/**
* IM消息管理API
*
@ -25,6 +27,6 @@ public interface MessageApi {
* @return 消息响应
*/
@PostMapping("api/im/message/dispatch")
ApiResult<MessageDispatchResp> sendMessage(@RequestBody @Validated MessageInfo messageInfo);
ApiResult<List<MessageDispatchResp>> sendMessage(@RequestBody @Validated MessageInfo messageInfo);
}

View File

@ -21,20 +21,19 @@ public class MessageInfo {
* 工人端企业端服务器
* WORKERENTERPRISESYSTEM
*/
@NotNull(message = "消息接收端类型")
private String appType;
@NotNull(message = "消息接收端类型列表")
private List<String> appTypeList;
/**
* 用户唯一标识
* 发送用户Id
*/
@NotNull(message = "personId不能为空")
private String personId;
/**
* 消息接收Id列表
* 消息接收用户Id列表
*/
@NotNull(message = "消息接收人Id不能为空")
@NotNull(message = "消息接收用户personIdList不能为空")
private List<String> toPersonIdList;
/**

View File

@ -87,11 +87,6 @@
<groupId>cn.axzo.basics</groupId>
<artifactId>basics-profiles-api</artifactId>
</dependency>
<dependency>
<groupId>cn.axzo.im.center</groupId>
<artifactId>im-center-api</artifactId>
<version>2.0.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>cn.axzo.framework.rocketmq</groupId>
<artifactId>axzo-common-rocketmq</artifactId>
@ -113,10 +108,8 @@
<scope>compile</scope>
</dependency>
<dependency>
<groupId>cn.axzo.im.center</groupId>
<artifactId>im-center-api</artifactId>
<version>2.0.0-SNAPSHOT</version>
<scope>compile</scope>
<groupId>cn.axzo.trade</groupId>
<artifactId>trade-data-security-spring-boot-starter</artifactId>
</dependency>
</dependencies>

View File

@ -0,0 +1,53 @@
package cn.axzo.im.channel.netease;
import lombok.Getter;
import org.apache.commons.lang3.StringUtils;
/**
* 云信IM消息类型
*
* @author zuoqinbo
* @version V1.0
* @date 2023/10/9 16:01
*/
@Getter
public enum NimMsgTypeEnum {
/**
* 模板消息
*/
TEMPLATE("template", "模板消息"),
/**
* 聊天消息
*/
chat("chat", "聊天消息"),
/**
* 通知消息
*/
notify("notify", "通知消息");
private String code;
private String message;
NimMsgTypeEnum(String code, String message) {
this.code = code;
}
public static NimMsgTypeEnum isValidAppType(String appType) {
if (StringUtils.isBlank(appType)) {
return null;
}
NimMsgTypeEnum[] appTypeEnums = NimMsgTypeEnum.values();
for (NimMsgTypeEnum appTypeEnum : appTypeEnums) {
if (appTypeEnum.getCode().equals(appType.toLowerCase())) {
return appTypeEnum;
}
}
return null;
}
}

View File

@ -0,0 +1,39 @@
package cn.axzo.im.channel.netease.dto;
import lombok.Data;
import java.util.Map;
/**
* 网易云信消息Body
*
* @author zuoqinbo
* @version V1.0
* @date 2023/10/19 15:02
*/
@Data
public class MessageBody {
/**
* 模板消息:Template聊天消息:Chat通知消息:Notify
*/
private String msgType;
/**
*消息标题
*/
private String msgHeader;
/**
* 消息内容
*/
private String msgContent;
/**
* 消息通知结构体
*/
private String msgBody;
private Map<String,String> ext;
}

View File

@ -10,6 +10,7 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.List;
/**
* IM消息派发相关
@ -28,8 +29,8 @@ public class MessageController implements MessageApi {
@Override
public ApiResult<MessageDispatchResp> sendMessage(MessageInfo messageInfo) {
MessageDispatchResp messageResp = messageService.sendMessage(messageInfo);
return ApiResult.ok(messageResp);
public ApiResult<List<MessageDispatchResp>> sendMessage(MessageInfo messageInfo) {
List<MessageDispatchResp> messageRespList = messageService.sendMessage(messageInfo);
return ApiResult.ok(messageRespList);
}
}

View File

@ -8,10 +8,14 @@ import cn.axzo.im.center.api.vo.resp.MessageDispatchResp;
import cn.axzo.im.center.api.vo.resp.UserAccountResp;
import cn.axzo.im.center.common.enums.AppTypeEnum;
import cn.axzo.im.channel.IMChannelProvider;
import cn.axzo.im.channel.netease.NimMsgTypeEnum;
import cn.axzo.im.channel.netease.dto.MessageBody;
import cn.axzo.im.channel.netease.dto.MessageDispatchRequest;
import cn.axzo.im.channel.netease.dto.MessageDispatchResponse;
import cn.axzo.im.dao.repository.AccountRegisterDao;
import cn.axzo.im.entity.AccountRegister;
import cn.hutool.json.JSONUtil;
import com.google.common.collect.Maps;
import com.google.common.collect.Lists;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
@ -19,7 +23,6 @@ import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
/**
@ -40,29 +43,30 @@ public class MessageService {
@Resource
private RobotMsgTemplateService robotMsgTemplateService;
@Resource
private AccountRegisterDao accountRegisterDao;
@Resource
private AccountService accountService;
public MessageDispatchResp sendMessage(MessageInfo messageInfo) {
public List<MessageDispatchResp> sendMessage(MessageInfo messageInfo) {
String msgTemplateId = messageInfo.getMsgTemplateId();
MessageDispatchRequest messageRequest = new MessageDispatchRequest();
HashMap messageBody = Maps.newHashMap();
messageBody.putIfAbsent("axzo", messageInfo.getMsgContent());
MessageBody messageBody = new MessageBody();
messageBody.setMsgType(NimMsgTypeEnum.TEMPLATE.getCode());
messageBody.setMsgContent(messageInfo.getMsgContent());
messageBody.setMsgHeader(messageInfo.getMsgHeader());
messageBody.setMsgBody(messageInfo.getMsgTemplateContent());
messageRequest.setBody(JSONUtil.toJsonStr(messageBody));
messageRequest.setFrom(messageInfo.getFromImAccount());
messageRequest.setTo(messageInfo.getToImAccountList().get(0));
if (StringUtils.isBlank(messageInfo.getMsgTemplateId()) &&
StringUtils.isBlank(messageInfo.getFromImAccount())) {
throw new ServiceException("消息模板ID,发送者IM账户,不能同时为空!!");
}
String templateId = messageInfo.getMsgTemplateId();
if (StringUtils.isNotBlank(templateId) && StringUtils.isBlank(messageInfo.getFromImAccount())) {
List<String> robotIdList = robotMsgTemplateService.queryRobotIdByTemplate(templateId);
//设置IM消息发送者账号
if (StringUtils.isNotBlank(msgTemplateId) && StringUtils.isBlank(messageInfo.getPersonId())) {
List<String> robotIdList = robotMsgTemplateService.queryRobotIdByTemplate(msgTemplateId);
if (CollectionUtils.isEmpty(robotIdList)) {
throw new ServiceException("消息模板ID[" + templateId + "],还未维护机器人账户!");
throw new ServiceException("消息模板ID[" + msgTemplateId + "],还未维护机器人账户!");
}
if (CollectionUtils.size(robotIdList) > 1) {
throw new ServiceException("消息模板ID[" + templateId + "],维护了多个机器人账户!");
throw new ServiceException("消息模板ID[" + msgTemplateId + "],关联了多个机器人!");
}
AccountQuery accountQuery = new AccountQuery();
String robotId = robotIdList.get(0);
@ -70,26 +74,57 @@ public class MessageService {
accountQuery.setAppType(AppTypeEnum.SYSTEM.getCode());
List<UserAccountResp> robotImAccountList = accountService.queryAccountInfo(accountQuery);
if (CollectionUtils.isEmpty(robotImAccountList)) {
throw new ServiceException("消息模板ID[" + templateId + "],机器人ID[" + robotId + "]," +
throw new ServiceException("消息模板ID[" + msgTemplateId + "],机器人ID[" + robotId + "]," +
"未查询到机器人IM账户注册信息!");
}
if (CollectionUtils.isNotEmpty(robotImAccountList) && robotImAccountList.size() > 1) {
throw new ServiceException("消息模板ID[" + templateId + "],维护了多个机器人账户!");
throw new ServiceException("消息模板ID[" + msgTemplateId + "],机器人ID[" + robotId + "],存在多个机器人IM账户!");
}
String robotImAccount = robotImAccountList.get(0).getImAccount();
if (StringUtils.isBlank(robotImAccount)) {
throw new ServiceException("消息模板ID[" + templateId + "],机器人ID[" + robotId + "],还未生成IM账户!");
throw new ServiceException("消息模板ID[" + msgTemplateId + "],机器人ID[" + robotId + "],还未生成IM账户!");
}
//目前发送用户为机器人
messageRequest.setFrom(robotImAccount);
} else {
throw new ServiceException("暂未支持普通用户[" + messageInfo.getPersonId() + "]发送IM消息");
}
MessageDispatchResponse response = imChannel.dispatchMessage(messageRequest);
MessageDispatchResp robotInfoResp = BeanMapper.map(response.getData(), MessageDispatchResp.class);
if (StringUtils.isNotBlank(response.getDesc())) {
if (robotInfoResp == null) {
robotInfoResp = new MessageDispatchResp();
//如果消息模板是多端则分开进行发送消息
List<String> appTypeList = messageInfo.getAppTypeList();
List<MessageDispatchResp> messageDispatchResps = Lists.newArrayList();
appTypeList.forEach(appType -> {
if (AppTypeEnum.isValidAppType(appType) == null) {
throw new ServiceException("当前appType,服务器不支持该类型!!");
}
robotInfoResp.setDesc(response.getDesc());
}
return robotInfoResp;
List<String> toPersonList = messageInfo.getToPersonIdList();
List<String> toPersonImList = Lists.newArrayList();
//进行接收者IM账户校验
toPersonList.forEach(personId -> {
AccountRegister accountRegister = accountRegisterDao.lambdaQuery().eq(AccountRegister::getIsDelete, 0)
.eq(AccountRegister::getAccountId, personId)
.eq(AccountRegister::getAppKey, appType).one();
if (accountRegister == null || StringUtils.isEmpty(accountRegister.getImAccount())) {
log.warn("接收用户账户[" + personId + "],appType[" + appType + "],未注册IM账户");
return;
}
toPersonImList.add(accountRegister.getImAccount());
});
if(CollectionUtils.isEmpty(toPersonImList)){
throw new ServiceException("接收端用户无IM账户[" + JSONUtil.toJsonStr(messageInfo.getToPersonIdList()) + "]");
}
//目前是单个用户进行发送
messageRequest.setTo(toPersonImList.get(0));
MessageDispatchResponse response = imChannel.dispatchMessage(messageRequest);
MessageDispatchResp messageDispatchResp = BeanMapper.map(response.getData(), MessageDispatchResp.class);
if (StringUtils.isNotBlank(response.getDesc())) {
if (messageDispatchResp == null) {
messageDispatchResp = new MessageDispatchResp();
}
messageDispatchResp.setDesc(response.getDesc());
}
messageDispatchResps.add(messageDispatchResp);
});
return messageDispatchResps;
}
}

View File

@ -59,6 +59,7 @@ public class RobotMsgTemplateService {
}
public List<RobotMsgTemplateResp> queryRobotMsgTemplateList(String robotId) {
RobotMsgTemplate robotMsgTemplate = robotMsgTemplateDao.lambdaQuery().eq(RobotMsgTemplate::getIsDelete, 0)
.eq(RobotMsgTemplate::getRobotId, robotId).one();