处理事件
通过事件订阅功能,应用可以及时接收飞书中资源数据的变化,并根据变化情况做对应的业务处理,详情参见事件概述。在应用内订阅事件时,还需要在本地服务端建立与应用的连接,以便接收事件数据。服务端 SDK 封装了长连接方式,可以快速建立数据通道处理事件;你也可以选择自建 HTTP 服务器处理事件。两种方式介绍如下:
| 订阅方式 | 介绍 |
|---|---|
| 使用长连接接收事件 | 该方式是飞书 SDK 内提供的能力,你可以通过集成飞书 SDK 与开放平台建立一条 WebSocket 全双工通道(你的服务器需要能够访问公网)。后续当应用订阅的事件发生时,开放平台会通过该通道向你的服务器发送消息。相较于传统的 Webhook 模式,长连接模式大大降低了接入成本,将原先 1 周左右的开发周期降低到 5 分钟。具体优势如下:测试阶段无需使用内网穿透工具,通过长连接模式在本地开发环境中即可接收事件回调。SDK 内封装了鉴权逻辑,只在建连时进行鉴权,后续事件推送均为明文数据,无需再处理解密和验签逻辑。只需保证运行环境具备访问公网能力即可,无需提供公网 IP 或域名。无需部署防火墙和配置白名单。 |
| 将事件发送至开发者服务器 | 传统的 Webhook 模式,该方式需要你提供用于接收事件消息的服务器公网地址。后续当应用订阅的事件发生时,开放平台会向服务器的公网地址发送 HTTP POST 请求,请求内包含事件数据。 |
(推荐)方式一:使用长连接接收事件
如果事件订阅方式需要选择 使用长连接接收事件,则需要先使用 SDK 建立与应用的连接。本章节提供建立长连接的示例代码与代码解析,通过 SDK 建立长连接之后,你才能在应用的事件订阅方式中保存 使用长连接接收事件 方式。关于应用内配置事件订阅方式的介绍,参考配置事件订阅方式。

注意事项
在开始配置之前,你需要确保已了解以下注意事项:
- 目前长连接模式仅支持企业自建应用。
- 与 将事件发送至开发者服务器 方式(即自建服务器方式)的要求相同,长连接模式下接收到消息后,需要在 3 秒内处理完成,否则会触发超时重推机制。
- 每个应用最多建立 50 个连接(在配置长连接时,每初始化一个 client 就是一个连接)。
- 长连接模式的消息推送为 集群模式,不支持广播,即如果同一应用部署了多个客户端(client),那么只有其中随机一个客户端会收到消息。
长连接代码
import lark_oapi as lark
## P2ImMessageReceiveV1 为接收消息 v2.0;CustomizedEvent 内的 message 为接收消息 v1.0。
def do_p2_im_message_receive_v1(data: lark.im.v1.P2ImMessageReceiveV1) -> None:
print(f'[ do_p2_im_message_receive_v1 access ], data: {lark.JSON.marshal(data, indent=4)}')
def do_message_event(data: lark.CustomizedEvent) -> None:
print(f'[ do_customized_event access ], type: message, data: {lark.JSON.marshal(data, indent=4)}')
event_handler = lark.EventDispatcherHandler.builder("", "") \
.register_p2_im_message_receive_v1(do_p2_im_message_receive_v1) \
.register_p1_customized_event("这里填入你要自定义订阅的 event 的 key,例如 out_approval", do_message_event) \
.build()
def main():
cli = lark.ws.Client("YOUR_APP_ID", "YOUR_APP_SECRET",
event_handler=event_handler,
log_level=lark.LogLevel.DEBUG)
cli.start()
if __name__ == "__main__":
main()代码实现说明:
通过 lark.EventDispatcherHandler.builder() 初始化事件处理器(event_handler),该方法的两个参数必须填空字符串。
通过 event_handler 的
register_{事件版本}_{事件类型 或 customized_event}方法处理不同的事件。在开发者后台应用详情页添加事件时(具体操作可参见添加事件),可获取事件的类型与版本信息。

v2.0 版本的事件
使用
data: lark.im.v1.P2ImMessageReceiveV1指定所选事件,其中:lark.im.v1表示对应的业务域以及版本,可通过事件类型的前缀获取业务域代码,例如im.message.receive_v1对应的业务域代码为im。P2ImMessageReceiveV1中,P2 表示事件版本为 v2.0,ImMessageReceiveV1 对应事件类型im.message.receive_v1。
使用
.register_p2_im_message_receive_v1()处理事件,其中:p2 表示事件版本为 v2.0。
im_message_receive_v1 对应事件类型
im.message.receive_v1。
:::note 说明:代码中的方法格式与事件类型不一致,注意甄别格式上的差异,避免因格式问题导致程序运行失败。
:::v1.0 版本的事件
- 固定使用
data: lark.CustomizedEvent方法,表示处理自定义事件。 - 使用
.register_p1_customized_event("这里填入你要自定义订阅的事件类型,例如 out_approval", do_message_event)处理事件:- p1 表示事件版本为 v1.0。
- customized_event 为固定的方法名称。
- customized_event 方法内需要传入事件 Key(String 类型),例如外出审批的事件类型为 out_approval。
你也可以参考代码片段注释了解如何配置:
python## P2ImMessageReceiveV1: ## P2 对应 v2.0 版本, ## ImMessageReceiveV1 对应接收消息事件类型 im.message.receive_v1。 def do_p2_im_message_receive_v1(data: lark.im.v1.P2ImMessageReceiveV1) -> None: print(f'[ do_p2_im_message_receive_v1 access ], data: {lark.JSON.marshal(data, indent=4)}') ## 如果是 v1.0 版本事件,需要使用 lark.CustomizedEvent def do_message_event(data: lark.CustomizedEvent) -> None: print(f'[ do_customized_event access ], type: message, data: {lark.JSON.marshal(data, indent=4)}') event_handler = lark.EventDispatcherHandler.builder("", "") \ ## register_p2 对应 v2.0 版本, ## im_message_receive_v1 对应接收消息事件类型 im.message.receive_v1。 .register_p2_im_message_receive_v1(do_p2_im_message_receive_v1) \ ## register_p1 对应 v1.0 版本, ## 参数值需要传入事件类型。例如 out_approval .register_p1_customized_event("这里填入你要自定义订阅的 event 的 key,例如 out_approval", do_message_event) \ .build()通过 lark.ws.Client() 初始化长连接客户端,必填参数为应用的 APP_ID 和 APP_SECRET,需登录开发者后台,在应用详情页的 凭证与基础信息 > 应用凭证 区域获取。

可选参数传入 event_handler,同时可设置日志级别。
通过 cli.start() 启动客户端,如连接成功,控制台会打印 "connected to wss://xxxxx",主线程将阻塞,直到进程结束。

方式二:将事件发送至开发者服务器
如果事件订阅方式选择 将事件发送至开发者服务器,则需要设置事件请求地址,后续在事件发生时,开放平台会向该地址发送包含事件 JSON 数据的 HTTP POST 请求。为此你需要在项目中启动一个 HTTP 服务,然后把 HTTP 服务的 URL 绑定到应用的事件订阅中,以接收事件。
本章节提供了使用 flask 启动 httpServer 的示例代码,如果你使用的是其他 Web 框架,只需处理 HTTP 出入参转换即可。以接收消息事件为例,接收事件订阅的示例代码如下:
from flask import Flask
import lark_oapi as lark
from lark_oapi.adapter.flask import *
from lark_oapi.api.im.v1 import *
app = Flask(__name__)
def do_p2_im_message_receive_v1(data: P2ImMessageReceiveV1) -> None:
print(lark.JSON.marshal(data))
def do_customized_event(data: lark.CustomizedEvent) -> None:
print(lark.JSON.marshal(data))
handler = lark.EventDispatcherHandler.builder(lark.ENCRYPT_KEY, lark.VERIFICATION_TOKEN, lark.LogLevel.DEBUG) \
.register_p2_im_message_receive_v1(do_p2_im_message_receive_v1) \
.register_p1_customized_event("message", do_customized_event) \
.build()
@app.route("/event", methods=["POST"])
def event():
resp = handler.do(parse_req())
return parse_resp(resp)
if __name__ == "__main__":
app.run(port=7777)代码片段解析:
事件存在两类结构,v1.0 版本事件结构和 v2.0 版本事件结构。在处理事件需要注意所需的是哪种事件结构。在为应用添加事件时,可获取事件版本和事件类型信息。

v2.0 版本的事件
使用
data: P2ImMessageReceiveV1指定所选事件,P2ImMessageReceiveV1中,P2 表示事件版本为 v2.0,ImMessageReceiveV1 对应事件类型im.message.receive_v1。使用
.register_p2_im_message_receive_v1()处理事件,其中:p2 表示事件版本为 v2.0。
im_message_receive_v1 对应事件类型
im.message.receive_v1。
:::note 说明:代码中的方法格式与事件类型不一致,注意甄别格式上的差异,避免因格式问题导致程序运行失败。
:::v1.0 版本的事件
- 固定使用
data: lark.CustomizedEvent方法,表示处理自定义事件。 - 使用
.register_p1_customized_event("这里填入你要自定义订阅的事件类型,例如 out_approval", do_message_event)处理事件:- p1 表示事件版本为 v1.0。
- customized_event 为固定的方法名称。
- customized_event 方法内需要传入事件 Key(String 类型),例如
message(历史版本 接收消息v1.0 事件)。
你也可以参考代码片段注释了解如何配置:
python## P2ImMessageReceiveV1: ## P2 对应 v2.0 版本, ## ImMessageReceiveV1 对应接收消息事件类型 im.message.receive_v1。 def do_p2_im_message_receive_v1(data: P2ImMessageReceiveV1) -> None: print(lark.JSON.marshal(data)) ## 如果是 v1.0 版本事件,需要使用 lark.CustomizedEvent def do_customized_event(data: lark.CustomizedEvent) -> None: print(lark.JSON.marshal(data)) handler = lark.EventDispatcherHandler.builder(lark.ENCRYPT_KEY, lark.VERIFICATION_TOKEN, lark.LogLevel.DEBUG) \ ## register_p2 对应 v2.0 版本, ## im_message_receive_v1 对应接收消息事件类型 im.message.receive_v1。 .register_p2_im_message_receive_v1(do_p2_im_message_receive_v1) \ ## register_p1 对应 v1.0 版本, ## 参数值需要传入事件类型。例如 message(历史版本 接收消息v1.0 事件) .register_p1_customized_event("message", do_customized_event) \ .build()如果你在开发者后台的应用详情中,配置了 事件与回调 > 加密策略 页面内的加密信息(Encrypt Key 和 Verification Token)。

则必须将加密信息的值传递到
EventDispatcherHandler.builder方法的参数中。pythonhandler = lark.EventDispatcherHandler.builder(lark.ENCRYPT_KEY, lark.VERIFICATION_TOKEN, lark.LogLevel.DEBUG) \ .register_p2_im_message_receive_v1(do_p2_im_message_receive_v1) \ .register_p1_customized_event("message", do_customized_event) \ .build()
其他事件示例参见事件示例代码。
