1-
21# 事件订阅与通知
32
43<!-- > 当用户在QQ平台内的一些行为操作或某些接口的有异步返回通知确认机制的场景的时候,QQ 会通过"事件"的方式,通知到开发者服务器,开发者可自行根据具体事件通知来进行下一步响应。譬如用户跟机器人发消息,用户添加机器人好友,机器人被拉入群聊等等事件。 -->
98
109## Webhook方式
1110
12- ** Webhook方式灰度中,仅灰度用户可使用 ** 其它用户请使用 [ websocket方式 ] ( #websocket方式 ) 。
11+ webhook事件回调链路目前在灰度验证,灰度用户可体验通过页面配置事件监听及回调地址。如未在灰度范围,可联系QQ机器人反馈助手开通 。
1312
14- 灰度用户如遇问题可通过 [ QQ机器人反馈助手 ] ( https://mpqq.gtimg.cn/bot-wiki/online/ images/api-231017/qqrobot-feedback.jpg ) 反馈
13+ < img :src = " $withBotBase('/ images/api-231017/feedback_bot.png') " alt = " QQ机器人反馈助手 " >
1514
1615QQ机器人开放平台支持通过使用HTTP接口接收事件。开发者可通过[ 管理端] ( https://q.qq.com/qqbot/#/developer/webhook-setting ) 设定回调地址,监听事件等。
1716
@@ -33,36 +32,39 @@ QQ机器人开放平台支持通过使用HTTP接口接收事件。开发者可
3332
3433` opcode ` 含义如下:
3534
36- | ** CODE** | ** 名称** | ** 客户端行为** | ** 描述** |
37- | --- | --- | --- | --- |
38- | 0 | Dispatch | Receive | 服务端进行消息推送 |
39- | 13 | 回调地址验证 | Receive | 开放平台对机器人服务端进行验证 |
35+ | ** CODE** | ** 名称** | ** 客户端行为** | ** 描述** |
36+ | ---------- | ---------- | ----------- | ----------------- |
37+ | 0 | Dispatch | Receive | 服务端进行消息推送 |
38+ | 13 | 回调地址验证 | Receive | 开放平台对机器人服务端进行验证 |
4039
4140### 签名校验
41+
4242机器人服务端需要对回调请求进行签名验证以保证数据没有被篡改过。
4343[ 签名算法] ( sign.md )
4444
4545### 回调地址及事件监听配置
4646
4747开发者需要提供一个HTTPS回调地址。并选定监听的事件类型。开放平台会将事件通过回调的方式推送给机器人。
48+
4849<img :src =" $withBotBase('/images/api-231017/event_subscription.png') " alt =" event_subscription " >
4950
5051配置回调地址后,开放平台会对回调地址进行验证:
5152* 请求结构(Payload.d)
5253
53- | ** 字段** | ** 描述** |
54- | --- | ------------|
54+ | ** 字段** | ** 描述** |
55+ | ------------- | ------------|
5556| plain_token | 需要计算签名的字符串 |
56- | event_ts | 计算签名使用时间戳 |
57+ | event_ts | 计算签名使用时间戳 |
5758
5859* 返回结果
5960
60- | ** 字段** | ** 描述** |
61- | --- | - ------------|
61+ | ** 字段** | ** 描述** |
62+ | ------------- | ------------|
6263| plain_token | 需要计算签名的字符串 |
63- | signature | 签名 |
64+ | signature | 签名 |
6465
6566计算过程如下(golang):
67+
6668``` go
6769func handleValidation (rw http .ResponseWriter , r *http .Request , botSecret string ) {
6870 httpBody , err := io.ReadAll (r.Body )
@@ -131,6 +133,8 @@ body: {"plain_token": "Arq0D5A61EgUu4OxUvOp","signature": "87befc99c42c651b3aac0
131133
132134## WebSocket方式
133135
136+ * websocket 事件推送链路将在24年年底前逐步下线,后续官方不再维护。
137+
134138通过 ` WebSocket ` 建立与QQ机器人开放平台的长链接通信管道,当需要事件通知的时候QQ后台通过 ` WebSocket ` 连接下发事件到开发者服务器上。
135139
136140开发者需要维护 ` WebSocket ` 长链接的状态,包括连接状态维护、登录鉴权、心跳维护、断线恢复重连等。
@@ -139,7 +143,7 @@ body: {"plain_token": "Arq0D5A61EgUu4OxUvOp","signature": "87befc99c42c651b3aac0
139143
140144### 通用数据结构 Payload
141145
142- ` payload ` 指的是在 ` websocket ` 连接上传输的数据,网关的上下行消息采用的都是同一个结构,如下:
146+ ` payload ` 指的是在 ` websocket ` 连接上传输的数据,网关的上下行消息采用的都是同一个结构,如下:
143147
144148``` json
145149{
@@ -149,29 +153,30 @@ body: {"plain_token": "Arq0D5A61EgUu4OxUvOp","signature": "87befc99c42c651b3aac0
149153 "t" : " GATEWAY_EVENT_NAME"
150154}
151155```
152- | 字段 | 描述|
153- | ----- | ----- |
154- | op | 指的是 opcode,参考连接维护 |
155- | s | 下行消息都会有一个序列号,标识消息的唯一性,客户端需要再发送心跳的时候,携带客户端收到的最新的s |
156- | t | 代表事件类型。主要用在op为 0 Dispatch 的时候|
157- | d | 代表事件内容,不同事件类型的事件内容格式都不同,请注意识别。主要用在op为 0 Dispatch 的时候|
156+
157+ | 字段 | 描述 |
158+ | -----| ------------------------------------------------------|
159+ | op | 指的是 opcode,参考连接维护 |
160+ | s | 下行消息都会有一个序列号,标识消息的唯一性,客户端需要再发送心跳的时候,携带客户端收到的最新的s |
161+ | t | 代表事件类型。主要用在op为 0 Dispatch 的时候 |
162+ | d | 代表事件内容,不同事件类型的事件内容格式都不同,请注意识别。主要用在op为 0 Dispatch 的时候 |
158163
159164
160165### 长连接维护 OpCode
161166
162167所有 ` opcode ` 列表如下:
163168
164- | ** CODE** | ** 名称** | ** 客户端行为** | ** 描述** |
165- | --- | --- | --- | --- |
166- | 0 | Dispatch | Receive | 服务端进行消息推送 |
167- | 1 | Heartbeat | Send/Receive | 客户端或服务端发送心跳 |
168- | 2 | Identify | Send | 客户端发送鉴权 |
169- | 6 | Resume | Send | 客户端恢复连接 |
170- | 7 | Reconnect | Receive | 服务端通知客户端重新连接 |
171- | 9 | Invalid Session | Receive | 当 identify 或 resume 的时候,如果参数有错,服务端会返回该消息 |
172- | 10 | Hello | Receive | 当客户端与网关建立 ws 连接之后,网关下发的第一条消息 |
173- | 11 | Heartbeat ACK | Receive/Reply | 当发送心跳成功之后,就会收到该消息 |
174- | 12 | HTTP Callback ACK | Reply | 仅用于 http 回调模式的回包,代表机器人收到了平台推送的数据 |
169+ | ** CODE** | ** 名称** | ** 客户端行为** | ** 描述** |
170+ | ---------- | ------------------- | --------------- | ------------------------------------------ |
171+ | 0 | Dispatch | Receive | 服务端进行消息推送 |
172+ | 1 | Heartbeat | Send/Receive | 客户端或服务端发送心跳 |
173+ | 2 | Identify | Send | 客户端发送鉴权 |
174+ | 6 | Resume | Send | 客户端恢复连接 |
175+ | 7 | Reconnect | Receive | 服务端通知客户端重新连接 |
176+ | 9 | Invalid Session | Receive | 当 identify 或 resume 的时候,如果参数有错,服务端会返回该消息 |
177+ | 10 | Hello | Receive | 当客户端与网关建立 ws 连接之后,网关下发的第一条消息 |
178+ | 11 | Heartbeat ACK | Receive/Reply | 当发送心跳成功之后,就会收到该消息 |
179+ | 12 | HTTP Callback ACK | Reply | 仅用于 http 回调模式的回包,代表机器人收到了平台推送的数据 |
175180
176181客户端行为含义如下:
177182
@@ -223,12 +228,12 @@ wss://api.sgroup.qq.com/websocket/
223228
224229```
225230
226- | ** 字段** | ** 描述** |
227- | --- | --- |
228- | token | 格式为"QQBot {AccessToken}" |
229- | intents | 是此次连接所需要接收的事件,具体可参考 ** Intents** [ 事件订阅intents\| QQ机器人文档] ( #事件订阅Intents ) |
230- | shard | 考虑到开发者事件接收时可以实现负载均衡,QQ 提供了分片逻辑,事件通知会落在不同的分片上,该参数是个拥有两个元素的数组。<br />例如:\[ 0,4\] ,代表分为四个片,当前链接是第 0 个片,业务稍后应该继续建立 ` shard ` 为\[ 1,4\] ,\[ 2,4\] ,\[ 3,4\] 的链接,才能完整接收事件,更多详细的内容可以参考 ** Shard** [ Shard机制\| QQ机器人文档] ( #%E5%88%86%E7%89%87%E8%BF%9E%E6%8E%A5LoadBalance ) <br /> 若无需分片,使用\[ 0, 1\] 即可。 |
231- | properties | 目前无实际作用,可以按照自己的实际情况填写,也可以留空 |
231+ | ** 字段** | ** 描述** |
232+ | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
233+ | token | 格式为"QQBot {AccessToken}" |
234+ | intents | 是此次连接所需要接收的事件,具体可参考 ** Intents** [ 事件订阅intents\ | QQ机器人文档] ( #事件订阅Intents ) |
235+ | shard | 考虑到开发者事件接收时可以实现负载均衡,QQ 提供了分片逻辑,事件通知会落在不同的分片上,该参数是个拥有两个元素的数组。<br />例如:\[ 0,4\] ,代表分为四个片,当前链接是第 0 个片,业务稍后应该继续建立 ` shard ` 为\[ 1,4\] ,\[ 2,4\] ,\[ 3,4\] 的链接,才能完整接收事件,更多详细的内容可以参考 ** Shard** [ Shard机制\ | QQ机器人文档] ( #%E5%88%86%E7%89%87%E8%BF%9E%E6%8E%A5LoadBalance ) <br /> 若无需分片,使用\[ 0, 1\] 即可。 |
236+ | properties | 目前无实际作用,可以按照自己的实际情况填写,也可以留空 |
232237
233238鉴权成功之后,QQ 后台会下发一个 Ready Event, ` payload ` 如下:
234239``` json
@@ -259,7 +264,6 @@ wss://api.sgroup.qq.com/websocket/
259264}
260265```
261266
262-
263267心跳发送成功之后会收到 [ OpCode 11 Heartbeat ACK] ( opcode.md ) 消息, ` payload ` 如下:
264268
265269``` json
@@ -382,16 +386,16 @@ PUBLIC_GUILD_MESSAGES (1 << 30) // 消息事件,此为公域的消息事件
382386
383387如果拥有的某个特殊事件类型的权限被取消,则在当前连接上不会报错,但是将不会收到对应的事件类型,如果重新连接,则报错,所以如果开发者的事件类型权限被取消,请及时调整监听事件代码,避免报错导致的无法连接。
384388
385-
386389### 分片连接LoadBalance
387390
388391随着` bot ` 的增长并被添加到越来越多的频道中,事件越来越多,业务有必要对事件进行水平分割,实现负载均衡。机器人网关实现了一种用户可控制的分片方法,该方法允许跨多个网关连接拆分事件。 分片完全由用户控制,并且不需要在单独的连接之间进行状态共享。
389392
390393要在连接上启用分片,需要在建立连接的时候指定分片参数,具体参考[ gateway] ( reference.md )
391394
392-
393395#### 获得合适的分片数
396+
394397使用[ /gateway/bot] ( ../../openapi/wss/shard_url_get.md ) 接口获取网关地址的时候,会同时返回一个建议的 ` shard ` 数,及最大并发限制。
398+
395399``` json
396400{
397401 "url" : " wss://sandbox.api.sgroup.qq.com/websocket" ,
@@ -406,7 +410,9 @@ PUBLIC_GUILD_MESSAGES (1 << 30) // 消息事件,此为公域的消息事件
406410```
407411
408412#### 分片规则
413+
409414分片是按照频道id进行哈希的,同一个频道的信息会固定从同一个链接推送。具体哈希计算规则如下:
415+
410416``` bash
411417shard_id = (guild_id >> 22) % num_shards
412418```
0 commit comments