1
-
2
1
# 事件订阅与通知
3
2
4
3
<!-- > 当用户在QQ平台内的一些行为操作或某些接口的有异步返回通知确认机制的场景的时候,QQ 会通过"事件"的方式,通知到开发者服务器,开发者可自行根据具体事件通知来进行下一步响应。譬如用户跟机器人发消息,用户添加机器人好友,机器人被拉入群聊等等事件。 -->
9
8
10
9
## Webhook方式
11
10
12
- ** Webhook方式灰度中,仅灰度用户可使用 ** 其它用户请使用 [ websocket方式 ] ( #websocket方式 ) 。
11
+ webhook事件回调链路目前在灰度验证,灰度用户可体验通过页面配置事件监听及回调地址。如未在灰度范围,可联系QQ机器人反馈助手开通 。
13
12
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机器人反馈助手 " >
15
14
16
15
QQ机器人开放平台支持通过使用HTTP接口接收事件。开发者可通过[ 管理端] ( https://q.qq.com/qqbot/#/developer/webhook-setting ) 设定回调地址,监听事件等。
17
16
@@ -33,36 +32,39 @@ QQ机器人开放平台支持通过使用HTTP接口接收事件。开发者可
33
32
34
33
` opcode ` 含义如下:
35
34
36
- | ** CODE** | ** 名称** | ** 客户端行为** | ** 描述** |
37
- | --- | --- | --- | --- |
38
- | 0 | Dispatch | Receive | 服务端进行消息推送 |
39
- | 13 | 回调地址验证 | Receive | 开放平台对机器人服务端进行验证 |
35
+ | ** CODE** | ** 名称** | ** 客户端行为** | ** 描述** |
36
+ | ---------- | ---------- | ----------- | ----------------- |
37
+ | 0 | Dispatch | Receive | 服务端进行消息推送 |
38
+ | 13 | 回调地址验证 | Receive | 开放平台对机器人服务端进行验证 |
40
39
41
40
### 签名校验
41
+
42
42
机器人服务端需要对回调请求进行签名验证以保证数据没有被篡改过。
43
43
[ 签名算法] ( sign.md )
44
44
45
45
### 回调地址及事件监听配置
46
46
47
47
开发者需要提供一个HTTPS回调地址。并选定监听的事件类型。开放平台会将事件通过回调的方式推送给机器人。
48
+
48
49
<img :src =" $withBotBase('/images/api-231017/event_subscription.png') " alt =" event_subscription " >
49
50
50
51
配置回调地址后,开放平台会对回调地址进行验证:
51
52
* 请求结构(Payload.d)
52
53
53
- | ** 字段** | ** 描述** |
54
- | --- | ------------|
54
+ | ** 字段** | ** 描述** |
55
+ | ------------- | ------------|
55
56
| plain_token | 需要计算签名的字符串 |
56
- | event_ts | 计算签名使用时间戳 |
57
+ | event_ts | 计算签名使用时间戳 |
57
58
58
59
* 返回结果
59
60
60
- | ** 字段** | ** 描述** |
61
- | --- | - ------------|
61
+ | ** 字段** | ** 描述** |
62
+ | ------------- | ------------|
62
63
| plain_token | 需要计算签名的字符串 |
63
- | signature | 签名 |
64
+ | signature | 签名 |
64
65
65
66
计算过程如下(golang):
67
+
66
68
``` go
67
69
func handleValidation (rw http .ResponseWriter , r *http .Request , botSecret string ) {
68
70
httpBody , err := io.ReadAll (r.Body )
@@ -130,6 +132,8 @@ body: {"plain_token": "Arq0D5A61EgUu4OxUvOp","signature": "87befc99c42c651b3aac0
130
132
```
131
133
132
134
## WebSocket方式
135
+ *
136
+ * websocket 事件推送链路将在24年年底前逐步下线,后续官方不再维护。
133
137
134
138
通过 ` WebSocket ` 建立与QQ机器人开放平台的长链接通信管道,当需要事件通知的时候QQ后台通过 ` WebSocket ` 连接下发事件到开发者服务器上。
135
139
@@ -139,7 +143,7 @@ body: {"plain_token": "Arq0D5A61EgUu4OxUvOp","signature": "87befc99c42c651b3aac0
139
143
140
144
### 通用数据结构 Payload
141
145
142
- ` payload ` 指的是在 ` websocket ` 连接上传输的数据,网关的上下行消息采用的都是同一个结构,如下:
146
+ ` payload ` 指的是在 ` websocket ` 连接上传输的数据,网关的上下行消息采用的都是同一个结构,如下:
143
147
144
148
``` json
145
149
{
@@ -149,29 +153,30 @@ body: {"plain_token": "Arq0D5A61EgUu4OxUvOp","signature": "87befc99c42c651b3aac0
149
153
"t" : " GATEWAY_EVENT_NAME"
150
154
}
151
155
```
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 的时候 |
158
163
159
164
160
165
### 长连接维护 OpCode
161
166
162
167
所有 ` opcode ` 列表如下:
163
168
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 回调模式的回包,代表机器人收到了平台推送的数据 |
175
180
176
181
客户端行为含义如下:
177
182
@@ -223,12 +228,12 @@ wss://api.sgroup.qq.com/websocket/
223
228
224
229
```
225
230
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 | 目前无实际作用,可以按照自己的实际情况填写,也可以留空 |
232
237
233
238
鉴权成功之后,QQ 后台会下发一个 Ready Event, ` payload ` 如下:
234
239
``` json
@@ -259,7 +264,6 @@ wss://api.sgroup.qq.com/websocket/
259
264
}
260
265
```
261
266
262
-
263
267
心跳发送成功之后会收到 [ OpCode 11 Heartbeat ACK] ( opcode.md ) 消息, ` payload ` 如下:
264
268
265
269
``` json
@@ -382,7 +386,6 @@ PUBLIC_GUILD_MESSAGES (1 << 30) // 消息事件,此为公域的消息事件
382
386
383
387
如果拥有的某个特殊事件类型的权限被取消,则在当前连接上不会报错,但是将不会收到对应的事件类型,如果重新连接,则报错,所以如果开发者的事件类型权限被取消,请及时调整监听事件代码,避免报错导致的无法连接。
384
388
385
-
386
389
### 分片连接LoadBalance
387
390
388
391
随着` bot ` 的增长并被添加到越来越多的频道中,事件越来越多,业务有必要对事件进行水平分割,实现负载均衡。机器人网关实现了一种用户可控制的分片方法,该方法允许跨多个网关连接拆分事件。 分片完全由用户控制,并且不需要在单独的连接之间进行状态共享。
@@ -391,7 +394,9 @@ PUBLIC_GUILD_MESSAGES (1 << 30) // 消息事件,此为公域的消息事件
391
394
392
395
393
396
#### 获得合适的分片数
397
+
394
398
使用[ /gateway/bot] ( ../../openapi/wss/shard_url_get.md ) 接口获取网关地址的时候,会同时返回一个建议的 ` shard ` 数,及最大并发限制。
399
+
395
400
``` json
396
401
{
397
402
"url" : " wss://sandbox.api.sgroup.qq.com/websocket" ,
@@ -406,7 +411,9 @@ PUBLIC_GUILD_MESSAGES (1 << 30) // 消息事件,此为公域的消息事件
406
411
```
407
412
408
413
#### 分片规则
414
+
409
415
分片是按照频道id进行哈希的,同一个频道的信息会固定从同一个链接推送。具体哈希计算规则如下:
416
+
410
417
``` bash
411
418
shard_id = (guild_id >> 22) % num_shards
412
419
```
0 commit comments