# wecloud-im 即时通讯云对接文档


[TOC]

## 使用场景

即时通讯服务现在已经被广泛使用**在应用内社交、工作协同、客服系统、超大型赛事和电视直播、以及游戏状态同步**等多种业务场景之中。

即时通讯是主要**解决产品内聊天**即时通信（Instant Messaging）、实时数据同步等需求，其设计上的主要目标是：

- **支持为现有应用快速加入多种通讯能力**

  我们很多客户的产品都已经达到一个比较稳定的形态，即时通讯只是其中一个锦上添花的功能，所以如何和现有系统无缝集成，是我们设计上一个重要的出发点。即时通讯服务可以在应用账户系统独立的情况下，快速接入并稳定安全地运行。

  我们支持了多种典型通讯场景，提供了UI 库和脚手架来帮助开发者快速接入。并且考虑到业务运行环境，我们提供了支持的 SDK。

   

- **强大的自定义机制满足业务各种扩展需求**

   

  我们默认支持了**文本、图片、音视频、地理位置**等多种类型的消息收发，同时也允许产品开发者来扩展自己的消息类型和 UI 样式。并且在基本功能之外，我们也支持更多高阶需求，例如消息撤回与修改、@ 成员提醒、暂态消息、「已读」回执、离线推送、敏感内容过滤等等与消息收发相关的功能在这里都可以得到满足。

   

- **安全和权限控制**

  我们始终把系统安全性放在首要位置，客户端与云端使用 WebSocket 全双工通讯，全程 TLS 加密传输。在用户登录和操作权限的控制上，我们专门设计了第三方操作签名的机制，让应用层在快速接入的同时，也可以实时、完整地控制用户在即时通讯系统内的所有活动。在群聊和开放聊天室等业务场景里，我们也提供了成员角色管理和黑名单的机制，以满足产品运营管理的多样需求。

   

- **最大限度降低客户的生产运维成本** 

  我们提供专业的技术支持服务，富有经验的资深工程师 7 × 24 小时对接，以帮助开发者快速、有效地完成产品集成，缩短开发周期。此外在产品运营阶段，让开发者彻底摆脱后端系统日常的运维细节和突发的软硬件故障处理，也不用关心用户量和流量的变化。帮助客户在享受高品质技术服务的同时，也可以最大限度降低生产运维成本，并且以更快的速度推进产品迭代，是我们始终追求的目标。

## 功能和特性

即时通讯服务提供的主要功能有：

- **基本聊天功能**，包括：

  - 支持多种聊天场景。除了普通的单聊、群聊

  - 用户之间可以发送多种多样的消息，如文本、图片、语音、音视频、地理位置等，以及更多的应用层自定义消息。

  - 聊天消息自动保存在云端,可选支持永久消息存储，支持各种复杂的查找和翻页方式。
  
    

- **特殊的消息收发需求**。除了普通的消息收发之外，我们还支持：

  - 带有提醒功能的 **@ 消息**（如微信里面的 @ 某人）
  - 消息的 **撤回和修改**
  - 消息送达和对方已读的 **回执通知**
  - 群聊里面为了避免过于干扰，允许用户开启 **消息免打扰** 开关
  - 在消息接收方离线时，自动转为 **系统推送通知,ios和安卓**（Push Notification）
  
    
  
- **安全控制**

  任何终端用户要开启即时通讯服务，只需要提供一个唯一标识自己的 `clientId` 即可,不需要传入任何用户数据,以保证信息不被泄露，这种与产品自有账户系统解耦合的方式，带来了集成的便利，也可以促使通讯服务商专注做好底层的「信使」角色。 同时我们也提供 **第三方鉴权** 的机制，通过在聊天流程中加入开发者服务器签名授权这一环节，来确保通讯操作的安全。 而且，即时通讯 SDK 与云端是 WebSocket 全双工通讯，且全程使用 TLS 安全加密。

- **强大的业务扩展能力**

  对于很多典型的需求，我们提供了默认的实现，而为了支持业务的多样性和特殊性，我们也提供了丰富的扩展机制：

  - 为了和产品自有用户系统进行对接，我们提供了第三方操作鉴权的扩展接口，确保在用户登录、创建/加入/退出对话群组、以及拉取聊天记录时，所有操作都得到了授权。

  - 同时我们还支持开发者对消息传递的过程进行 **hook 处理**，在消息到达云端但是还没有投递之前和投递之后，分别完成自定义的处理逻辑，例如过滤掉竞品的品牌，以及自定义离线推送消息，等等。

  - 我们也支持通过简单的 **web hook** 来完成云端和应用后端的消息同步。

  - 在提供移动端的 SDK 之外，我们还提供了 REST API，以帮助产品在可信环境下更好地实现业务处理。


**我们相信灵活性和扩展性也是云服务的核心竞争力。**




## 核心概念说明

### clientId、用户和登录

即时通讯服务中的每一个终端称为一个「Client」。Client 拥有一个在应用内唯一标识自己的 ID（`clientId`）。这个 ID 由应用自己定义，必须是 **由任意英文字母、数字、半角下划线与半角短横线组成，可以纯数字，不超过 64个字符的字符串组成**。在大部分场合，Client 都可以对应到应用中的某个「用户」，但是并不是只有真的用户才能作为「Client」，你完全可以把一个探测器当成一个「Client」，把它收集到的数据通过即时通讯服务广播给更多「人」。

要使用即时通讯服务，每一个终端设备需要首先建立与即时通讯云服务端的 WebSocket 长连接，并使用唯一的 `clientId` 来加入即时通讯服务，我们把这一过程称为「登录」。请注意这里的登录仅仅指客户端登录即时通讯服务，与应用层面的用户账户注册登录是不一样的。

### appKey与appSecret

appKey为应用在蔚可云的唯一标识, appSecret为安全密钥, 均由蔚可云控制台或联系客服下发,给应用接入方安全验证密钥,生产环境appSecret不建议保存在接入方前端客户端, appKey与appSecret总是成对出现和使用

### 生成sign签名

sign 由接入方后端生成, 进行加签的参数:  MD5{timestamp + clientId + appKey + appSecret}
timestamp:毫秒时间戳
clientId:由后端生成

**在生产环境中，你需要自行部署服务器签发 sign**

### 对话（Conversation）

用户登录之后，与其他人(client)进行消息沟通，即为开启了一个「对话（Conversation）」。在即时通讯服务中，「对话」包含了沟通的用户群体（成员），也是所有消息依托的媒介：消息都是由某一个 Client 发往一个「对话」。终端用户在开始聊天之前，需要先创建或者加入一个对话，然后再邀请其他人进来（可选），之后所有参与者在这个对话内进行交流。

### 已读/已接收

**已接收**为客户端接收到该消息,已经保存到本地缓存中,用户还未打开会话查看该条消息的情况. 服务器将不会再次下发已接收状态的离线消息,未接收的消息会在拉取离线消息时返回

**已读**为客户端已经查看该消息



## 业务场景的需求


在解释对话类型之前，我们先列举一下即时通讯可能的使用场景。

-  单聊/私聊


就是两个 Client 之间的对话，公开与否（能否让其他人看到这个对话存在）由应用层自己控制。通常的业务场景里它是私密的，并且加入新的成员之后，会切换成新的群聊（当然，也可以依然不离开当前对话，这一点还是由应用层来决定）, 可选两个client之间只能存在一个会话。

- 群聊


就是两个（含）以上 Client 之间的对话，通常可以添加和删除成员，并且会赋予群聊一个名字，例如「家人群」、「朋友群」、「部门同事群」等等。随着成员的减少，群聊也可能只有两个甚至一个成员（成员的多少并不是区分群聊和单聊的关键）。群聊能否公开（譬如支持名字搜索），由应用自己决定。



## 客户端连接流程

![wc_im_client连接流程-Page-1](https://tva1.sinaimg.cn/large/008i3skNly1gvv3zjcuajj30zt0u0div.jpg)

1. appKey, appSecret为蔚可云下发给客户方安全保护密钥,不建议保存在前端客户端;
2. 第三方应用服务端需提供获取sign的接口, sign 由MD5{timestamp + clientId + appKey + appSecret},其中clientId由后端生成;
3. 前端拿到sign后,调用验证sign接口进行获取token;
4. websocket连接初始化需要带上token即可连接成功;
5. sign 需要在你的应用服务端生成;



### 第三方应用后端生成sign接口示例

本文展示如何在服务端部署一个 sign 生成器。

 **java**示例代码 ,供客户应用后端参考

```java
import org.springframework.util.DigestUtils;
private void getSign(String timestamp, String clientId, String appKey, String appSecret) {

  String data = timestamp + clientId + appKey + appSecret;
	String sign = DigestUtils.md5DigestAsHex(data.getBytes());
}

public static void main(String[] args)   {
  String clientId = "client_123123";
  String appKey = "elLwpel1gWCHDqZy";
  String appSecret = "68809bb5a9077a83631aeb0b17b5965d6b2302faf2ab3737";
  String timestamp = String.valueOf(new Date().getTime());
  getSign(timestamp, clientId, appKey, appSecret);
}
```

第三方应用后端**必须**要响应给前端的参数:

```json
{
	"timestamp": "1628838135066",
	"clientId": "client_3334444",
	"appKey": "D13ug9jsWbJbeVx1",
	"sign": "c15a886fe4114dba2c8f078369e6bec9"
}
```



## 消息数据加密

#### 自定义加密算法

如果客户方对数据安全比较敏感, 建议对消息聊天中的字符串数据进行**RSA不对称加密**或**AES对称加密**等数据加密技术,客户方可以任意选择世界上任一种加密算法, 加密和解密都在客户方应用内进行, wecloud平台将无法得知明文数据.

例如: 客户端发送文本消息 : "给我银行卡账号汇款10万元,卡号是10101010",

客户方可以在自己系统内维护RSA或AES的密钥, 对本文中的内容进行加密 : "给我银行卡账号汇款10万元,卡号是10101010",加密后的消息数据在wecloud将不会以明文的方式存储,以保障数据安全.

业务方服务端需要保存生成的加密密钥, 否则数据将无法解密



#### wecloud提供的加密

wecloud为提供**HTTPS**,以安全为目标的 HTTP 通道，在HTTP的基础上通过传输加密和身份认证保证了传输过程的安全性,。HTTPS 在HTTP 的基础下加入**SSL**，HTTPS 的安全基础是 SSL,。保障终端设备到服务器传输时的数据安全,不被窃取.


## IOS推送指南
客户方将应用APNS证书上传至wecloud控制台

## Android 混合推送开发指南

### 混合推送概述

自 Android 8.0 之后，系统权限控制越来越严，第三方推送通道的生命周期受到较大限制；同时，国内主流厂商也开始推出自己独立的推送服务，而厂商间千差万别的繁杂接口徒增了开发和代码维护的难度。为此，我们推出了混合推送的方案。我们逐一对接国内主流厂商，将它们不同的接口隐藏起来，让开发者通过统一的 API 完成推送任务。这不仅大幅降低了开发复杂度，还保障了主流 Android 系统上的推送到达率。
 
在混合推送方案里，消息下发时使用的通道不再是我们自己维持的 WebSocket 长连接，而是借用厂商和 OS 层的系统通道进行通信。一条推送消息下发的步骤如下：
 
1. 开发者调用云服务 Push API 请求对全部或特定设备进行推送；
2. 云推送服务端将请求转发给厂商的推送接口；
3. 厂商通过手机端的系统通道下发推送消息，同时手机端系统消息接收器将推送消息展示到通知栏；
4. 终端用户点击消息之后唤起目标应用或者页面。

整个流程与苹果的 APNs 推送类似，SDK 在客户端基本不会得到调用，消息的下发和展示都依赖厂商客户端的行为。所以如果部分厂商在某些推送中夹带了其他非开发者提交的消息，或者在服务启用的时候，有额外营销性质的弹窗，这都是厂商自己的行为，与我们完全无关，还请大家了解。另外，如果开发者碰到厂商 SDK 的问题，我们也无法深入调查，还请大家自行到厂商的论坛或技术支持渠道咨询解决。
 
Android 混合推送功能仅对商用版应用开放，如果希望使用该功能，请进入 **云服务控制台 > 推送 > 设置 > 混合推送**，打开混合推送的开关。
 

注意，混合推送可以随时按需开关。当该选项关闭后，下一次 Android 推送会与普通推送一样自动选择自有通道送达客户端，除了会再次遇到上面提到的自有通道在部分 ROM 上会受到限制的问题之外，不会有别的影响。而当该选项再次开启后，Android 推送又会去选择厂商推送渠道。

 
开启了混合推送之后，Installation 表中每一个设备对应的记录，会增加一个 vendor 字段（如果没有这一字段，则说明客户端集成有问题），其值分别为：+
 
| vendor | 厂商                   |
| :----- | :--------------------- |
| `HMS`  | 华为 HMS 推送          |
| `mi`   | 小米推送               |
| `mz`   | 魅族推送               |
| `oppo` | Oppo 推送              |
| `vivo` | VIVO 推送              |
| `fcm`  | FCM 推送（仅限国际版） |

注意，混合推送对接的是厂商各自的推送服务，需要单独配置，不支持混用。 通常情况下，需要提交不同的版本（分别对接厂商的推送服务）到相应厂商的应用商店。 如果希望使用统一版本，那么需要自行判断手机型号，在手机上开启对应的推送。
 
## 富媒体消息

为了方便开发者的使用，我们提供了几种封装好的基于 JSON 格式的富媒体消息类型（`TypedMessage`），譬如：

- 文本（`TextMessage`）
- 图片（`ImageMessage`）
- 音频（`AudioMessage`）
- 视频（`VideoMessage`）
- 位置（`LocationMessage`）


### 自定义类型消息

如发送红包  转账通知 好友验证等等

开发者可以基于我们的框架，方便地扩展出自己的消息类型。
