回调功能
回调功能
回调功能,即环信 IM 服务器会在事件发生之前或之后,向你的应用服务器发送请求,你可以根据业务需求来干预事件的后续处理流程(发送前回调),或据此进行必要的数据同步(发送后回调)。
一般发送前回调是对用户发送的消息内容的处理,发送后回调还包括送达回执和已读回执、群组或聊天室操作、好友关系操作和用户状态变化等事件,详见发送后回调过滤规则设置。
设置消息内容回调的规则可以在环信即时通讯云控制台实现,如需单独设置特定类型不回调,请联系环信商务经理。
从处理角度看,回调分为以下两类:
- 发送前回调:回调的主要目的在于让 app 后台可以干预该事件的处理逻辑,环信 IM 服务器会根据响应中的返回值确定后续处理流程;
- 发送后回调:回调的主要目的在于让 app 后台实现必要的数据同步,环信 IM 服务器忽略回调返回码。
1、发送前回调
技术原理
发送前回调只对客户端发送的消息有效,不包含 REST API 发送的消息。
应用服务器可以通过发送前回调实时监控用户的聊天消息,对消息进行处理,例如,拦截用户的消息请求。可拦截所有类型的消息,包含文本、图片、自定义消息等;
回调发生时间
环信 IM 服务器收到用户发送的上行单聊和群聊消息之后、将该消息下发给目标用户之前。
前提条件
以下是使用发送前回调功能需要了解的前提条件,包括在高并发可用性的基础上的使用限制说明,请按照此限制正确使用回调。
- 回调的方向是环信 IM 服务器向应用服务器发起 HTTP/HTTPS POST 请求。
- 若同时设置了消息发送前和发送后两种回调,且消息发送前回调返回拒绝,则消息发送后回调将不会被触发。
- 对同一个 app,可以针对不同类型的消息(“TEXT”,“IMAGE”,“VIDEO”,“LOCATION”,“VOICE” 和 ”FILE”)做配置;规则支持选择两种以上消息类型同时回调至一个指定服务器地址,接收到消息后,你可以区分消息的类型以便进行分类处理。详见 消息管理 REST API。
- 环信 IM 服务器执行发送前回调后,如果你的应用服务器没有返回 valid 状态或者未收到应答包,该条消息会根据默认设置(console 后台发送前回调中 ”调用失败时默认策略”)处理,不会重试;后续消息依然正常执行回调。
- 消息发送到你的应用服务器后,应用服务器需返回 HTTP 响应码 200 和 valid 属性,根据 valid 状态决定是否进行下发。
实现步骤
- 在管理后台开通消息回调服务。
- 在环信控制台配置发送前回调规则。
- 从环信服务器向你的应用服务器发送请求。
请求采用 POST 方式,支持 HTTP/HTTPS
,正文部分为 JSON 格式的字符串,字符集为 UTF-8。
请求 header
字段名 | 值 |
---|---|
Content-Type | 内容类型,请填 application/json 。 |
请求 body
参数 | 类型 |
---|---|
callId | callId 为 {appkey}_{uuid} ,其中 uuid 为随机生成,作为每条回调的唯一标识。 |
timestamp | 环信 IM 服务器接收到此消息的时间戳。 |
chat_type | 聊天类型:chat 为单聊,group 为群组聊天,chatroom 为聊天室。 |
group_id | 回调消息所在的群组或聊天室。该参数仅对群组聊天或聊天室中的消息回调生效。 |
from | 消息的发送方。 |
to | 消息的接收方。单聊为消息接收方,群组聊天和聊天室为群组 ID 和聊天室 ID。 |
msg_id | 消息的 ID。 |
payload | 消息内容,与通过 REST API 发送过来的一致,查看 消息格式文档。 |
securityVersion | 安全校验版本,目前为 1.0.0。忽略此参数,以后会改成 Console 后台做设置。 |
security | 签名,格式如下: MD5(callId+Secret+timestamp)。Secret 见 环信即时通讯云控制台回调规则。 |
响应 body
响应内容不能超过 1,000 个字符,否则环信服务器会认为是攻击,导致回调失败。
参数 | 类型 | 是否必需 | 描述 |
---|---|---|---|
valid | bool | 是 | 根据开发者自己服务器设定的规则判断消息是否合法: - true :消息合法,环信服务器应下发该消息;false :消息非法,环信服务器应拦截该消息。 |
code | String | 否 | 客户端上报的自定义发送前回调错误。环信控制台上的发送前回调页面中的消息拦截报错时显示设置为报错 时,该 code 的内容为客户端提示的错误。错误分为以下几种情况:- 若 code 的内容为字符串类型,客户端上的错误为该参数的内容;- 响应中不包含 code 字段, 客户端提示 custom logic denied ;- 若 code 为空字符串,移动客户端提示 Message blocked by external logic 错误;- 若在指定时间内未收到应答包,则按默认配置处理,客户端提示 custom internal error 错误;- 如果返回的应答包出现错误,包括缺少必填字段 valid 或字段类型不符合约定类型,客户端提示 custom internal error 错误。 |
payload | Object | 否 | 修改后的消息内容。若无需修改消息内容,请勿传该参数。 若需要更改消息内容可以回传修改后的内容,格式同传入的消息内容。目前仅支持文本的形式,并且消息大小不能超过 1 KB。如果需要支持修改其他类型的消息,需要联系商务配置。 |
示例
请求示例
{
"callId":"easemob-demo#test_0990a64f-dp01-6c50-8696-cf3b48b20e7e",
"timestamp":1600060847294,
"chat_type":"groupchat",
"group_id":"16934809238921545",
"from":"user1",
"to":"user2",
"msg_id":"8924312242322",
"payload":{
// 具体的消息内容
},
"securityVersion":"1.0.0",
"security":"2ca02c394bef9e7abc83958bcc3156d3"
}
响应示例
{
"valid": true,
"code": "HX:10000",
"payload": {
// 具体的消息内容。
// 仅支持文本类型消息。
}
}
2、发送后回调
技术原理
发送后回调经常用在 app 后台需要实现必要的数据同步的场景。比如:
- 针对客户消息的内容进行自动回复;
- 在你的应用服务器端及时保存聊天历史记录或者离线消息。
提示
如果您对聊天消息没有时效性需求,可以直接通过免费的 聊天记录拉取 REST API 获取聊天记录,无需使用发送后回调。
前提条件
以下是需要了解的发送后回调功能说明,包括在高并发可用性的基础上的使用限制说明,请按照此限制正确使用回调。
- 消息回调属于增值服务,需要开通相应版本后才能使用,详见 环信即时通讯 IM 价格。
- 消息回调规则设置成功即可正常使用。最多支持 4 个回调规则(包含发送前回调和发送后回调),如果需要提升回调规则数量上限,需要联系商务经理开通。
- 发送后回调范围,所有聊天消息有效(包含通过 SDK 和 REST API 发送的消息),包含单聊/群聊;如果 app 开通了反垃圾/敏感词过滤,被识别的消息会在服务器被拦截并禁止发送,将不会回调。
- 发送后回调接收延时,是指消息服务器接收到客户端聊天消息、再将消息成功回调至客户指定服务器地址的时间间隔。消息接收延时保障是 99.95% 的消息在 30s 内。
- 发送后回调对同一个 app 可以针对不同类型的消息(聊天消息、离线消息和通过 REST API 发送的消息)进行配置,如果 app 同时需要聊天消息和离线消息两种消息,建议区分回调地址。当然,规则也可以把这两种消息同时回调至一个指定服务器地址,在接收到消息后,可以对 eventType 做判断,区分消息的类型。
- 发送后回调重试,当环信服务器执行发出回调后,响应状态码非 200,则认为回调失败,然后立即重试,若再次失败,再记录一次失败;针对一条回调仅重试一次,重试失败后即丢弃。若开通了补发回调存储信息功能,则将消息放入异常存储中。若 30 秒内累计 90 次失败,会封禁该 app 的回调规则。封禁规则为,24 小时内连续封禁计数最大为 5(若封禁次数超过 5 次,仍计为 5),首次封禁默认 5 分钟,后续封禁时间为封禁次数 * 5 分钟,即第一次封禁 5 分钟,第二次封禁 10 分钟,第三次封禁 15 分钟,第四次封禁 20 分钟,第五次封禁 25 分钟,后续封禁时间与第 5 次保持一致为 25 分钟。重试失败以及封禁期间的回调不会自动补录,可以下载历史消息记录自行补充。
- 指定服务器收到回调消息后,向消息服务器发出响应内容不能超过 1,000 字符长度,如果连续发送超长的响应内容,会导致回调规则封禁,只能手动解除,需要用户手动重新设置。
- 客户有特殊需求不能丢失回调消息的情况下,请联系环信商务经理开通回调异常缓存功能,并使用 查询回调异常缓存 和 补发回调储存信息 接口。
实现步骤
- 配置发送后回调规则;
- 从环信服务器向你的应用服务器发送请求;
- 在不能丢失回调消息的情况下,请联系环信商务经理开通回调异常缓存功能后,进行回调异常缓存的查询和重新发送。
具体如下:
在环信即时通讯云控制台 配置发送回回调规则。App Key 可以配置回调规则的数据格式,默认最多开通 4 个规则,开通服务后才允许用户配置。
从环信服务器向你的应用服务器发送请求。
请求采用 POST 方式,支持 HTTP/HTTPS,正文部分为 JSON 格式的字符串,字符集为 UTF-8。
回调时,会对发送的正文做 MD5 签名。环信 IM 使用的 MD5 为 org.apache.commons.codec.digest.DigestUtils#md5Hex
。
app 的响应内容不能超过 1,000 个字符,否则环信服务器会认为是攻击,导致回调失败。
回调消息的参数说明
参数 | 类型 |
---|---|
callId | callId 为 {appkey}_{uuid} 其中 UUID 为随机生成,作为每条回调的唯一标识。 |
eventType | • chat 聊天消息;• chat_offline 离线消息。 |
timestamp | 环信 IM 服务器接收到此消息的 Unix 时间戳,单位为毫秒。 |
chat_type | • chat 单聊回调;• groupchat 群聊回调包含了群组和聊天室的消息回调,默认全选。 |
group_id | 群聊时才有此参数,回调消息所在的群组。 |
from | 消息的发送方。 |
to | 消息的接收方。 |
msg_id | 消息的 ID。 |
payload | 消息内容,与通过 REST API 发送过来的一致,查看 消息格式文档。 |
securityVersion | 安全校验版本,目前为 1.0.0。忽略此参数,以后会改成控制台做设置。 |
security | 签名,格式如下: MD5(callId+Secret+timestamp)。Secret 见 Console 后台回调规则。 |
回调成功返回的示例
{
"callId": "XXXX-demo#XXXX-dp01-XXXX-8696-cf3b48b20e7e",
"eventType": "chat_offline",
"timestamp": 1600060847294,
"chat_type": "groupchat",
"group_id": "169XXXX21545",
"from": "user1",
"to": "user2",
"msg_id": "8924312242322",
"payload": {
// 具体的消息内容。
},
"securityVersion": "1.0.0",
"security": "2ca02c394bef9e7abc83958bcc3156d3"
}
应答包字段说明
环信 IM 服务器不会验证响应的 response 内容,只要你的服务器给我们返回 HTTP 状态码是 200 即认为将消息回调成功。
查询回调储存详情接口描述
查询 App Key 下由于异常(比如链接超时,响应超时,回调规则封禁等)回调失败时存储的消息和事件类型集合,按每十分钟一个 date key 存储,然后用户可以根据消息集合按需拉取。
功能限制说明
- 异常存储过期时间默认 3 天,若有存储需及时补发。
- 补发重试次数建议控制在 10 次以内。
认证方式
环信即时通讯 RESTful API 要求 Bearer HTTP 认证。每次发送 HTTP 请求时,都必须在请求头部填入如下 Authorization
字段:
Authorization:Bearer YourAppToken
为提高项目的安全性,使用 token(动态密钥)对即将登录即时通讯系统的用户进行鉴权。即时通讯 RESTful API 支持使用 App Token 的鉴权方式,详见 使用 App Token 鉴权。
基本信息
方法:GET
接入点: /{org_name}/{app_name}/callbacks/storage/info
路径参数
参数 | 类型 | 是否必需 | 描述 |
---|---|---|---|
org_name | String | 是 | 环信即时通讯 IM 为每个公司(组织)分配的唯一标识。详见 获取环信即时通讯 IM 的信息。 |
app_name | String | 是 | 你在环信即时通讯云控制台创建应用时填入的应用名称。详见 获取环信即时通讯 IM 的信息。 |
请求 header
参数 | 类型 | 是否必需 | 描述 |
---|---|---|---|
Authorization | String | 是 | 鉴权 Token,管理员 Token(含)以上权限。 |
响应 body
参数 | 类型 | 描述 |
---|---|---|
path | string | 请求路径。 |
uri | string | 请求路径的 URI。 |
timestamp | long | 环信 IM 服务器接收到此消息的 Unix 时间戳,单位为毫秒。 |
organization | string | 你在环信 IM 管理后台注册的组织唯一标识。 |
application | string | 你在环信 IM 管理后台注册的 App 唯一标识。 |
action | string | 请求方法。 |
duration | long | 请求耗时,单位为毫秒。 |
applicationName | string | 你在环信 IM 管理后台注册的 App 名称。 |
data | object | 响应数据内容。包括以下三个参数:date 、size 和 retry 。 |
- date | String | 当前的 date key,即每 10 分钟内的消息和事件。key 为 10 分钟的起点。 |
- size | Int | 该 date key 内的消息数量。 |
- retry | Int | 该 date key 内的数据已经重试补发的次数。未重试时值为 0 。 |
请求示例
curl -X GET 'https://a1.easemob.com/easemob-demo/easeim/callbacks/storage/info' \
-H 'Authorization: Bearer <YourAppToken>'
响应示例
{
"path": "/callbacks",
"uri": "https://XXXX/XXXX/XXXX/callbacks",
"timestamp": 1631193031254,
"organization": "XXXX",
"application": "8dfb1641-XXXX-XXXX-bbe9-d8d45a3be39f",
"action": "post",
"data": [
{
"date": "202109091440",
"size": 15,
"retry": 0
},
{
"date": "202109091450",
"size": 103,
"retry": 1
}
],
"duration": 153,
"applicationName": "XXXX"
}
补发回调存储信息接口描述
调用接口根据存储集合进行回调补发。
基本信息
方法:POST
接入点: https://{host}/{org_name}/{app_name}/callbacks/storage/retry
路径参数
参数 | 类型 | 是否必需 | 描述 |
---|---|---|---|
org_name | String | 是 | 环信即时通讯 IM 为每个公司(组织)分配的唯一标识。详见 获取环信即时通讯 IM 的信息。 |
app_name | String | 是 | 你在环信即时通讯云控制台创建应用时填入的应用名称。详见 获取环信即时通讯 IM 的信息。 |
请求 header
参数 | 类型 | 是否必需 | 描述 |
---|---|---|---|
Content-Type | String | 是 | 内容类型,请填 application/json 。 |
Authorization | String | 是 | 鉴权 App Token 的值。详见 使用 App Token 鉴权。 |
请求 body
参数 | 类型 | 是否必需 | 描述 |
---|---|---|---|
date | String | 是 | 可以补发的一个十分钟 date key,key 为十分钟的起点。 |
retry | Int | 否 | 开发已重试的次数。考虑到补发也可能失败,服务器会继续存储。最开始是 0。 |
targetUrl | String | 否 | 补发消息的回调地址,如果为空,则使用原回调规则的回调地址。 |
响应 body
参数 | 类型 | 描述 |
---|---|---|
path | String | 请求路径。 |
uri | String | 请求路径的 URI。 |
timestamp | long | 环信 IM 服务器接收到此消息的 Unix 时间戳,单位为毫秒。 |
organization | String | 环信即时通讯 IM 为每个公司(组织)分配的唯一标识,与请求参数 org_name 相同。 |
application | String | 你在环信 IM 管理后台注册的 app 唯一标识。 |
action | String | 请求方法。 |
data | Bool | • success :成功;• failure :失败。 |
duration | long | 请求耗时,单位为毫秒。 |
请求示例
curl -X POST 'https://XXXX/XXXX/XXXX/callback/storage/retry' \
-H 'Authorization: Bearer <YourAppToken>' \
-H 'Content-Type: application/json' \
--data-raw '{
"date": "202108272230",
"retry": 0,
"targetUrl": "https://localhost:8000/test"
}'
响应示例
{
"path": "/callbacks",
"uri": "https://XXXX/XXXX/XXXX/callbacks",
"timestamp": 1631194031721,
"organization": "XXXX",
"application": "8dfb1641-XXXX-XXXX-bbe9-d8d45a3be39f",
"action": "post",
"data": "success",
"duration": 225,
"applicationName": "XXXX"
}
响应码说明
状态码 | 描述 |
---|---|
200 | 请求成功。 |
400 | 请求参数错误,请根据返回提示检查。 |
401 | 用户权限错误。 |
403 | 服务未开通或权限不足。 |
429 | 单位时间内请求过多。 |
500 | 服务器内部错误。 |
常见问题
Q: 发送前回调响应中的
valid
为false
,但为什么消息还是下发了?A:可能是你的服务器在发送前回调规则中配置的等待时间内未返回响应。这种情况下,如果你在环信控制台的发送前回调规则页面配置的调用失败时默认策略为放行,消息则会下发。为了避免这种情况,建议将等待响应时间(即时通讯 > 功能配置 > 消息回调 > 添加回调地址 > 发送前回调,默认为 200 毫秒)参数的值提升,例如,增加至 3000 毫秒。