[TOC]

> 消息协议需要调研一下，需求可以服务端转发消息

# 消息体

## 基础结构

> 已读回执

```json
{
  "id": "",
  "from": "",
  "to": "",
  "tenantNo": "",
  "target": "",
  "type": "Type",
  "content": {
  },
    
  "timestamp": 1675416709033,
  "isBackground": false
}

```

> 部分说明
>
> id 为发送端随机数，用来去重
>
> `单聊` -> from 发送者 to 接收者 服务器直接转发
>
> `群聊`-> 发送消息体：from发送者、to群、target接收者；接收消息体：from群、to接收者、target发送者

### Type

```java
public enum MsgType {
    UNKNOWN(-1),  // 未知消息
    TEXT(0),  // 文本消息
}
```

### 异常上报

### 文本(text)

```json
{
  "text": ""
}
```

### 图片(image)

```json
{
  "storageId": "",
  "thumbnail": "",
  "thumbnailWidth": 100,
  "thumbnailHeight": 100
}
```

### 语音(audio)

```json
{
  "storageId": "",
  "duration": 152
}

```

### 视频

```json
{
  "storageId": "",
  "fileName": "",
  "fileSize": "",
  "duration": 100,
  "thumbnail": "",
  "thumbnailWidth": 100,
  "thumbnailHeight": 100
}

```

### 文件

```json
{
  "storageId": "",
  "fileName": "",
  "fileSize": "",
  "duration": 100,
  "mimeType": "video/3gpp"
}

```

### 位置

```json
```

### 通知

```json
{
  "title": "",
  "content": "",
  "action": "",
  "appid": "",
  "appName": "",
  "appLogo": "",
  "url": ""
}

```

### 后台运行

> 组织架构类，大数据，后台更新，已读回执
>
> 视频通话邀请

```json
{
  "type": "",
  "content": {}
}
```

### 音视频通话

```json
{
  "status": "",
  "avType": "",
  "uid": "",
  "roomId": "",
  "timestamp": 1675416709033,
  "useTime": 1675416709033,
  "agoraKey": 1675416709033
}
```

>
>status
>
> //邀请invite 拒绝refuse 取消cancel 超时timeout 占线busy
>
> // 已在其他设备接听other_answer（256推送消息）
>
> // 已在其他设备拒绝other_refuse（根据fromid == account判断）
>
> uid // 前端展示邀请人所用
>
> useTime //本地纪录的用时，单位秒
>
> agoraKey //声网key

```java
enum OsType {
    IOS(1),
    ANDROID(2),
    WEB(3),
    WINDOWS(4),
    UNKNOWN(-1)
}
```

### 应用消息

> 区分子应用，提高分配效率
>
> 处方单

```json
{
  "title": "",
  "content": "",
  "action": "",
  "appid": "",
  "appName": "",
  "appLogo": "",
  "url": ""
}

```

### 扩展

> 应对未定义消息，细微拓展。
>

```json
{}
```

## 消息收发机制

```mermaid
sequenceDiagram
Title: 基础流程(MQTT)
actor APP
actor SDK
actor 服务端
actor 厂商

critical 启动
      SDK -->> SDK: 获取设备信息、生成唯一码、获取对应厂商的pushTOken，缓存本地
      APP ->> SDK: 服务初始化，提供userId
      SDK ->> 服务端: 提供设备信息、唯一码、pushToken以及userId，注册im服务
      服务端 -->> 服务端: 保证每一个唯一码只有一个对应的pushToken等信息（历史唯一码标识只为注销），生成account。
      服务端 ->> SDK: 返回account，im服务器信息(域名，端口等)
      SDK -->> SDK: 连接im服务，订阅account
end

critical 发送消息
      APP ->> SDK: 发送消息api
      SDK ->> 服务端: 整理消息发送
      alt 单聊
        服务端->>服务端: 原消息留档后发送
      else 群聊
        服务端->>服务端: 原消息留档后，重构消息，发送给群里所有人。<br/>
      end
      服务端 ->> SDK: 消息送达
      服务端 ->> 厂商: 根据是否开启推送以及sdk是否在线，决定是否需要厂商推送
	  厂商 ->> APP: 厂商推送
      SDK ->> SDK: 去重(？修改状态，是同id消息，还是消息体体现)<br/>、存表
      SDK ->> APP: 通知消息送达
	alt im推送
    	APP ->> APP: 根据实际情况，决定是直接使用通知里的消息，还是查表获取。
    else 厂商推送
    	APP ->> APP: 点击通知栏动作(服务端可以配置)
    end
end

critical 应用消息
    Note right of 服务端: 第三方服务获取token(权限认证，类似有appId获取autoTOken之类)
    Note right of 服务端: 设置群组api、标签api等
    Note right of 服务端: 调用发送消息api
	alt 单聊、群聊
    	服务端->>服务端: 原消息留档后发送指定人员或者群组
    else 所有人
    	服务端->>服务端: 原消息留档后，发送到所有用户
    end
    服务端 ->> SDK: 消息送达
    服务端 ->> 厂商: 根据是否开启推送以及sdk是否在线，决定是否需要厂商推送
    厂商 ->> APP: 厂商推送
    SDK ->> SDK: 去重(？修改状态，是同id消息，还是消息体体现)<br/>、存表
    SDK ->> APP: 通知消息送达
	alt im推送
    	APP ->> APP: 根据实际情况，决定是直接使用通知里的消息，还是查表获取。
    else 厂商推送
    	APP ->> APP: 点击通知栏动作(服务端可以配置)
    end
end

critical 历史消息、离线消息
      
      alt 历史消息
        APP ->> SDK: 获取离线消息api
      	SDK ->> 服务端: 获取离线消息(开始时间)
      	服务端 ->> SDK: 消息送达
      	SDK ->> APP: 通知消息送达
      	APP ->> APP: 查表获取
      else 离线消息
        APP ->> SDK: 获取历史消息api
      	SDK ->> 服务端: 获取离线消息
      	服务端 ->> 服务端: 根据target判断是获取所有还是单人
      	服务端 ->> SDK: 消息送达
      	SDK ->> APP: 通知消息送达
      	APP ->> APP: 查表获取
      end
end

critical 注销、停用推送
    par 停用推送
		APP ->> SDK: 请求关闭推送
		SDK ->> 服务端: 请求关闭推送
		服务端 -->> 服务端: 关闭推送标识(或者直接删除pushtoken？)
	and 注销
		APP ->> SDK: 注销
		SDK ->> 服务端: 注销
		服务端 -->> 服务端: 针对这个account对应的唯一码，修改状态为已注销
	end
end

```























































