@larksuiteoapi/node-sdk 1.61.1 → 1.62.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +26 -4
- package/README.zh.md +170 -78
- package/es/index.js +3764 -7
- package/lib/index.js +3775 -7
- package/package.json +1 -1
- package/types/index.d.ts +592 -18
package/README.md
CHANGED
|
@@ -81,7 +81,7 @@ const res = await client.im.message.create({
|
|
|
81
81
|
````
|
|
82
82
|
> tips:
|
|
83
83
|
> * If you want to debug an API, you can click the link in the comment to enter the API debugging platform for debugging:
|
|
84
|
-
> 
|
|
85
85
|
> * How to obtain the semantic call interface:[Click here](https://github.com/larksuite/node-sdk/issues/42)
|
|
86
86
|
|
|
87
87
|
#### Create Client
|
|
@@ -246,7 +246,7 @@ client.im.message.create({
|
|
|
246
246
|
}
|
|
247
247
|
})
|
|
248
248
|
```
|
|
249
|
-

|
|
250
250
|
There will be a problem: **If the content of the message card is relatively rich, the generated template json is relatively large, and there will be more content that needs to be filled with data, and manual maintenance is more cumbersome**. To solve this problem, The Open-Platform provides the ability of [Template Message](https://open.feishu.cn/document/tools-and-resources/message-card-builder#3e1f2c7c).When sending a message card, you only need to provide the template id and the data content of the template. The sdk encapsulates this ability in terms of calling, and the interface that supports message cards will synchronously add a ByCard calling method, only need to pass `template_id` and `template_variable`. The above call can be rewritten as:
|
|
251
251
|
```typescript
|
|
252
252
|
client.im.message.createByCard({
|
|
@@ -281,7 +281,7 @@ client.im.message.create({
|
|
|
281
281
|
}
|
|
282
282
|
})
|
|
283
283
|
```
|
|
284
|
-

|
|
285
285
|
|
|
286
286
|
#### Configure request options
|
|
287
287
|
If you want to modify the parameters of the request during the API call, such as carrying some headers, custom tenantToken, etc., you can use the second parameter of the request method to modify:
|
|
@@ -386,7 +386,7 @@ server.listen(3000);
|
|
|
386
386
|
| cache | Cache | Cache | No | - |
|
|
387
387
|
|
|
388
388
|
> Note: Some events are v1.0 version and are no longer maintained. The SDK retains support for them. It is strongly recommended to use new versions of events that are consistent with their functions. Move the mouse to the corresponding event subscription function to see the relevant documents:
|
|
389
|
-

|
|
390
390
|
|
|
391
391
|
#### Combined with express
|
|
392
392
|
The SDK provides an adapter for experss to convert eventDispatcher into express middleware, which can be seamlessly combined with services written using express (*The use of bodyParser in the example is not necessary, but the community mostly uses it to format body data*):
|
|
@@ -587,6 +587,28 @@ wsClient.start({
|
|
|
587
587
|
```
|
|
588
588
|
|
|
589
589
|
|
|
590
|
+
### Channel module
|
|
591
|
+
|
|
592
|
+
`Channel` is a high-level module built on top of `WSClient` / `Client` that bundles transport, message normalization, safety policy, outbound sending, streaming replies, media upload, and card interactions into a single abstraction. It is the recommended entry point for conversational bots (AI chat, streaming replies, interactive card buttons, etc.).
|
|
593
|
+
|
|
594
|
+
```typescript
|
|
595
|
+
import { createLarkChannel } from '@larksuiteoapi/node-sdk';
|
|
596
|
+
|
|
597
|
+
const channel = createLarkChannel({ appId, appSecret });
|
|
598
|
+
|
|
599
|
+
channel.on('message', async (msg) => {
|
|
600
|
+
await channel.send(
|
|
601
|
+
msg.chatId,
|
|
602
|
+
{ markdown: `received: ${msg.content}` },
|
|
603
|
+
{ replyTo: msg.messageId },
|
|
604
|
+
);
|
|
605
|
+
});
|
|
606
|
+
|
|
607
|
+
await channel.connect();
|
|
608
|
+
```
|
|
609
|
+
|
|
610
|
+
Full reference (event subscription, sending, streaming, low-level helpers, error handling, configuration, etc.) — see [docs/channel.md](./docs/channel.md).
|
|
611
|
+
|
|
590
612
|
### [Message Card](https://open.feishu.cn/document/ukTMukTMukTM/uczM3QjL3MzN04yNzcDN)
|
|
591
613
|
|
|
592
614
|
The processing of the Message Card is also a kind of Event processing. The only difference between the two is that the processor of the Message Card is used to respond to the events generated by the interaction between the user and the Message Card. If the processor has a return value (*the value structure should be in line with the structure defined by [Message Card Structure](https://open.feishu.cn/document/ukTMukTMukTM/uEjNwUjLxYDM14SM2ATN)*), then the return value is used to update the responded message card:
|
package/README.zh.md
CHANGED
|
@@ -5,58 +5,72 @@
|
|
|
5
5
|

|
|
6
6
|
|
|
7
7
|
[English](https://github.com/larksuite/node-sdk/blob/main/README.md)
|
|
8
|
+
|
|
8
9
|
## 概述
|
|
10
|
+
|
|
9
11
|
[飞书开放平台](https://open.feishu.cn/document/ukTMukTMukTM/uITNz4iM1MjLyUzM)提供了一系列服务端的原子api来实现多元化的功能,但在实际编码过程中感受不是很顺畅,原因在于使用这些api完成功能时,需要考虑很多额外的工作,如token的获取及其维护、数据加解密、请求的验签等等;再者,在实际编码过程中,少了函数调用的语义化描述,类型系统的支持,使得心智负担过重。
|
|
10
12
|
|
|
11
13
|
凡此种种,都使得整体的开发体验不佳,基于此,为了让开放能力变得易用,我们编写了该SDK,将所有冗长的逻辑内置处理,提供完备的类型系统,对外提供语义化的编程接口,提高编码体验。😙
|
|
12
14
|
|
|
13
15
|
以下是一些基于该sdk的官方教程:
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
16
|
+
|
|
17
|
+
- [快速开发互动卡片](https://open.feishu.cn/document/home/quickly-develop-interactive-cards/introduction)
|
|
18
|
+
- [快速开发人员及考勤管理系统](https://open.feishu.cn/document/home/quick-start-of-personnel-and-attendance-management-system/overview)
|
|
19
|
+
- [快速接入多维表格](https://open.feishu.cn/document/home/quick-access-to-base/preparation)
|
|
20
|
+
- [基于网页应用实现部门人员管理](https://open.feishu.cn/document/home/quick-access-to-base/department-personnel-management-based-on-web-app/overview)
|
|
21
|
+
- [快速接入通讯录](https://open.feishu.cn/document/home/quick-access-to-contact-api/introduction)
|
|
22
|
+
- [基于审批实现自动考勤管理](https://open.feishu.cn/document/home/automatic-attendance-management-based-on-approval/introduction)
|
|
20
23
|
|
|
21
24
|
## 概念
|
|
22
|
-
- 开发文档:开放平台的开放接口的参考,**开发者必看,可以使用搜索功能,高效的查询文档**。[更多介绍说明](https://open.feishu.cn/document/) 。
|
|
23
25
|
|
|
26
|
+
- 开发文档:开放平台的开放接口的参考,**开发者必看,可以使用搜索功能,高效的查询文档**。[更多介绍说明](https://open.feishu.cn/document/) 。
|
|
24
27
|
- 开发者后台:开发者开发应用的管理后台,[更多介绍说明](https://open.feishu.cn/app/) 。
|
|
25
|
-
|
|
26
28
|
- 企业自建应用:应用仅仅可在本企业内安装使用,[更多介绍说明](https://open.feishu.cn/document/uQjL04CN/ukzM04SOzQjL5MDN) 。
|
|
27
|
-
|
|
28
29
|
- 应用商店应用:应用会在 [应用目录](https://app.feishu.cn/?lang=zh-CN)
|
|
29
30
|
展示,各个企业可以选择安装,[更多介绍说明](https://open.feishu.cn/document/uQjL04CN/ugTO5UjL4kTO14CO5kTN) 。
|
|
30
31
|
|
|
31
32
|
## 安装
|
|
33
|
+
|
|
32
34
|
npm
|
|
33
|
-
|
|
35
|
+
|
|
36
|
+
```shell
|
|
34
37
|
npm install @larksuiteoapi/node-sdk
|
|
35
38
|
```
|
|
39
|
+
|
|
36
40
|
yarn
|
|
41
|
+
|
|
37
42
|
```
|
|
38
43
|
yarn add @larksuiteoapi/node-sdk
|
|
39
44
|
```
|
|
40
45
|
|
|
41
46
|
## 如何使用
|
|
47
|
+
|
|
42
48
|
提供ECMAScript,CommonJS2个版本,支持原生Javascript和Typescript的使用,示例均以Typescript为例。
|
|
43
49
|
|
|
44
50
|
Typescript
|
|
51
|
+
|
|
45
52
|
```typescript
|
|
46
53
|
import * as lark from '@larksuiteoapi/node-sdk';
|
|
47
54
|
```
|
|
55
|
+
|
|
48
56
|
CommonJS
|
|
57
|
+
|
|
49
58
|
```javascript
|
|
50
59
|
const lark = require('@larksuiteoapi/node-sdk');
|
|
51
60
|
```
|
|
61
|
+
|
|
52
62
|
ECMAScript
|
|
63
|
+
|
|
53
64
|
```javascript
|
|
54
65
|
import * as lark from '@larksuiteoapi/node-sdk';
|
|
55
66
|
```
|
|
67
|
+
|
|
56
68
|
### api调用
|
|
69
|
+
|
|
57
70
|
飞书开放平台开放的所有 API 列表,可点击[这里查看](https://open.feishu.cn/document/ukTMukTMukTM/uYTM5UjL2ETO14iNxkTN/server-api-list)。
|
|
58
71
|
|
|
59
72
|
SDK提供了语义化的调用方式,只需要依据相关参数构造出client实例,接着使用其上的语义化方法(*client.业务域.资源.方法*)即可完成api调用,调用过程及调用结果均有完备的类型进行提示,如向群聊中发送消息:
|
|
73
|
+
|
|
60
74
|
```typescript
|
|
61
75
|
import * as lark from '@larksuiteoapi/node-sdk';
|
|
62
76
|
|
|
@@ -78,12 +92,15 @@ const res = await client.im.message.create({
|
|
|
78
92
|
},
|
|
79
93
|
});
|
|
80
94
|
```
|
|
81
|
-
|
|
82
|
-
>
|
|
83
|
-
>
|
|
84
|
-
>
|
|
95
|
+
|
|
96
|
+
> tips:
|
|
97
|
+
>
|
|
98
|
+
> - 如果想调试某个api,可以点击注释中的链接进入api调试台进行调试:
|
|
99
|
+
> 
|
|
100
|
+
> - 如何获取语义化调用接口:[点击这里](https://github.com/larksuite/node-sdk/issues/42)
|
|
85
101
|
|
|
86
102
|
#### 创建client
|
|
103
|
+
|
|
87
104
|
对于自建应用,可以使用下面的代码创建一个client:
|
|
88
105
|
|
|
89
106
|
```typescript
|
|
@@ -96,6 +113,7 @@ const client = new lark.Client({
|
|
|
96
113
|
```
|
|
97
114
|
|
|
98
115
|
对于商店应用,需要显示的指定appType为lark.AppType.ISV:
|
|
116
|
+
|
|
99
117
|
```typescript
|
|
100
118
|
import * as lark from '@larksuiteoapi/node-sdk';
|
|
101
119
|
|
|
@@ -105,7 +123,9 @@ const client = new lark.Client({
|
|
|
105
123
|
appType: lark.AppType.ISV,
|
|
106
124
|
});
|
|
107
125
|
```
|
|
108
|
-
|
|
126
|
+
|
|
127
|
+
**使用创建好的商店应用的client发起api调用时,还需在请求时手动传递[tenant\_key](https://open.feishu.cn/document/ukTMukTMukTM/ukDNz4SO0MjL5QzM/g#d15ab5d)**,可以使用lark.withTenantKey来完成:
|
|
128
|
+
|
|
109
129
|
```typescript
|
|
110
130
|
client.im.message.create({
|
|
111
131
|
params: {
|
|
@@ -120,23 +140,26 @@ client.im.message.create({
|
|
|
120
140
|
```
|
|
121
141
|
|
|
122
142
|
#### `Client`构造参数:
|
|
123
|
-
|
|
124
|
-
|
|
|
125
|
-
|
|
|
126
|
-
|
|
|
127
|
-
|
|
|
128
|
-
|
|
|
129
|
-
|
|
|
130
|
-
|
|
|
131
|
-
|
|
|
132
|
-
|
|
|
133
|
-
|
|
|
134
|
-
|
|
|
135
|
-
|
|
|
143
|
+
|
|
144
|
+
| 参数 | 描述 | 类型 | 必须 | 默认 |
|
|
145
|
+
| ----------------- | ---------------------------------------------------------------------------------- | ---------------- | -- | -------------------------------------------------------------- |
|
|
146
|
+
| appId | 应用的id | string | 是 | - |
|
|
147
|
+
| appSecret | 应用的密码 | string | 是 | - |
|
|
148
|
+
| domain | 应用的域,分为飞书(<https://open.feishu.cn)、lark(https://open.larksuite.com)、其它(需要传递完整的域名)> | Domain \| string | 否 | Domain.Feishu |
|
|
149
|
+
| httpInstance | sdk发送请求的http实例。*sdk内部默认使用axios.create()构造出一个defaultHttpInstance来进行http调用。* | HttpInstance | 否 | defaultHttpInstance。*可以从sdk中import它,在其上添加interceptors来完成业务需求。* |
|
|
150
|
+
| loggerLevel | 日志级别 | LoggerLevel | 否 | info |
|
|
151
|
+
| logger | - | Logger | 否 | - |
|
|
152
|
+
| cache | 缓存器 | Cache | 否 | - |
|
|
153
|
+
| disableTokenCache | 是否禁用缓存,如若禁用,则token等不会进行缓存,每次需要使用时都会重新拉取 | boolean | 否 | false |
|
|
154
|
+
| appType | 应用的类型,分为商店应用或者自建应用 | AppType | 否 | AppType.SelfBuild |
|
|
155
|
+
| helpDeskId | 服务台id | string | 否 | - |
|
|
156
|
+
| helpDeskToken | 服务台token | string | 否 | - |
|
|
136
157
|
|
|
137
158
|
#### 分页
|
|
138
|
-
|
|
139
|
-
|
|
159
|
+
|
|
160
|
+
针对返回值以分页形式呈现的接口,对其提供了迭代器方式的封装(方法名后缀为WithIterator),提高易用性,消弭了根据page\_token来反复获取数据的繁琐操作,如获取用户列表:
|
|
161
|
+
|
|
162
|
+
```typescript
|
|
140
163
|
// 每次处理20条数据
|
|
141
164
|
for await (const items of await client.contact.user.listWithIterator({
|
|
142
165
|
params: {
|
|
@@ -157,9 +180,13 @@ const listIterator = await SDKClient.contact.user.listWithIterator({
|
|
|
157
180
|
const { value } = await listIterator[Symbol.asyncIterator]().next();
|
|
158
181
|
console.log(value);
|
|
159
182
|
```
|
|
160
|
-
|
|
183
|
+
|
|
184
|
+
*当然也可以使用无迭代器封装的版本,这时候需要自己每次根据返回的page\_token来手动进行分页调用。*
|
|
185
|
+
|
|
161
186
|
#### 文件上传
|
|
187
|
+
|
|
162
188
|
和调用普通api的方式一样,按类型提示传递参数即可,内部封装了对文件上传的处理,如:
|
|
189
|
+
|
|
163
190
|
```typescript
|
|
164
191
|
const res = await client.im.file.create({
|
|
165
192
|
data: {
|
|
@@ -169,8 +196,11 @@ const res = await client.im.file.create({
|
|
|
169
196
|
},
|
|
170
197
|
});
|
|
171
198
|
```
|
|
199
|
+
|
|
172
200
|
#### 文件下载
|
|
201
|
+
|
|
173
202
|
对返回的二进制流进行了封装,消弭了对流本身的处理,只需调用writeFile方法即可将数据写入文件,如:
|
|
203
|
+
|
|
174
204
|
```typescript
|
|
175
205
|
const resp = await client.im.file.get({
|
|
176
206
|
path: {
|
|
@@ -179,7 +209,9 @@ const resp = await client.im.file.get({
|
|
|
179
209
|
});
|
|
180
210
|
await resp.writeFile(`filepath.suffix`);
|
|
181
211
|
```
|
|
212
|
+
|
|
182
213
|
如果想要自定义对流的处理,可以调用getReadableStream方法获取到流,如将流写入文件:
|
|
214
|
+
|
|
183
215
|
```typescript
|
|
184
216
|
import * as fs from 'fs';
|
|
185
217
|
|
|
@@ -192,10 +224,13 @@ const readableStream = resp.getReadableStream();
|
|
|
192
224
|
const writableStream = fs.createWriteStream('file url');
|
|
193
225
|
readableStream.pipe(writableStream);
|
|
194
226
|
```
|
|
227
|
+
|
|
195
228
|
> 注意:流只能被消费一次,即如果使用了writeFile消费了流,则getReadableStream获取流会报错/获取到的流为空;如需消费多次流,可以使用getReadableStream获取流,然后读取流中的数据做缓存,将缓存的数据给消费方使用。
|
|
196
229
|
|
|
197
230
|
#### 普通调用
|
|
231
|
+
|
|
198
232
|
某些老版本的开放接口,无法生成对应的语义化调用方法,需要使用client上的request方法来进行手动调用:
|
|
233
|
+
|
|
199
234
|
```typescript
|
|
200
235
|
import * as lark from '@larksuiteoapi/node-sdk';
|
|
201
236
|
|
|
@@ -213,8 +248,11 @@ const res = await client.request({
|
|
|
213
248
|
params: {},
|
|
214
249
|
});
|
|
215
250
|
```
|
|
251
|
+
|
|
216
252
|
#### 消息卡片
|
|
253
|
+
|
|
217
254
|
在发送[消息卡片](https://open.feishu.cn/document/ukTMukTMukTM/uczM3QjL3MzN04yNzcDN)信息时,会先在[消息卡片搭建工具](https://open.feishu.cn/document/ukTMukTMukTM/uYzM3QjL2MzN04iNzcDN/message-card-builder)中搭建出消息卡片的模版,拿到生成的模版json,用数据替换其中内容相关的部分,将结果作为支持消息卡片api的参数来使用。如发送一个简单的具有`title`和`content`的消息卡片:
|
|
255
|
+
|
|
218
256
|
```typescript
|
|
219
257
|
client.im.message.create({
|
|
220
258
|
params: {
|
|
@@ -245,8 +283,10 @@ client.im.message.create({
|
|
|
245
283
|
}
|
|
246
284
|
})
|
|
247
285
|
```
|
|
248
|
-
|
|
286
|
+
|
|
287
|
+

|
|
249
288
|
这样使用会有一个问题:**如果消息卡片内容比较丰富,生成的模版json比较大,与之相关需要数据填充的内容部分也会比较多,手动维护比较繁琐**。针对这个问题,开放平台提供了[模版消息](https://open.feishu.cn/document/tools-and-resources/message-card-builder#3e1f2c7c)的能力,发送消息卡片时只需要提供模版id和模版的数据内容即可。sdk对这个能力进行了调用上的封装,支持消息卡片的接口会同步的增加一个ByCard的调用方式,只需要传递`template_id`和`template_variable`即可。如上面的调用可以改写成:
|
|
289
|
+
|
|
250
290
|
```typescript
|
|
251
291
|
client.im.message.createByCard({
|
|
252
292
|
params: {
|
|
@@ -262,7 +302,9 @@ client.im.message.createByCard({
|
|
|
262
302
|
}
|
|
263
303
|
});
|
|
264
304
|
```
|
|
305
|
+
|
|
265
306
|
如果想要快速体验消息卡片,可以使用sdk中内置的一个基础卡片:
|
|
307
|
+
|
|
266
308
|
```typescript
|
|
267
309
|
import * as lark from '@larksuiteoapi/node-sdk';
|
|
268
310
|
|
|
@@ -280,11 +322,14 @@ client.im.message.create({
|
|
|
280
322
|
}
|
|
281
323
|
})
|
|
282
324
|
```
|
|
325
|
+
|
|
283
326
|
效果同上:
|
|
284
|
-

|
|
285
328
|
|
|
286
329
|
#### 配置请求选项
|
|
330
|
+
|
|
287
331
|
如果想在api调用过程中修改请求的参数,如携带一些header,自定义tenantToken等,则可以使用请求方法的第二个参数来进行修改:
|
|
332
|
+
|
|
288
333
|
```typescript
|
|
289
334
|
await client.im.message.create({
|
|
290
335
|
params: {
|
|
@@ -301,15 +346,16 @@ await client.im.message.create({
|
|
|
301
346
|
}
|
|
302
347
|
});
|
|
303
348
|
```
|
|
349
|
+
|
|
304
350
|
SDK亦将常用的修改操作封装成了方法,可以使用:
|
|
305
351
|
|
|
306
|
-
|
|
|
307
|
-
|
|
|
308
|
-
| withTenantKey
|
|
309
|
-
| withTenantToken
|
|
310
|
-
| withHelpDeskCredential
|
|
311
|
-
| withUserAccessToken
|
|
312
|
-
| withAll
|
|
352
|
+
| 方法 | 描述 |
|
|
353
|
+
| ---------------------- | ------------------------------------------------------------------------------------- |
|
|
354
|
+
| withTenantKey | 设置tenant key |
|
|
355
|
+
| withTenantToken | 设置tenant token |
|
|
356
|
+
| withHelpDeskCredential | 是否在请求中带入[服务台token](https://open.feishu.cn/document/ukTMukTMukTM/ugDOyYjL4gjM24CO4IjN) |
|
|
357
|
+
| withUserAccessToken | 设置access token |
|
|
358
|
+
| withAll | 将上述方法的结果合并起来 |
|
|
313
359
|
|
|
314
360
|
```typescript
|
|
315
361
|
await client.im.message.create({
|
|
@@ -339,14 +385,17 @@ await client.im.message.create({
|
|
|
339
385
|
```
|
|
340
386
|
|
|
341
387
|
### 处理事件
|
|
388
|
+
|
|
342
389
|
飞书开放平台开放的所有事件列表,可点击[这里查看](https://open.feishu.cn/document/ukTMukTMukTM/uYDNxYjL2QTM24iN0EjN/event-list)。
|
|
343
390
|
|
|
344
391
|
针对事件处理的场景,我们所关心的仅是**监听何种事件**,以及事件发生后我们**做些什么**,其它诸如数据解密等工作是我们不想关心的。SDK提供了直观的方式来描述这部分逻辑:
|
|
392
|
+
|
|
345
393
|
1. 构造事件处理器`EventDispatcher`的实例;
|
|
346
394
|
2. 在实例上注册需要监听的事件及其处理函数;
|
|
347
395
|
3. 将实例和服务进行绑定;
|
|
348
396
|
|
|
349
397
|
`EventDispatcher`内部会进行数据解密等操作,如果没有传递相关参数,则会自动忽略。
|
|
398
|
+
|
|
350
399
|
```typescript
|
|
351
400
|
import http from 'http';
|
|
352
401
|
import * as lark from '@larksuiteoapi/node-sdk';
|
|
@@ -378,18 +427,20 @@ server.listen(3000);
|
|
|
378
427
|
|
|
379
428
|
#### `EventDispatcher`构造参数
|
|
380
429
|
|
|
381
|
-
|
|
|
382
|
-
|
|
|
383
|
-
| [encryptKey](https://open.feishu.cn/document/ukTMukTMukTM/uYDNxYjL2QTM24iN0EjN/event-subscription-configure-/encrypt-key-encryption-configuration-case)
|
|
384
|
-
| loggerLevel
|
|
385
|
-
| logger
|
|
386
|
-
| cache
|
|
430
|
+
| 参数 | 描述 | 类型 | 必须 | 默认 |
|
|
431
|
+
| ------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------- | ----------- | -- | --------------------- |
|
|
432
|
+
| [encryptKey](https://open.feishu.cn/document/ukTMukTMukTM/uYDNxYjL2QTM24iN0EjN/event-subscription-configure-/encrypt-key-encryption-configuration-case) | 推送数据加密的key,开启加密推送时需要使用来进行数据解密 | string | 否 | - |
|
|
433
|
+
| loggerLevel | 日志级别 | LoggerLevel | 否 | lark.LoggerLevel.info |
|
|
434
|
+
| logger | - | Logger | 否 | - |
|
|
435
|
+
| cache | 缓存器 | Cache | 否 | - |
|
|
387
436
|
|
|
388
437
|
> 注:有一些事件是v1.0版本且已经不在维护了,SDK保留了对其的支持,强烈建议使用与之功能相一致的新版事件代替。鼠标移动到相应事件订阅函数上即可看到相关文档:
|
|
389
|
-

|
|
390
439
|
|
|
391
440
|
#### 和express结合
|
|
441
|
+
|
|
392
442
|
SDK提供了针对experss的适配器,用于将eventDispatcher转化为express的中间件,可无缝与使用express编写的服务相结合(*示例中的bodyParser的使用不是必须的,但社区大多用其来格式化body数据*):
|
|
443
|
+
|
|
393
444
|
```typescript
|
|
394
445
|
import * as lark from '@larksuiteoapi/node-sdk';
|
|
395
446
|
import express from 'express';
|
|
@@ -421,8 +472,11 @@ const eventDispatcher = new lark.EventDispatcher({
|
|
|
421
472
|
server.use('/webhook/event', lark.adaptExpress(eventDispatcher));
|
|
422
473
|
server.listen(3000);
|
|
423
474
|
```
|
|
475
|
+
|
|
424
476
|
#### 和koa结合
|
|
477
|
+
|
|
425
478
|
SDK提供了针对koa的适配器,用于将eventDispatcher转化为koa的中间件,可无缝与使用koa编写的服务相结合(*示例中的koaBody的使用不是必须的,但社区大多用其来格式化body数据*):
|
|
479
|
+
|
|
426
480
|
```typescript
|
|
427
481
|
import * as lark from '@larksuiteoapi/node-sdk';
|
|
428
482
|
import Koa from 'koa';
|
|
@@ -455,8 +509,11 @@ const eventDispatcher = new lark.EventDispatcher({
|
|
|
455
509
|
server.use(lark.adaptKoa('/webhook/event', eventDispatcher));
|
|
456
510
|
server.listen(3000);
|
|
457
511
|
```
|
|
512
|
+
|
|
458
513
|
#### 和koa-router结合
|
|
514
|
+
|
|
459
515
|
在使用koa来编写服务时,大多情况下会配合使用koa-router来对路由进行处理,因此SDK也提供了针对这一情况的适配:
|
|
516
|
+
|
|
460
517
|
```typescript
|
|
461
518
|
import * as lark from '@larksuiteoapi/node-sdk';
|
|
462
519
|
import Koa from 'koa';
|
|
@@ -509,9 +566,11 @@ server.sendResult(result);
|
|
|
509
566
|
```
|
|
510
567
|
|
|
511
568
|
#### challenge校验
|
|
569
|
+
|
|
512
570
|
在配置事件请求地址时,开放平台会向请求地址推送一个`application/json`格式的 POST请求,该POST请求用于验证所配置的请求地址的合法性,请求体中会携带一个`challenge`字段,**应用需要在 1 秒内,将接收到的challenge值原样返回给飞书开放平台**。详见:[文档](https://open.feishu.cn/document/ukTMukTMukTM/uYDNxYjL2QTM24iN0EjN/event-subscription-configure-/request-url-configuration-case)
|
|
513
571
|
|
|
514
572
|
上面sdk提供出的适配器内部封装了这部分验证的逻辑,将options参数中的`autoChallenge`字段设为true即可启用:
|
|
573
|
+
|
|
515
574
|
```typescript
|
|
516
575
|
// adaptDefault
|
|
517
576
|
lark.adaptDefault('/webhook/event', eventDispatcher, {
|
|
@@ -535,14 +594,15 @@ router.post(
|
|
|
535
594
|
```
|
|
536
595
|
|
|
537
596
|
### 使用长链模式处理事件
|
|
597
|
+
|
|
538
598
|
官方文档:[文档](https://open.feishu.cn/document/uAjLw4CM/ukTMukTMukTM/event-subscription-guide/long-connection-mode#62c8b8c8)
|
|
539
599
|
|
|
540
600
|
开发者通过集成飞书 SDK 与开放平台建立一条 WebSocket 全双工通道,当有事件回调发生时,开放平台会通过该通道向开发者发送消息。与传统的 Webhook 模式相比,长连接模式大大降低了接入成本,将原先 1 周左右的开发周期降低到 5 分钟。具体优势如下:
|
|
541
601
|
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
602
|
+
- 测试阶段**无需使用内网穿透工具**,通过长连接模式在本地开发环境中即可接收事件回调。
|
|
603
|
+
- 只在建连时进行鉴权,后续事件推送均为明文数据,无需开发者再处理解密和验签逻辑。
|
|
604
|
+
- 只需保证运行环境具备访问公网能力即可,无需提供公网 IP 或域名。
|
|
605
|
+
- 无需部署防火墙和配置白名单。
|
|
546
606
|
|
|
547
607
|
> 注意事项
|
|
548
608
|
|
|
@@ -551,6 +611,7 @@ router.post(
|
|
|
551
611
|
3. 目前长连接模式仅支持事件订阅,不支持回调订阅。
|
|
552
612
|
|
|
553
613
|
SDK支持了该功能集成,`1.24.0`及之后的版本可用,示例代码:
|
|
614
|
+
|
|
554
615
|
```typescript
|
|
555
616
|
import * as Lark from '@larksuiteoapi/node-sdk';
|
|
556
617
|
|
|
@@ -587,6 +648,28 @@ wsClient.start({
|
|
|
587
648
|
});
|
|
588
649
|
```
|
|
589
650
|
|
|
651
|
+
### Channel 模块
|
|
652
|
+
|
|
653
|
+
`Channel` 是在 `WSClient` / `Client` 之上封装的高层模块,一站式封装飞书机器人接入的传输、消息归一化、安全策略、出站发送、流式回复、媒体上传、卡片交互等杂活,适合会话式机器人(AI 对话、流式回复、卡片按钮等)场景。
|
|
654
|
+
|
|
655
|
+
```typescript
|
|
656
|
+
import { createLarkChannel } from '@larksuiteoapi/node-sdk';
|
|
657
|
+
|
|
658
|
+
const channel = createLarkChannel({ appId, appSecret });
|
|
659
|
+
|
|
660
|
+
channel.on('message', async (msg) => {
|
|
661
|
+
await channel.send(
|
|
662
|
+
msg.chatId,
|
|
663
|
+
{ markdown: `收到:${msg.content}` },
|
|
664
|
+
{ replyTo: msg.messageId },
|
|
665
|
+
);
|
|
666
|
+
});
|
|
667
|
+
|
|
668
|
+
await channel.connect();
|
|
669
|
+
```
|
|
670
|
+
|
|
671
|
+
完整用法(事件监听、发送消息、流式回复、底层能力、错误处理、配置项等)见 [docs/channel.zh.md](./docs/channel.zh.md)。
|
|
672
|
+
|
|
590
673
|
### [消息卡片](https://open.feishu.cn/document/ukTMukTMukTM/uczM3QjL3MzN04yNzcDN)
|
|
591
674
|
|
|
592
675
|
对消息卡片的处理亦是对事件处理的一种,两者的不同点仅在于消息卡片的处理器用于响应用户与消息卡片交互所产生的事件,若处理器有返回值(*返回值的数据结构理应为符合[消息卡片结构](https://open.feishu.cn/document/ukTMukTMukTM/uEjNwUjLxYDM14SM2ATN)所定义的结构*),则返回值被用来更新被响应的消息卡片:
|
|
@@ -619,15 +702,16 @@ server.listen(3000);
|
|
|
619
702
|
|
|
620
703
|
#### `CardActionHandler`构造参数
|
|
621
704
|
|
|
622
|
-
|
|
|
623
|
-
|
|
|
624
|
-
| [encryptKey](https://open.feishu.cn/document/ukTMukTMukTM/uYDNxYjL2QTM24iN0EjN/event-subscription-configure-/encrypt-key-encryption-configuration-case)
|
|
625
|
-
| [verificationToken](https://open.feishu.cn/document/ukTMukTMukTM/uYzMxEjL2MTMx4iNzETM)
|
|
626
|
-
| loggerLevel
|
|
627
|
-
| logger
|
|
628
|
-
| cache
|
|
705
|
+
| 参数 | 描述 | 类型 | 必须 | 默认 |
|
|
706
|
+
| ------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------- | ----------- | -- | ---------------- |
|
|
707
|
+
| [encryptKey](https://open.feishu.cn/document/ukTMukTMukTM/uYDNxYjL2QTM24iN0EjN/event-subscription-configure-/encrypt-key-encryption-configuration-case) | 推送数据加密的key,开启加密推送时需要使用来进行数据解密 | string | 否 | - |
|
|
708
|
+
| [verificationToken](https://open.feishu.cn/document/ukTMukTMukTM/uYzMxEjL2MTMx4iNzETM) | 安全校验,开启消息的安全校验时需要使用 | string | 否 | - |
|
|
709
|
+
| loggerLevel | 日志级别 | LoggerLevel | 否 | LoggerLevel.info |
|
|
710
|
+
| logger | - | Logger | 否 | - |
|
|
711
|
+
| cache | 缓存器 | Cache | 否 | - |
|
|
629
712
|
|
|
630
713
|
### 一键创建应用
|
|
714
|
+
|
|
631
715
|
SDK提供了`registerApp`方法,基于 OAuth 2.0 Device Authorization Grant(RFC 8628)协议实现一键创建应用。该方法会返回一个验证链接,用户在飞书/Lark中打开该链接完成授权后,即可自动注册应用并获取凭据,无需手动到开发者后台创建。
|
|
632
716
|
|
|
633
717
|
```typescript
|
|
@@ -661,37 +745,41 @@ try {
|
|
|
661
745
|
|
|
662
746
|
#### `registerApp`参数
|
|
663
747
|
|
|
664
|
-
| 参数
|
|
665
|
-
|
|
|
666
|
-
| domain
|
|
667
|
-
| larkDomain
|
|
668
|
-
| source
|
|
669
|
-
| signal
|
|
670
|
-
| onQRCodeReady
|
|
671
|
-
| onStatusChange | 轮询状态变化时的回调,参数为 `{ status, interval? }`。status 取值:`polling`、`slow_down`、`domain_switched` | function
|
|
748
|
+
| 参数 | 描述 | 类型 | 必须 | 默认 |
|
|
749
|
+
| -------------- | ---------------------------------------------------------------------------------------- | ----------- | -- | ------------------------ |
|
|
750
|
+
| domain | 自定义认证域名(仅 host 部分) | string | 否 | `accounts.feishu.cn` |
|
|
751
|
+
| larkDomain | 自定义 Lark 认证域名(仅 host 部分),检测到 Lark 租户时自动切换 | string | 否 | `accounts.larksuite.com` |
|
|
752
|
+
| source | 来源标识,拼入二维码 URL 的 `from` 参数,格式为 `node-sdk/{source}` | string | 否 | - |
|
|
753
|
+
| signal | 用于取消轮询的 `AbortSignal` | AbortSignal | 否 | - |
|
|
754
|
+
| onQRCodeReady | 验证链接就绪时的回调,参数为 `{ url, expireIn }`。可将 URL 渲染为二维码供用户扫码,或直接作为链接展示 | function | 是 | - |
|
|
755
|
+
| onStatusChange | 轮询状态变化时的回调,参数为 `{ status, interval? }`。status 取值:`polling`、`slow_down`、`domain_switched` | function | 否 | - |
|
|
672
756
|
|
|
673
757
|
#### 返回值
|
|
674
758
|
|
|
675
|
-
| 字段
|
|
676
|
-
|
|
|
677
|
-
|
|
|
678
|
-
|
|
|
679
|
-
|
|
|
680
|
-
|
|
|
681
|
-
|
|
|
759
|
+
| 字段 | 类型 | 描述 |
|
|
760
|
+
| ------------------------ | ---------- | --------------------- |
|
|
761
|
+
| client\_id | string | App ID |
|
|
762
|
+
| client\_secret | string | App Secret |
|
|
763
|
+
| user\_info | object(可选) | 扫码用户信息 |
|
|
764
|
+
| user\_info.open\_id | string(可选) | 扫码用户的 open\_id |
|
|
765
|
+
| user\_info.tenant\_brand | string(可选) | `"feishu"` 或 `"lark"` |
|
|
682
766
|
|
|
683
767
|
#### 错误处理
|
|
768
|
+
|
|
684
769
|
抛出的错误对象包含 `code` 和 `description` 字段:
|
|
685
770
|
|
|
686
|
-
| code
|
|
687
|
-
|
|
|
688
|
-
| `access_denied` | 用户拒绝了授权
|
|
689
|
-
| `expired_token` | 二维码过期或轮询超时
|
|
690
|
-
| `abort`
|
|
771
|
+
| code | 描述 |
|
|
772
|
+
| --------------- | ----------------- |
|
|
773
|
+
| `access_denied` | 用户拒绝了授权 |
|
|
774
|
+
| `expired_token` | 二维码过期或轮询超时 |
|
|
775
|
+
| `abort` | 通过 AbortSignal 取消 |
|
|
691
776
|
|
|
692
777
|
### 工具方法
|
|
778
|
+
|
|
693
779
|
#### AESCipher
|
|
780
|
+
|
|
694
781
|
解密。如果配置了[加密推送](https://open.feishu.cn/document/ukTMukTMukTM/uYDNxYjL2QTM24iN0EjN/event-subscription-configure-/encrypt-key-encryption-configuration-case),开放平台会推送加密的数据,这时候需要对数据进行解密处理,调用此方法可以便捷的进行解密。(一般情况下,SDK中内置了解密逻辑,不需要手动进行处理)。
|
|
782
|
+
|
|
695
783
|
```typescript
|
|
696
784
|
import * as lark from '@larksuiteoapi/node-sdk';
|
|
697
785
|
|
|
@@ -699,13 +787,17 @@ new lark.AESCipher('encrypt key').decrypt('content');
|
|
|
699
787
|
```
|
|
700
788
|
|
|
701
789
|
## Examples
|
|
790
|
+
|
|
702
791
|
[快速开发自动回复机器人](https://github.com/larksuite/lark-samples/blob/main/react_and_nodejs/robot/README.zh.md)
|
|
703
792
|
|
|
704
793
|
## Blog
|
|
794
|
+
|
|
705
795
|
[ISV(商店应用)开发指南](https://bytedance.feishu.cn/docx/RUZKdGwdyoH4KexMJgDcITQnn0b)
|
|
706
796
|
|
|
707
797
|
## 许可协议
|
|
798
|
+
|
|
708
799
|
MIT
|
|
709
800
|
|
|
710
801
|
## 联系我们
|
|
802
|
+
|
|
711
803
|
点击[服务端SDK](https://open.feishu.cn/document/ukTMukTMukTM/uETO1YjLxkTN24SM5UjN) 页面右上角【这篇文档是否对你有帮助?】提交反馈😘
|