Commit 3003b9e8 by hweeeeeei

添加服务端rest-api下发消息

parent 70414f9b
package com.wecloud.im.controller.serverapi;
import com.wecloud.im.entity.ImApplication;
import com.wecloud.im.param.add.ImMsgSendToOnlineClient;
import com.wecloud.im.param.add.ImMsgSendRestApi;
import com.wecloud.im.param.add.ImMsgSendRestResult;
import com.wecloud.im.service.ImApplicationService;
import com.wecloud.im.service.ImMessageService;
import io.geekidea.springbootplus.framework.common.api.ApiCode;
......@@ -34,12 +35,36 @@ public class ApiImMessageController extends BaseController {
@Autowired
private ImMessageService imMessageService;
/**
* 向会话中的client下发消息
*/
@PostMapping("/send")
@ApiOperation(value = "向会话中的client下发消息", notes = "应用服务端向某会话中所有client下发消息, 会保存进离线消息, 在线和离线client能收到,离线有系统推送")
public ApiResult<ImMsgSendRestResult> restApiImMessageSendChat(@RequestBody ImMsgSendRestApi imMsgSendRestApi, @RequestHeader String appkey, @RequestHeader String appSecret) throws Exception {
// 根据appKey从数据库查询密钥
ImApplication imApplication = imApplicationService.getOneByAppKey(appkey);
if (imApplication == null) {
return ApiResult.result(ApiCode.FAIL, null);
}
// 校验appkey 和appSecret
if (!imApplication.getAppSecret().equals(appSecret)) {
return ApiResult.result(ApiCode.FAIL, null);
}
return imMessageService.restApiImMessageSend(imMsgSendRestApi, imApplication);
}
/**
* 向会话中在线client,下发透传消息
*/
@PostMapping("/sendToOnlineClient")
@PostMapping("/sendToOnline")
@ApiOperation(value = "向会话中在线client,下发透传消息", notes = "应用服务端向某会话中所有client下发透传消息, 不会保存进离线消息, 仅在线client能收到")
public ApiResult<Boolean> restApiImMessageSend(@RequestBody ImMsgSendToOnlineClient imMsgSendToOnlineClient, @RequestHeader String appkey, @RequestHeader String appSecret) throws Exception {
public ApiResult<ImMsgSendRestResult> restApiImMessageSend(@RequestBody ImMsgSendRestApi imMsgSendRestApi, @RequestHeader String appkey, @RequestHeader String appSecret) throws Exception {
// return imMessageService.updateMsgWithdrawById(imMsgRecall);
......@@ -55,7 +80,7 @@ public class ApiImMessageController extends BaseController {
return ApiResult.result(ApiCode.FAIL, null);
}
return imMessageService.restApiImMessageSend(imMsgSendToOnlineClient, imApplication);
return imMessageService.restApiImMessageSendOnline(imMsgSendRestApi, imApplication);
}
......
......@@ -18,19 +18,17 @@ import java.util.HashMap;
@Accessors(chain = true)
@EqualsAndHashCode(callSuper = true)
@ApiModel(value = "ImMsgSendToOnlineClient")
public class ImMsgSendToOnlineClient extends BaseEntity {
public class ImMsgSendRestApi extends BaseEntity {
private static final long serialVersionUID = 1L;
// @ApiModelProperty(value = "自定义透传内容", required = true)
// private String content;
@ApiModelProperty(value = "发送者id", required = true)
private String senderClient;
@ApiModelProperty(value = "自定义透传内容 ,为任意参数名称和类型的对象,供开发者扩展使用。", required = true)
@ApiModelProperty(value = "自定义内容 ,为任意参数名称和类型的对象,供开发者扩展使用。", required = true)
private HashMap content;
@ApiModelProperty(value = "会话id", required = true)
private Long conversationId;
// @ApiModelProperty(value = "会话id", required = true)
// private Long conversationId;
}
package com.wecloud.im.param.add;
import io.geekidea.springbootplus.framework.common.entity.BaseEntity;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
* 服务端api消息下发
*
* @author wei
*/
@Data
@Accessors(chain = true)
@EqualsAndHashCode(callSuper = true)
@ApiModel(value = "ImMsgSendRestResult")
public class ImMsgSendRestResult extends BaseEntity {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "消息id", required = true)
private Long msgId;
}
......@@ -5,7 +5,8 @@ import com.wecloud.im.entity.ImClient;
import com.wecloud.im.entity.ImMessage;
import com.wecloud.im.param.ImHistoryMessagePageParam;
import com.wecloud.im.param.add.ImMsgRecall;
import com.wecloud.im.param.add.ImMsgSendToOnlineClient;
import com.wecloud.im.param.add.ImMsgSendRestApi;
import com.wecloud.im.param.add.ImMsgSendRestResult;
import com.wecloud.im.param.add.ImMsgUpdate;
import com.wecloud.im.vo.ImMessageOfflineListVo;
import com.wecloud.im.vo.OfflineMsgDto;
......@@ -27,10 +28,12 @@ public interface ImMessageService extends BaseService<ImMessage> {
/**
* 下发透传消息
*
* @param imMsgSendToOnlineClient
* @param imMsgSendRestApi
* @return
*/
ApiResult<Boolean> restApiImMessageSend(ImMsgSendToOnlineClient imMsgSendToOnlineClient, ImApplication imApplication);
ApiResult<ImMsgSendRestResult> restApiImMessageSendOnline(ImMsgSendRestApi imMsgSendRestApi, ImApplication imApplication);
ApiResult<ImMsgSendRestResult> restApiImMessageSend(ImMsgSendRestApi imMsgSendRestApi, ImApplication imApplication);
ImMessage saveImMessage(ImApplication imApplication, ImClient imClientSender, Long toConversationId, long messageId, String content);
......
......@@ -11,17 +11,21 @@ import com.wecloud.im.entity.ImApplication;
import com.wecloud.im.entity.ImClient;
import com.wecloud.im.entity.ImConversation;
import com.wecloud.im.entity.ImConversationMembers;
import com.wecloud.im.entity.ImInbox;
import com.wecloud.im.entity.ImMessage;
import com.wecloud.im.entity.ImMessageOnlineSend;
import com.wecloud.im.mapper.ImMessageMapper;
import com.wecloud.im.param.ImHistoryMessagePageParam;
import com.wecloud.im.param.add.ImMsgRecall;
import com.wecloud.im.param.add.ImMsgSendToOnlineClient;
import com.wecloud.im.param.add.ImMsgSendRestApi;
import com.wecloud.im.param.add.ImMsgSendRestResult;
import com.wecloud.im.param.add.ImMsgUpdate;
import com.wecloud.im.service.ImApplicationService;
import com.wecloud.im.service.ImClientBlacklistService;
import com.wecloud.im.service.ImClientService;
import com.wecloud.im.service.ImConversationMembersService;
import com.wecloud.im.service.ImConversationService;
import com.wecloud.im.service.ImInboxService;
import com.wecloud.im.service.ImMessageService;
import com.wecloud.im.vo.ImMessageOfflineListVo;
import com.wecloud.im.vo.OfflineMsgDto;
......@@ -35,6 +39,7 @@ import io.geekidea.springbootplus.framework.common.api.ApiResult;
import io.geekidea.springbootplus.framework.common.service.impl.BaseServiceImpl;
import io.geekidea.springbootplus.framework.core.pagination.PageInfo;
import io.geekidea.springbootplus.framework.core.pagination.Paging;
import io.geekidea.springbootplus.framework.shiro.util.SnowflakeUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
......@@ -43,6 +48,7 @@ import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
/**
......@@ -57,44 +63,80 @@ public class ImMessageServiceImpl extends BaseServiceImpl<ImMessageMapper, ImMes
// private static final JsonMapper JSON_MAPPER = new JsonMapper();
public static final String PUSH_KEY = "push";
public static final String MSG_ID = "msgId";
private static final String TO_CONVERSATION_KEY = "toConversation";
private static final JsonMapper JSON_MAPPER = new JsonMapper();
@Autowired
private ImMessageMapper imMessageMapper;
private ImClientBlacklistService imClientBlacklistService;
@Autowired
private ImClientService imClientService;
private WriteDataService writeDataService;
@Autowired
private ImConversationService imConversationService;
private ImMessageService imMessageService;
@Autowired
private PushTask pushTask;
private ImInboxService imInboxService;
@Autowired
private ImApplicationService imApplicationService;
@Autowired
private ImConversationMembersService imConversationMembersService;
@Autowired
private WriteDataService writeDataService;
private ImClientService imClientService;
@Autowired
private PushTask systemPush;
@Autowired
private ImMessageMapper imMessageMapper;
@Autowired
private ImConversationService imConversationService;
@Autowired
private PushTask pushTask;
@Override
@Transactional(rollbackFor = Exception.class)
public ApiResult<Boolean> restApiImMessageSend(ImMsgSendToOnlineClient imMsgSendToOnlineClient, ImApplication imApplication) {
public ApiResult<ImMsgSendRestResult> restApiImMessageSendOnline(ImMsgSendRestApi imMsgSendRestApi, ImApplication imApplication) {
if (imApplication == null) {
log.info("imApplication为空");
return ApiResult.result(ApiCode.FAIL, new ImMsgSendRestResult());
}
// 查询发送者client
ImClient imClientSender = getClientSender(imMsgSendRestApi.getSenderClient(), imApplication);
if (imClientSender == null) {
return ApiResult.result(ApiCode.FAIL, new ImMsgSendRestResult());
}
// 获取会话id
if (imMsgSendRestApi.getContent().get(TO_CONVERSATION_KEY) == null) {
return ApiResult.result(ApiCode.FAIL, new ImMsgSendRestResult());
}
Long toConversationId = Long.valueOf(imMsgSendRestApi.getContent().get(TO_CONVERSATION_KEY).toString());
// 查询该会话所有成员
List<ImConversationMembers> membersList = imConversationMembersService.list(
new QueryWrapper<ImConversationMembers>().lambda()
.eq(ImConversationMembers::getFkConversationId, imMsgSendToOnlineClient.getConversationId())
.eq(ImConversationMembers::getFkConversationId, toConversationId)
.notIn(ImConversationMembers::getFkClientId, imClientSender.getId())
);
if (membersList.isEmpty()) {
log.info("membersList为空,toConversationId:" + imMsgSendToOnlineClient.getConversationId());
return ApiResult.fail();
log.info("membersList为空,toConversationId:" + toConversationId);
return ApiResult.result(ApiCode.FAIL, new ImMsgSendRestResult());
}
imMsgSendRestApi.getContent().remove(TO_CONVERSATION_KEY);
ImApiMessageOnlineSend imApiMessageOnlineSend = new ImApiMessageOnlineSend();
imApiMessageOnlineSend.setCreateTime(new Date());
......@@ -102,14 +144,15 @@ public class ImMessageServiceImpl extends BaseServiceImpl<ImMessageMapper, ImMes
JsonMapper jsonMapper = new JsonMapper();
try {
String attributes = jsonMapper.writeValueAsString(imMsgSendToOnlineClient.getContent());
String attributes = jsonMapper.writeValueAsString(imMsgSendRestApi.getContent());
imApiMessageOnlineSend.setContent(attributes);
} catch (JsonProcessingException e) {
e.printStackTrace();
return ApiResult.fail();
return ApiResult.result(ApiCode.FAIL, new ImMsgSendRestResult());
}
imApiMessageOnlineSend.setConversationId(imMsgSendToOnlineClient.getConversationId());
imApiMessageOnlineSend.setConversationId(toConversationId);
// 遍历发送
......@@ -136,9 +179,159 @@ public class ImMessageServiceImpl extends BaseServiceImpl<ImMessageMapper, ImMes
}
ImMsgSendRestResult data = new ImMsgSendRestResult();
data.setMsgId(1L);
return ApiResult.ok(data);
}
private ImClient getClientSender(String clientUniId, ImApplication imApplication) {
ImClient imClientSender = imClientService.getOne(new QueryWrapper<ImClient>().lambda()
.eq(ImClient::getFkAppid, imApplication.getId())
.eq(ImClient::getClientId, clientUniId));
if (imClientSender == null) {
log.info("imClientSender为空");
return null;
}
return imClientSender;
}
@Override
public ApiResult<ImMsgSendRestResult> restApiImMessageSend(ImMsgSendRestApi imMsgSendRestApi, ImApplication imApplication) {
if (imApplication == null) {
log.info("imApplication为空");
return ApiResult.result(ApiCode.FAIL, new ImMsgSendRestResult());
}
// 查询发送者client
ImClient imClientSender = getClientSender(imMsgSendRestApi.getSenderClient(), imApplication);
if (imClientSender == null) {
return ApiResult.result(ApiCode.FAIL, new ImMsgSendRestResult());
}
// 获取会话id
HashMap dataHashMap = (HashMap) imMsgSendRestApi.getContent().get("data");
if (dataHashMap.get(TO_CONVERSATION_KEY) == null) {
return ApiResult.result(ApiCode.FAIL, new ImMsgSendRestResult());
}
Long toConversationId = Long.valueOf(dataHashMap.get(TO_CONVERSATION_KEY).toString());
// 查询该会话所有成员
List<ImConversationMembers> membersList = imConversationMembersService.list(
new QueryWrapper<ImConversationMembers>().lambda()
.eq(ImConversationMembers::getFkConversationId, toConversationId)
.notIn(ImConversationMembers::getFkClientId, imClientSender.getId())
);
if (membersList.isEmpty()) {
log.info("membersList为空,toConversationId:" + toConversationId);
return ApiResult.result(ApiCode.FAIL, new ImMsgSendRestResult());
}
dataHashMap.remove(TO_CONVERSATION_KEY);
// 获取自定义推送字段
HashMap<String, Object> pushMap = null;
if (dataHashMap.get(PUSH_KEY) != null) {
pushMap = (HashMap<String, Object>) dataHashMap.get(PUSH_KEY);
dataHashMap.remove(PUSH_KEY);
}
String content = null;
try {
content = JSON_MAPPER.writeValueAsString(imMsgSendRestApi.getContent());
} catch (JsonProcessingException e) {
e.printStackTrace();
}
// 判断为单聊
if (membersList.size() == 1) {
// 拉黑逻辑
if (black(imClientSender, membersList)) {
return ApiResult.result(ApiCode.FAIL, new ImMsgSendRestResult());
}
}
// 生成消息id
long messageId = SnowflakeUtil.getId();
// 保存消息至消息表
ImMessage imMessage = imMessageService.saveImMessage(imApplication, imClientSender, toConversationId, messageId, content);
// 封装响应的实体
ImMessageOnlineSend imMessageOnlineSend = new ImMessageOnlineSend();
BeanUtils.copyProperties(imMessage, imMessageOnlineSend);
imMessageOnlineSend.setMsgId(imMessage.getId());
imMessageOnlineSend.setSender(imMsgSendRestApi.getSenderClient());
imMessageOnlineSend.setContent(dataHashMap);
imMessageOnlineSend.setConversationId(toConversationId);
// 遍历发送
for (ImConversationMembers conversationMembers : membersList) {
// 保存收件箱
long imInboxId = SnowflakeUtil.getId();
ImInbox imInbox = new ImInbox();
imInbox.setId(imInboxId);
imInbox.setCreateTime(new Date());
imInbox.setFkAppid(imApplication.getId());
imInbox.setReceiver(conversationMembers.getFkClientId());
imInbox.setFkMsgId(messageId);
imInbox.setReadMsgStatus(0);
imInbox.setReceiverMsgStatus(0);
imInbox.setFkConversationId(toConversationId);
imInboxService.save(imInbox);
// 查询接收方
ImClient imClientReceiver = imClientService.getOne(new QueryWrapper<ImClient>().lambda()
.eq(ImClient::getFkAppid, imApplication.getId())
.eq(ImClient::getId, conversationMembers.getFkClientId()));
if (imClientReceiver == null) {
continue;
}
// 向接收方推送
WsResponseModel<ImMessageOnlineSend> responseModel = new WsResponseModel<>();
responseModel.setCmd(WsResponseCmdEnum.ONLINE_MSG.getCmdCode());
ApiResult<Boolean> result = ApiResult.result(ApiCode.SUCCESS);
responseModel.setCode(result.getCode());
responseModel.setMsg(result.getMessage());
responseModel.setData(imMessageOnlineSend);
responseModel.setReqId(null);
writeDataService.write(responseModel, imApplication.getAppKey(), imClientReceiver.getClientId());
// 异步推送系统通知消息
systemPush.push(pushMap, imClientReceiver, imApplication);
}
ImMsgSendRestResult data = new ImMsgSendRestResult();
data.setMsgId(messageId);
return ApiResult.ok(data);
}
private boolean black(ImClient imClientSender, List<ImConversationMembers> membersList) {
// 判断是否被拉黑
boolean beBlack = imClientBlacklistService.isBeBlack(membersList.get(0).getFkClientId(), imClientSender.getId());
if (beBlack) {
log.info("被对方拉黑了");
return true;
}
// 是否把对方拉黑
boolean black = imClientBlacklistService.isBeBlack(imClientSender.getId(), membersList.get(0).getFkClientId());
if (black) {
log.info("你把对方拉黑了");
return true;
}
return false;
}
@Override
@Transactional(rollbackFor = Exception.class)
......
# wecloud-im服务端REST API对接文档
# wecloud-im服务端REST API对接文档
......@@ -2,31 +2,15 @@
## 本地API文档地址
http://192.168.1.110:8082/api/doc.html#/home
http://192.168.1.89:8082/api/doc.html#/home
账号密码admin admin
以上只包含api接口文档 websocket对接说明在此文档中
## 测试外网
文档:
```
https://wstest.im199.com/api/doc.html#/home
```
___
测试外网请求示例:
```
https://wstest.im199.com/api/imApplication/add
```
以上只包含api接口文档 websocket对接说明在此文档中
_______
## 测试外网
......@@ -57,7 +41,7 @@ _______
## 鉴权方式
### 方式一(正在开发):
### 方式一(开发完成):
对于 POST 和 PUT 请求,请求的主体必须是 JSON 格式,而且 HTTP header 的 Content-Type 需要设置为 `application/json`
......@@ -65,13 +49,15 @@ _______
**示例**: rest-api-会话成员表分页列表
#### **示例**:
rest-api-会话成员表分页列表
- Request URL: http://192.168.1.89:8082/api/restApi/imConversationMembers/findList
- Request Method: POST
**请求头**
**请求头参数**
```
appkey: D13ug9jsWbJbeVx1
......@@ -81,11 +67,25 @@ appSecret: c92edcc7ba0c68b9b1da4cec6f3511876b2302faf2ab3737
**请求body**
**请求body示例**
```
{
"conversationId": 1442742976269914112
"senderClient": "client_2",
"content": {
"reqId":"1231223123",
"cmd":1,
"data":{
"diyAbcd":"aaaa自已定2义字段的值",
"toConversation":1495943481078714368,
"type":-1,
"text":"发给12312123213这是一123个纯文本消息,发给12312123213这是一123个纯文本消息发给12312123213这是一123个纯文本消息",
"attrs":{
"a":"attrs 阿道夫123123是用来213存储用户自定义的一些键值对,ttrs 阿道夫123123是用来213存储用户自定义的一些键值对",
"b":"attrs 阿道夫123123是用来213存储用户自定义的一些键值对,ttrs 阿道夫123123是用来213存储用户自定义的一些键值对"
}
}
}
}
```
......@@ -94,7 +94,23 @@ appSecret: c92edcc7ba0c68b9b1da4cec6f3511876b2302faf2ab3737
**响应数据**
```
{"code":200,"message":"成功","data":[{"clientId":"1442742442803503105"},{"clientId":"1435497966619996162"}]}
{
"senderClient": "client_2",
"content": {
"reqId":"1231223123",
"cmd":1,
"data":{
"diyAbcd":"aaaa自已定2义字段的值",
"toConversation":1495943481078714368,
"type":-1,
"text":"发给12312123213这是一123个纯文本消息,发给12312123213这是一123个纯文本消息发给12312123213这是一123个纯文本消息",
"attrs":{
"a":"attrs 阿道夫123123是用来213存储用户自定义的一些键值对,ttrs 阿道夫123123是用来213存储用户自定义的一些键值对",
"b":"attrs 阿道夫123123是用来213存储用户自定义的一些键值对,ttrs 阿道夫123123是用来213存储用户自定义的一些键值对"
}
}
}
}
```
......@@ -143,7 +159,19 @@ curl -X PUT \
一个请求是否成功是由 HTTP 状态码标明的。一个 2XX 的状态码表示成功,而一个 4XX 表示请求失败。当一个请求失败时响应的主体仍然是一个 JSON 对象,但是总是会包含 `code``error` 这两个字段,你可以用它们来进行调试。举个例子,如果尝试用非法的属性名来保存一个对象会得到如下信息:
## 单聊、群聊
### 服务端发消息
文档: 服务端rest-API-消息 - > 向会话中的client下发消息
文档地址
http://192.168.1.89:8082/api/doc.html#/app/%E6%9C%8D%E5%8A%A1%E7%AB%AFrest-API-%E6%B6%88%E6%81%AF/restApiImMessageSendChatUsingPOST
### 创建对话
......@@ -159,7 +187,13 @@ curl -X PUT \
### 查询成员
### 单聊、群聊-发消息
### 查询历史消息
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment