# 飞书开放接口 SDK
为帮助开发者更加便捷地使用飞书开放能力开发应用,简化在接入飞书开放平台时的操作步骤,开放平台提供了统一的服务端 SDK。开发者可使用 SDK,快捷地开发功能,提升开发效率。
## 安装
```shell
pip install lark-oapi -U
```
支持 Python 3.7 及以上
## 简单示例
```python
import lark_oapi as lark
# 创建client
client = lark.Client.builder().app_id("APP_ID").app_secret("APP_SECRET").build()
# 构造请求对象
request = lark.contact.v3.GetUserRequest.builder().user_id("7be5fg9a").build()
# 发起请求
response = client.contact.v3.user.get(request)
```
更多示例可参考:[请求示例](./samples/api)
## API Client
开发者在调用 API 前,需要先创建一个 API Client,然后才可以基于 API Client 发起 API 调用。
### 创建 Client
- 自建应用
```python
import lark_oapi as lark
client = lark.Client.builder() \
.app_id("APP_ID") \
.app_secret("APP_SECRET") \
.build()
```
- 商店应用
```python
import lark_oapi as lark
client = lark.Client.builder() \
.app_id("APP_ID") \
.app_secret("APP_SECRET") \
.app_type(lark.AppType.ISV) \
.build()
```
### Client 配置项
创建 API Client 时,可以对 API Client 进行一定的配置,比如我们可以在创建 API Client 时设置日志级别、http 请求超时时间等。
```python
import lark_oapi as lark
client = lark.Client.builder() \
.app_id("APP_ID") \
.app_secret("APP_SECRET") \
.domain(lark.FEISHU_DOMAIN) \ # 域名, 默认为 https://open.feishu.cn
.timeout(3) \ # 客户端超时时间, 单位秒, 默认永不超时
.app_type(lark.AppType.ISV) \ # 应用类型, 默认为自建应用; 若设为 ISV 需在 request_option 中配置 tenant_key
.app_ticket("xxxx") \ # 获取 app_access_token 凭证, app_type = ISV 时需配置
.enable_set_token(False) \ # 是否允许手动设置 token, 默认不开启; 开启后需在 request_option 中配置 token
.cache(Cache()) \ # 自定义缓存, 默认使用预置的本地缓存
.log_level(lark.LogLevel.DEBUG) \ # 日志级别, 默认为 WARNING
.build()
```
## API 调用
创建完 API Client 后,我们可以使用 ``client.业务域.版本.资源.方法名称`` 来定位具体的 API 方法,然后对具体的 API 发起调用。
![client_expr](./doc/client_expr.png)
飞书开放平台开放的所有 API
列表,可点击[这里查看](https://open.feishu.cn/document/ukTMukTMukTM/uYTM5UjL2ETO14iNxkTN/server-api-list)
### 基本用法
如下示例,我们通过 client 调用 [通过手机号或邮箱获取用户 ID](https://open.feishu.cn/document/server-docs/contact-v3/user/batch_get_id) 接口。
```python
# Code generated by Lark OpenAPI.
import lark_oapi as lark
from lark_oapi.api.contact.v3 import *
client = lark.Client.builder() \
.app_id("APP_ID") \
.app_secret("APP_SECRET") \
.log_level(lark.LogLevel.DEBUG) \
.build()
# 构造请求对象
request: BatchGetIdUserRequest = BatchGetIdUserRequest.builder() \
.user_id_type("open_id") \
.request_body(BatchGetIdUserRequestBody.builder()
.emails(["xxxx@bytedance.com"])
.mobiles(["15000000000"])
.build()) \
.build()
# 发起请求
response: BatchGetIdUserResponse = client.contact.v3.user.batch_get_id(request)
# 处理失败返回
if not response.success():
lark.logger.error(
f"client.contact.v3.user.batch_get_id failed, code: {response.code}, msg: {response.msg}, log_id: {response.get_log_id()}")
# 处理业务结果
lark.logger.info(lark.JSON.marshal(response.data, indent=4))
```
更多示例可参考:[请求示例](./samples/api)
### Request 配置项
在每次发起 API 调用时,可以设置请求级别的一些参数,比如传递 userAccessToken, 自定义 headers 等。
```python
import lark_oapi as lark
from lark_oapi.api.contact.v3 import *
# 创建client
import lark_oapi as lark
from lark_oapi.api.contact.v3 import *
# 创建client
client = lark.Client.builder() \
.enable_set_token(True) \
.log_level(lark.LogLevel.DEBUG) \
.build()
# 构造请求对象
request: BatchGetIdUserRequest = BatchGetIdUserRequest.builder() \
.user_id_type("open_id") \
.request_body(BatchGetIdUserRequestBody.builder()
.emails(["xxxx@bytedance.com"])
.mobiles(["15000000000"])
.build()) \
.build()
# 设置请求选项
headers = {"key1": "value1", "key2": "value2"}
req_opt = lark.RequestOption.builder()\
.tenant_access_token("t-g1047hjTXIZKCBFYWXUCK3D2LJWZYCWYL7USXXXX")\
.headers(headers)\
.build()
# 发起请求
response: BatchGetIdUserResponse = client.contact.v3.user.batch_get_id(request, req_opt)
# 处理失败返回
if not response.success():
lark.logger.error(
f"client.contact.v3.user.batch_get_id failed, code: {response.code}, msg: {response.msg}, log_id: {response.get_log_id()}")
# 处理业务结果
lark.logger.info(lark.JSON.marshal(response.data, indent=4))
```
如上使用 RequestOptions 的 Builder 模式构建请求级别的参数。如下表格,展示了所有可设置的选项:
<table>
<thead align=left>
<tr>
<th>
配置选项
</th>
<th>
描述
</th>
</tr>
</thead>
<tbody align=left valign=top>
<tr>
<th>
<code>tenant_key</code>
</th>
<td>租户 key, 商店应用必须设置该选项。</td>
</tr>
<tr>
<th>
<code>user_access_token</code>
</th>
<td>用户 token,创建 Client 时 enable_set_token 需要设置为 True。</td>
</tr>
<tr>
<th>
<code>tenant_access_token</code>
</th>
<td>租户 token,创建 Client 时 enable_set_token 需要设置为 True。</td>
</tr>
<tr>
<th>
<code>app_access_token</code>
</th>
<td>应用 token,创建 Client 时 enable_set_token 需要设置为 True。</td>
</tr>
<tr>
<th>
<code>headers</code>
</th>
<td>自定义请求头,这些请求头会被透传到飞书开放平台服务端。</td
</tr>
</tbody>
</table>
### 原生方式调用
部分老版本接口,由于没有元数据信息,所以无法生成对应的 SDK 模型,需要使用原生方式调用。
如下示例,使用 client 原生方式同样调用 [通过手机号或邮箱获取用户 ID](https://open.feishu.cn/document/server-docs/contact-v3/user/batch_get_id) 接口。
```python
import lark_oapi as lark
# 创建client
client = lark.Client.builder() \
.app_id("APP_ID") \
.app_secret("APP_SECRET") \
.log_level(lark.LogLevel.DEBUG) \
.build()
# 构造请求对象
request: lark.BaseRequest = lark.BaseRequest.builder() \
.http_method(lark.HttpMethod.POST) \
.uri("/open-apis/contact/v3/users/batch_get_id") \
.token_types({lark.AccessTokenType.TENANT}) \
.queries([("user_id_type", "open_id")]) \
.body({"emails": ["xxxx@bytedance.com"], "mobiles": ["15000000000"]}) \
.build()
# 发起请求
response: lark.BaseResponse = client.request(request)
# 处理失败返回
if not response.success():
lark.logger.error(
f"client.request failed, code: {response.code}, msg: {response.msg}, log_id: {response.get_log_id()}")
# 处理业务结果
lark.logger.info(str(response.raw.content, lark.UTF_8))
```
更多示例可参考:[原生调用](samples/api/raw.py)
## 处消事件订阅
了解事件订阅相关的知识,可以 [点击这里](https://open.feishu.cn/document/ukTMukTMukTM/uUTNz4SN1MjL1UzM)
获取飞书开放平台开放的所有事件列表,可以 [点击这里](https://open.feishu.cn/document/ukTMukTMukTM/uYDNxYjL2QTM24iN0EjN/event-list)
### 基本用法
开发者订阅事件后,可以使用下面代码,对飞书开放平台推送的消息事件进行处理。
如下示例中使用 flask 启动 httpServer,如使用其他 web 框架,只需处理 http 出入参转换即可。
```python
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("这里填入你要自定义订阅的 event 的 key,例如 out_approval", 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)
```
其中 EventDispatcherHandler.builder(encrypt_key: str, verification_token: str) 方法参数用于签名验证和消息解密使用, 可在 [开发者后台](https://open.feishu.cn/app?lang=zh-CN) ->「事件订阅」中查看。
![console](doc/console.jpeg)
需要注意的是注册处理器时,比如使用 register_p2_im_message_receive_v1 注册接受消息事件回调时,其中的 P2 为消息协议版本,当前飞书开放平台存在 [两种消息协议](https://open.feishu.cn/document/ukTMukTMukTM/uUTNz4SN1MjL1UzM#8f960a4b) ,分别为 1.0 和 2.0。
如下图开发者在注册消息处理器时,需从 [事件列表](https://open.feishu.cn/document/ukTMukTMukTM/uYDNxYjL2QTM24iN0EjN/event-list) 中查看自己需要的是哪种协议的事件。
如果是 1.0 的消息协议,则注册处理器时,需要找以 register_p1_xxxx 开头的。如果是 2.0 的消息协议,则注册处理器时,需要找以 register_p2_xxxx 开头的。
若在 SDK 中未找到处理器,可使用 register_p1_customized_event 或 register_p2_customized_event 注册自定义事件。
![event_prot](doc/event_prot.png)
更多示例可参考:[事件回调](samples/event)
## 处理卡片行为回调
关于卡片行为相关的知识,可点击[这里查看](https://open.feishu.cn/document/ukTMukTMukTM/uczM3QjL3MzN04yNzcDN)
以下示例为处理消息卡片回传交互(旧)(card.action.trigger_v1)的写法。
新版本卡片回传交互 (card.action.trigger) 请参考事件订阅 [event samples](./samples/event/flask_sample.py) 中 register_p2_card_action_trigger
### 基本用法
开发者可以使用下面代码处理卡片回调,示例中使用 flask 启动 httpServer,如使用其他 web 框架,只需处理 http 出入参转换即可。
```python
from typing import Any
from flask import Flask
import lark_oapi as lark
from lark_oapi.adapter.flask import *
app = Flask(__name__)
def do_interactive_card(data: lark.Card) -> Any:
print(lark.JSON.marshal(data))
content = {
"header": {
"title": {
"tag": "plain_text",
"content": "更新卡片成功"
},
"template": "green"
},
"elements": [
{
"tag": "div",
"text": {
"tag": "lark_md",
"content": "**Success!\n成功啦😄**"
}
},
]
}
return content
handler = lark.CardActionHandler.builder(lark.ENCRYPT_KEY, lark.VERIFICATION_TOKEN, lark.LogLevel.DEBUG) \
.register(do_interactive_card) \
.build()
@app.route("/card", methods=["POST"])
def card():
resp = handler.do(parse_req())
return parse_resp(resp)
if __name__ == "__main__":
app.run(port=7777)
```
更多示例可参考:[事件回调](samples/card)
## 扩展示例
我们还基于 SDK 封装了常用的 API 组合调用及业务场景示例,如:
* 消息
* [发送文件消息](https://github.com/larksuite/oapi-sdk-python-demo/blob/main/composite_api/im/send_file.py)
* [发送图片消息](https://github.com/larksuite/oapi-sdk-python-demo/blob/main/composite_api/im/send_image.py)
* 通讯录
* [获取部门下所有用户列表](https://github.com/larksuite/oapi-sdk-python-demo/blob/main/composite_api/contact/list_user_by_department.py)
* 多维表格
* [创建多维表格同时添加数据表](https://github.com/larksuite/oapi-sdk-python-demo/blob/main/composite_api/base/create_app_and_tables.py)
* 电子表格
* [复制粘贴某个范围的单元格数据](https://github.com/larksuite/oapi-sdk-python-demo/blob/main/composite_api/sheets/copy_and_paste_by_range.py)
* [下载指定范围单元格的所有素材列表](https://github.com/larksuite/oapi-sdk-python-demo/blob/main/composite_api/sheets/download_media_by_range.py)
* 教程
* [机器人自动拉群报警](https://github.com/larksuite/oapi-sdk-python-demo/blob/main/quick_start/robot) ([开发教程](https://open.feishu.cn/document/home/message-development-tutorial/introduction))
更多示例可参考:https://github.com/larksuite/oapi-sdk-python-demo
## License
MIT
## 加入讨论群
[_单击_](https://applink.feishu.cn/client/chat/chatter/add_by_link?link_token=575k28fa-2c12-400a-80c0-2d8924e00d38)或扫码加入讨论群
<img src="doc/qrcode.png" width="200" alt="讨论群">
Raw data
{
"_id": null,
"home_page": "https://github.com/larksuite/oapi-sdk-python",
"name": "lark-oapi",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.7",
"maintainer_email": null,
"keywords": "Lark, OpenAPI",
"author": "Wenbo Mao",
"author_email": "maowenbo@bytedance.com",
"download_url": "https://files.pythonhosted.org/packages/fe/51/2d0000a9f9433f2dec679e304c8cdd99bb858e214cad52723c0c7fbeb7e5/lark-oapi-1.4.0.tar.gz",
"platform": null,
"description": "# \u98de\u4e66\u5f00\u653e\u63a5\u53e3 SDK\n\u4e3a\u5e2e\u52a9\u5f00\u53d1\u8005\u66f4\u52a0\u4fbf\u6377\u5730\u4f7f\u7528\u98de\u4e66\u5f00\u653e\u80fd\u529b\u5f00\u53d1\u5e94\u7528\uff0c\u7b80\u5316\u5728\u63a5\u5165\u98de\u4e66\u5f00\u653e\u5e73\u53f0\u65f6\u7684\u64cd\u4f5c\u6b65\u9aa4\uff0c\u5f00\u653e\u5e73\u53f0\u63d0\u4f9b\u4e86\u7edf\u4e00\u7684\u670d\u52a1\u7aef SDK\u3002\u5f00\u53d1\u8005\u53ef\u4f7f\u7528 SDK\uff0c\u5feb\u6377\u5730\u5f00\u53d1\u529f\u80fd\uff0c\u63d0\u5347\u5f00\u53d1\u6548\u7387\u3002\n\n## \u5b89\u88c5\n```shell\npip install lark-oapi -U\n```\n\u652f\u6301 Python 3.7 \u53ca\u4ee5\u4e0a\n\n## \u7b80\u5355\u793a\u4f8b\n```python\nimport lark_oapi as lark\n\n# \u521b\u5efaclient\nclient = lark.Client.builder().app_id(\"APP_ID\").app_secret(\"APP_SECRET\").build()\n\n# \u6784\u9020\u8bf7\u6c42\u5bf9\u8c61\nrequest = lark.contact.v3.GetUserRequest.builder().user_id(\"7be5fg9a\").build()\n\n# \u53d1\u8d77\u8bf7\u6c42\nresponse = client.contact.v3.user.get(request)\n```\n\u66f4\u591a\u793a\u4f8b\u53ef\u53c2\u8003\uff1a[\u8bf7\u6c42\u793a\u4f8b](./samples/api)\n\n## API Client\n\u5f00\u53d1\u8005\u5728\u8c03\u7528 API \u524d\uff0c\u9700\u8981\u5148\u521b\u5efa\u4e00\u4e2a API Client\uff0c\u7136\u540e\u624d\u53ef\u4ee5\u57fa\u4e8e API Client \u53d1\u8d77 API \u8c03\u7528\u3002\n\n### \u521b\u5efa Client\n- \u81ea\u5efa\u5e94\u7528\n```python\nimport lark_oapi as lark\n\nclient = lark.Client.builder() \\\n .app_id(\"APP_ID\") \\\n .app_secret(\"APP_SECRET\") \\\n .build()\n```\n\n- \u5546\u5e97\u5e94\u7528\n```python\nimport lark_oapi as lark\n\nclient = lark.Client.builder() \\\n .app_id(\"APP_ID\") \\\n .app_secret(\"APP_SECRET\") \\\n .app_type(lark.AppType.ISV) \\\n .build()\n```\n\n### Client \u914d\u7f6e\u9879\n\u521b\u5efa API Client \u65f6\uff0c\u53ef\u4ee5\u5bf9 API Client \u8fdb\u884c\u4e00\u5b9a\u7684\u914d\u7f6e\uff0c\u6bd4\u5982\u6211\u4eec\u53ef\u4ee5\u5728\u521b\u5efa API Client \u65f6\u8bbe\u7f6e\u65e5\u5fd7\u7ea7\u522b\u3001http \u8bf7\u6c42\u8d85\u65f6\u65f6\u95f4\u7b49\u3002\n\n```python\nimport lark_oapi as lark\n\nclient = lark.Client.builder() \\\n .app_id(\"APP_ID\") \\\n .app_secret(\"APP_SECRET\") \\\n .domain(lark.FEISHU_DOMAIN) \\ # \u57df\u540d, \u9ed8\u8ba4\u4e3a https://open.feishu.cn\n .timeout(3) \\ # \u5ba2\u6237\u7aef\u8d85\u65f6\u65f6\u95f4, \u5355\u4f4d\u79d2, \u9ed8\u8ba4\u6c38\u4e0d\u8d85\u65f6\n .app_type(lark.AppType.ISV) \\ # \u5e94\u7528\u7c7b\u578b, \u9ed8\u8ba4\u4e3a\u81ea\u5efa\u5e94\u7528; \u82e5\u8bbe\u4e3a ISV \u9700\u5728 request_option \u4e2d\u914d\u7f6e tenant_key\n .app_ticket(\"xxxx\") \\ # \u83b7\u53d6 app_access_token \u51ed\u8bc1, app_type = ISV \u65f6\u9700\u914d\u7f6e\n .enable_set_token(False) \\ # \u662f\u5426\u5141\u8bb8\u624b\u52a8\u8bbe\u7f6e token, \u9ed8\u8ba4\u4e0d\u5f00\u542f; \u5f00\u542f\u540e\u9700\u5728 request_option \u4e2d\u914d\u7f6e token\n .cache(Cache()) \\ # \u81ea\u5b9a\u4e49\u7f13\u5b58, \u9ed8\u8ba4\u4f7f\u7528\u9884\u7f6e\u7684\u672c\u5730\u7f13\u5b58\n .log_level(lark.LogLevel.DEBUG) \\ # \u65e5\u5fd7\u7ea7\u522b, \u9ed8\u8ba4\u4e3a WARNING\n .build()\n```\n\n## API \u8c03\u7528\n\u521b\u5efa\u5b8c API Client \u540e\uff0c\u6211\u4eec\u53ef\u4ee5\u4f7f\u7528 ``client.\u4e1a\u52a1\u57df.\u7248\u672c.\u8d44\u6e90.\u65b9\u6cd5\u540d\u79f0`` \u6765\u5b9a\u4f4d\u5177\u4f53\u7684 API \u65b9\u6cd5\uff0c\u7136\u540e\u5bf9\u5177\u4f53\u7684 API \u53d1\u8d77\u8c03\u7528\u3002\n\n![client_expr](./doc/client_expr.png)\n\n\u98de\u4e66\u5f00\u653e\u5e73\u53f0\u5f00\u653e\u7684\u6240\u6709 API\n\u5217\u8868\uff0c\u53ef\u70b9\u51fb[\u8fd9\u91cc\u67e5\u770b](https://open.feishu.cn/document/ukTMukTMukTM/uYTM5UjL2ETO14iNxkTN/server-api-list)\n\n### \u57fa\u672c\u7528\u6cd5\n\u5982\u4e0b\u793a\u4f8b\uff0c\u6211\u4eec\u901a\u8fc7 client \u8c03\u7528 [\u901a\u8fc7\u624b\u673a\u53f7\u6216\u90ae\u7bb1\u83b7\u53d6\u7528\u6237 ID](https://open.feishu.cn/document/server-docs/contact-v3/user/batch_get_id) \u63a5\u53e3\u3002\n\n```python\n# Code generated by Lark OpenAPI.\n\nimport lark_oapi as lark\nfrom lark_oapi.api.contact.v3 import *\n\n\nclient = lark.Client.builder() \\\n .app_id(\"APP_ID\") \\\n .app_secret(\"APP_SECRET\") \\\n .log_level(lark.LogLevel.DEBUG) \\\n .build()\n\n# \u6784\u9020\u8bf7\u6c42\u5bf9\u8c61\nrequest: BatchGetIdUserRequest = BatchGetIdUserRequest.builder() \\\n .user_id_type(\"open_id\") \\\n .request_body(BatchGetIdUserRequestBody.builder()\n .emails([\"xxxx@bytedance.com\"])\n .mobiles([\"15000000000\"])\n .build()) \\\n .build()\n\n# \u53d1\u8d77\u8bf7\u6c42\nresponse: BatchGetIdUserResponse = client.contact.v3.user.batch_get_id(request)\n\n# \u5904\u7406\u5931\u8d25\u8fd4\u56de\nif not response.success():\n lark.logger.error(\n f\"client.contact.v3.user.batch_get_id failed, code: {response.code}, msg: {response.msg}, log_id: {response.get_log_id()}\")\n\n# \u5904\u7406\u4e1a\u52a1\u7ed3\u679c\nlark.logger.info(lark.JSON.marshal(response.data, indent=4))\n```\n\u66f4\u591a\u793a\u4f8b\u53ef\u53c2\u8003\uff1a[\u8bf7\u6c42\u793a\u4f8b](./samples/api)\n\n### Request \u914d\u7f6e\u9879\n\u5728\u6bcf\u6b21\u53d1\u8d77 API \u8c03\u7528\u65f6\uff0c\u53ef\u4ee5\u8bbe\u7f6e\u8bf7\u6c42\u7ea7\u522b\u7684\u4e00\u4e9b\u53c2\u6570\uff0c\u6bd4\u5982\u4f20\u9012 userAccessToken, \u81ea\u5b9a\u4e49 headers \u7b49\u3002\n\n```python\nimport lark_oapi as lark\nfrom lark_oapi.api.contact.v3 import *\n\n# \u521b\u5efaclient\nimport lark_oapi as lark\nfrom lark_oapi.api.contact.v3 import *\n\n# \u521b\u5efaclient\nclient = lark.Client.builder() \\\n .enable_set_token(True) \\\n .log_level(lark.LogLevel.DEBUG) \\\n .build()\n\n# \u6784\u9020\u8bf7\u6c42\u5bf9\u8c61\nrequest: BatchGetIdUserRequest = BatchGetIdUserRequest.builder() \\\n .user_id_type(\"open_id\") \\\n .request_body(BatchGetIdUserRequestBody.builder()\n .emails([\"xxxx@bytedance.com\"])\n .mobiles([\"15000000000\"])\n .build()) \\\n .build()\n\n# \u8bbe\u7f6e\u8bf7\u6c42\u9009\u9879\nheaders = {\"key1\": \"value1\", \"key2\": \"value2\"}\nreq_opt = lark.RequestOption.builder()\\\n .tenant_access_token(\"t-g1047hjTXIZKCBFYWXUCK3D2LJWZYCWYL7USXXXX\")\\\n .headers(headers)\\\n .build()\n\n# \u53d1\u8d77\u8bf7\u6c42\nresponse: BatchGetIdUserResponse = client.contact.v3.user.batch_get_id(request, req_opt)\n\n# \u5904\u7406\u5931\u8d25\u8fd4\u56de\nif not response.success():\n lark.logger.error(\n f\"client.contact.v3.user.batch_get_id failed, code: {response.code}, msg: {response.msg}, log_id: {response.get_log_id()}\")\n\n# \u5904\u7406\u4e1a\u52a1\u7ed3\u679c\nlark.logger.info(lark.JSON.marshal(response.data, indent=4))\n```\n\n\u5982\u4e0a\u4f7f\u7528 RequestOptions \u7684 Builder \u6a21\u5f0f\u6784\u5efa\u8bf7\u6c42\u7ea7\u522b\u7684\u53c2\u6570\u3002\u5982\u4e0b\u8868\u683c\uff0c\u5c55\u793a\u4e86\u6240\u6709\u53ef\u8bbe\u7f6e\u7684\u9009\u9879\uff1a\n\n<table>\n <thead align=left>\n <tr>\n <th>\n \u914d\u7f6e\u9009\u9879\n </th>\n <th>\n \u63cf\u8ff0\n </th>\n </tr>\n </thead>\n <tbody align=left valign=top>\n <tr>\n <th>\n <code>tenant_key</code>\n </th>\n <td>\u79df\u6237 key, \u5546\u5e97\u5e94\u7528\u5fc5\u987b\u8bbe\u7f6e\u8be5\u9009\u9879\u3002</td>\n </tr>\n <tr>\n <th>\n <code>user_access_token</code>\n </th>\n <td>\u7528\u6237 token\uff0c\u521b\u5efa Client \u65f6 enable_set_token \u9700\u8981\u8bbe\u7f6e\u4e3a True\u3002</td>\n </tr>\n <tr>\n <th>\n <code>tenant_access_token</code>\n </th>\n <td>\u79df\u6237 token\uff0c\u521b\u5efa Client \u65f6 enable_set_token \u9700\u8981\u8bbe\u7f6e\u4e3a True\u3002</td>\n </tr>\n <tr>\n <th>\n <code>app_access_token</code>\n </th>\n <td>\u5e94\u7528 token\uff0c\u521b\u5efa Client \u65f6 enable_set_token \u9700\u8981\u8bbe\u7f6e\u4e3a True\u3002</td>\n </tr>\n <tr>\n <th>\n <code>headers</code>\n </th>\n <td>\u81ea\u5b9a\u4e49\u8bf7\u6c42\u5934\uff0c\u8fd9\u4e9b\u8bf7\u6c42\u5934\u4f1a\u88ab\u900f\u4f20\u5230\u98de\u4e66\u5f00\u653e\u5e73\u53f0\u670d\u52a1\u7aef\u3002</td\n </tr>\n </tbody>\n</table>\n\n### \u539f\u751f\u65b9\u5f0f\u8c03\u7528\n\u90e8\u5206\u8001\u7248\u672c\u63a5\u53e3\uff0c\u7531\u4e8e\u6ca1\u6709\u5143\u6570\u636e\u4fe1\u606f\uff0c\u6240\u4ee5\u65e0\u6cd5\u751f\u6210\u5bf9\u5e94\u7684 SDK \u6a21\u578b\uff0c\u9700\u8981\u4f7f\u7528\u539f\u751f\u65b9\u5f0f\u8c03\u7528\u3002\n\n\u5982\u4e0b\u793a\u4f8b\uff0c\u4f7f\u7528 client \u539f\u751f\u65b9\u5f0f\u540c\u6837\u8c03\u7528 [\u901a\u8fc7\u624b\u673a\u53f7\u6216\u90ae\u7bb1\u83b7\u53d6\u7528\u6237 ID](https://open.feishu.cn/document/server-docs/contact-v3/user/batch_get_id) \u63a5\u53e3\u3002\n\n```python\nimport lark_oapi as lark\n\n\n# \u521b\u5efaclient\nclient = lark.Client.builder() \\\n .app_id(\"APP_ID\") \\\n .app_secret(\"APP_SECRET\") \\\n .log_level(lark.LogLevel.DEBUG) \\\n .build()\n\n# \u6784\u9020\u8bf7\u6c42\u5bf9\u8c61\nrequest: lark.BaseRequest = lark.BaseRequest.builder() \\\n .http_method(lark.HttpMethod.POST) \\\n .uri(\"/open-apis/contact/v3/users/batch_get_id\") \\\n .token_types({lark.AccessTokenType.TENANT}) \\\n .queries([(\"user_id_type\", \"open_id\")]) \\\n .body({\"emails\": [\"xxxx@bytedance.com\"], \"mobiles\": [\"15000000000\"]}) \\\n .build()\n\n# \u53d1\u8d77\u8bf7\u6c42\nresponse: lark.BaseResponse = client.request(request)\n\n# \u5904\u7406\u5931\u8d25\u8fd4\u56de\nif not response.success():\n lark.logger.error(\n f\"client.request failed, code: {response.code}, msg: {response.msg}, log_id: {response.get_log_id()}\")\n\n# \u5904\u7406\u4e1a\u52a1\u7ed3\u679c\nlark.logger.info(str(response.raw.content, lark.UTF_8))\n```\n\u66f4\u591a\u793a\u4f8b\u53ef\u53c2\u8003\uff1a[\u539f\u751f\u8c03\u7528](samples/api/raw.py)\n\n## \u5904\u6d88\u4e8b\u4ef6\u8ba2\u9605\n\u4e86\u89e3\u4e8b\u4ef6\u8ba2\u9605\u76f8\u5173\u7684\u77e5\u8bc6\uff0c\u53ef\u4ee5 [\u70b9\u51fb\u8fd9\u91cc](https://open.feishu.cn/document/ukTMukTMukTM/uUTNz4SN1MjL1UzM)\n\n\u83b7\u53d6\u98de\u4e66\u5f00\u653e\u5e73\u53f0\u5f00\u653e\u7684\u6240\u6709\u4e8b\u4ef6\u5217\u8868\uff0c\u53ef\u4ee5 [\u70b9\u51fb\u8fd9\u91cc](https://open.feishu.cn/document/ukTMukTMukTM/uYDNxYjL2QTM24iN0EjN/event-list)\n### \u57fa\u672c\u7528\u6cd5\n\u5f00\u53d1\u8005\u8ba2\u9605\u4e8b\u4ef6\u540e\uff0c\u53ef\u4ee5\u4f7f\u7528\u4e0b\u9762\u4ee3\u7801\uff0c\u5bf9\u98de\u4e66\u5f00\u653e\u5e73\u53f0\u63a8\u9001\u7684\u6d88\u606f\u4e8b\u4ef6\u8fdb\u884c\u5904\u7406\u3002\n\n\u5982\u4e0b\u793a\u4f8b\u4e2d\u4f7f\u7528 flask \u542f\u52a8 httpServer\uff0c\u5982\u4f7f\u7528\u5176\u4ed6 web \u6846\u67b6\uff0c\u53ea\u9700\u5904\u7406 http \u51fa\u5165\u53c2\u8f6c\u6362\u5373\u53ef\u3002\n\n```python\nfrom flask import Flask\n\nimport lark_oapi as lark\nfrom lark_oapi.adapter.flask import *\nfrom lark_oapi.api.im.v1 import *\n\napp = Flask(__name__)\n\n\ndef do_p2_im_message_receive_v1(data: P2ImMessageReceiveV1) -> None:\n print(lark.JSON.marshal(data))\n\n\ndef do_customized_event(data: lark.CustomizedEvent) -> None:\n print(lark.JSON.marshal(data))\n\n\nhandler = lark.EventDispatcherHandler.builder(lark.ENCRYPT_KEY, lark.VERIFICATION_TOKEN, lark.LogLevel.DEBUG) \\\n .register_p2_im_message_receive_v1(do_p2_im_message_receive_v1) \\\n .register_p1_customized_event(\"\u8fd9\u91cc\u586b\u5165\u4f60\u8981\u81ea\u5b9a\u4e49\u8ba2\u9605\u7684 event \u7684 key,\u4f8b\u5982 out_approval\", do_customized_event) \\\n .build()\n\n\n@app.route(\"/event\", methods=[\"POST\"])\ndef event():\n resp = handler.do(parse_req())\n return parse_resp(resp)\n\n\nif __name__ == \"__main__\":\n app.run(port=7777)\n```\n\u5176\u4e2d EventDispatcherHandler.builder(encrypt_key: str, verification_token: str) \u65b9\u6cd5\u53c2\u6570\u7528\u4e8e\u7b7e\u540d\u9a8c\u8bc1\u548c\u6d88\u606f\u89e3\u5bc6\u4f7f\u7528, \u53ef\u5728 [\u5f00\u53d1\u8005\u540e\u53f0](https://open.feishu.cn/app?lang=zh-CN) ->\u300c\u4e8b\u4ef6\u8ba2\u9605\u300d\u4e2d\u67e5\u770b\u3002\n\n![console](doc/console.jpeg)\n\n\u9700\u8981\u6ce8\u610f\u7684\u662f\u6ce8\u518c\u5904\u7406\u5668\u65f6\uff0c\u6bd4\u5982\u4f7f\u7528 register_p2_im_message_receive_v1 \u6ce8\u518c\u63a5\u53d7\u6d88\u606f\u4e8b\u4ef6\u56de\u8c03\u65f6\uff0c\u5176\u4e2d\u7684 P2 \u4e3a\u6d88\u606f\u534f\u8bae\u7248\u672c\uff0c\u5f53\u524d\u98de\u4e66\u5f00\u653e\u5e73\u53f0\u5b58\u5728 [\u4e24\u79cd\u6d88\u606f\u534f\u8bae](https://open.feishu.cn/document/ukTMukTMukTM/uUTNz4SN1MjL1UzM#8f960a4b) \uff0c\u5206\u522b\u4e3a 1.0 \u548c 2.0\u3002\n\n\u5982\u4e0b\u56fe\u5f00\u53d1\u8005\u5728\u6ce8\u518c\u6d88\u606f\u5904\u7406\u5668\u65f6\uff0c\u9700\u4ece [\u4e8b\u4ef6\u5217\u8868](https://open.feishu.cn/document/ukTMukTMukTM/uYDNxYjL2QTM24iN0EjN/event-list) \u4e2d\u67e5\u770b\u81ea\u5df1\u9700\u8981\u7684\u662f\u54ea\u79cd\u534f\u8bae\u7684\u4e8b\u4ef6\u3002\n\n\u5982\u679c\u662f 1.0 \u7684\u6d88\u606f\u534f\u8bae\uff0c\u5219\u6ce8\u518c\u5904\u7406\u5668\u65f6\uff0c\u9700\u8981\u627e\u4ee5 register_p1_xxxx \u5f00\u5934\u7684\u3002\u5982\u679c\u662f 2.0 \u7684\u6d88\u606f\u534f\u8bae\uff0c\u5219\u6ce8\u518c\u5904\u7406\u5668\u65f6\uff0c\u9700\u8981\u627e\u4ee5 register_p2_xxxx \u5f00\u5934\u7684\u3002\n\n\u82e5\u5728 SDK \u4e2d\u672a\u627e\u5230\u5904\u7406\u5668\uff0c\u53ef\u4f7f\u7528 register_p1_customized_event \u6216 register_p2_customized_event \u6ce8\u518c\u81ea\u5b9a\u4e49\u4e8b\u4ef6\u3002\n\n![event_prot](doc/event_prot.png)\n\n\u66f4\u591a\u793a\u4f8b\u53ef\u53c2\u8003\uff1a[\u4e8b\u4ef6\u56de\u8c03](samples/event)\n\n## \u5904\u7406\u5361\u7247\u884c\u4e3a\u56de\u8c03\n\u5173\u4e8e\u5361\u7247\u884c\u4e3a\u76f8\u5173\u7684\u77e5\u8bc6\uff0c\u53ef\u70b9\u51fb[\u8fd9\u91cc\u67e5\u770b](https://open.feishu.cn/document/ukTMukTMukTM/uczM3QjL3MzN04yNzcDN)\n\n\u4ee5\u4e0b\u793a\u4f8b\u4e3a\u5904\u7406\u6d88\u606f\u5361\u7247\u56de\u4f20\u4ea4\u4e92\uff08\u65e7\uff09\uff08card.action.trigger_v1\uff09\u7684\u5199\u6cd5\u3002 \n\n\u65b0\u7248\u672c\u5361\u7247\u56de\u4f20\u4ea4\u4e92 (card.action.trigger) \u8bf7\u53c2\u8003\u4e8b\u4ef6\u8ba2\u9605 [event samples](./samples/event/flask_sample.py) \u4e2d register_p2_card_action_trigger\n\n### \u57fa\u672c\u7528\u6cd5\n\u5f00\u53d1\u8005\u53ef\u4ee5\u4f7f\u7528\u4e0b\u9762\u4ee3\u7801\u5904\u7406\u5361\u7247\u56de\u8c03\uff0c\u793a\u4f8b\u4e2d\u4f7f\u7528 flask \u542f\u52a8 httpServer\uff0c\u5982\u4f7f\u7528\u5176\u4ed6 web \u6846\u67b6\uff0c\u53ea\u9700\u5904\u7406 http \u51fa\u5165\u53c2\u8f6c\u6362\u5373\u53ef\u3002\n\n```python\nfrom typing import Any\n\nfrom flask import Flask\n\nimport lark_oapi as lark\nfrom lark_oapi.adapter.flask import *\n\napp = Flask(__name__)\n\n\ndef do_interactive_card(data: lark.Card) -> Any:\n print(lark.JSON.marshal(data))\n content = {\n \"header\": {\n \"title\": {\n \"tag\": \"plain_text\",\n \"content\": \"\u66f4\u65b0\u5361\u7247\u6210\u529f\"\n },\n \"template\": \"green\"\n },\n \"elements\": [\n {\n \"tag\": \"div\",\n \"text\": {\n \"tag\": \"lark_md\",\n \"content\": \"**Success!\\n\u6210\u529f\u5566\ud83d\ude04**\"\n }\n },\n ]\n }\n return content\n\n\nhandler = lark.CardActionHandler.builder(lark.ENCRYPT_KEY, lark.VERIFICATION_TOKEN, lark.LogLevel.DEBUG) \\\n .register(do_interactive_card) \\\n .build()\n\n\n@app.route(\"/card\", methods=[\"POST\"])\ndef card():\n resp = handler.do(parse_req())\n return parse_resp(resp)\n\n\nif __name__ == \"__main__\":\n app.run(port=7777)\n\n```\n\n\u66f4\u591a\u793a\u4f8b\u53ef\u53c2\u8003\uff1a[\u4e8b\u4ef6\u56de\u8c03](samples/card)\n\n## \u6269\u5c55\u793a\u4f8b\n\u6211\u4eec\u8fd8\u57fa\u4e8e SDK \u5c01\u88c5\u4e86\u5e38\u7528\u7684 API \u7ec4\u5408\u8c03\u7528\u53ca\u4e1a\u52a1\u573a\u666f\u793a\u4f8b\uff0c\u5982\uff1a\n* \u6d88\u606f\n * [\u53d1\u9001\u6587\u4ef6\u6d88\u606f](https://github.com/larksuite/oapi-sdk-python-demo/blob/main/composite_api/im/send_file.py)\n * [\u53d1\u9001\u56fe\u7247\u6d88\u606f](https://github.com/larksuite/oapi-sdk-python-demo/blob/main/composite_api/im/send_image.py)\n* \u901a\u8baf\u5f55\n * [\u83b7\u53d6\u90e8\u95e8\u4e0b\u6240\u6709\u7528\u6237\u5217\u8868](https://github.com/larksuite/oapi-sdk-python-demo/blob/main/composite_api/contact/list_user_by_department.py)\n* \u591a\u7ef4\u8868\u683c\n * [\u521b\u5efa\u591a\u7ef4\u8868\u683c\u540c\u65f6\u6dfb\u52a0\u6570\u636e\u8868](https://github.com/larksuite/oapi-sdk-python-demo/blob/main/composite_api/base/create_app_and_tables.py)\n* \u7535\u5b50\u8868\u683c\n * [\u590d\u5236\u7c98\u8d34\u67d0\u4e2a\u8303\u56f4\u7684\u5355\u5143\u683c\u6570\u636e](https://github.com/larksuite/oapi-sdk-python-demo/blob/main/composite_api/sheets/copy_and_paste_by_range.py)\n * [\u4e0b\u8f7d\u6307\u5b9a\u8303\u56f4\u5355\u5143\u683c\u7684\u6240\u6709\u7d20\u6750\u5217\u8868](https://github.com/larksuite/oapi-sdk-python-demo/blob/main/composite_api/sheets/download_media_by_range.py)\n* \u6559\u7a0b\n * [\u673a\u5668\u4eba\u81ea\u52a8\u62c9\u7fa4\u62a5\u8b66](https://github.com/larksuite/oapi-sdk-python-demo/blob/main/quick_start/robot) ([\u5f00\u53d1\u6559\u7a0b](https://open.feishu.cn/document/home/message-development-tutorial/introduction))\n\n\u66f4\u591a\u793a\u4f8b\u53ef\u53c2\u8003\uff1ahttps://github.com/larksuite/oapi-sdk-python-demo\n\n## License\nMIT\n\n## \u52a0\u5165\u8ba8\u8bba\u7fa4\n[_\u5355\u51fb_](https://applink.feishu.cn/client/chat/chatter/add_by_link?link_token=575k28fa-2c12-400a-80c0-2d8924e00d38)\u6216\u626b\u7801\u52a0\u5165\u8ba8\u8bba\u7fa4\n\n<img src=\"doc/qrcode.png\" width=\"200\" alt=\"\u8ba8\u8bba\u7fa4\">\n",
"bugtrack_url": null,
"license": null,
"summary": "Lark OpenAPI SDK for Python",
"version": "1.4.0",
"project_urls": {
"Homepage": "https://github.com/larksuite/oapi-sdk-python",
"Source": "https://github.com/larksuite/oapi-sdk-python"
},
"split_keywords": [
"lark",
" openapi"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "9d3476915eb93bc371d8a888e0b136081eb398c9b5370260aa6b556e5d62f8b4",
"md5": "2e374bfa0d65b6b9760fe3a255356114",
"sha256": "f9dedb3aa6733efff43885d6f5ffb23f473f729129b904ddd1c984c64b19aefd"
},
"downloads": -1,
"filename": "lark_oapi-1.4.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "2e374bfa0d65b6b9760fe3a255356114",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.7",
"size": 4908171,
"upload_time": "2024-11-19T11:57:54",
"upload_time_iso_8601": "2024-11-19T11:57:54.781780Z",
"url": "https://files.pythonhosted.org/packages/9d/34/76915eb93bc371d8a888e0b136081eb398c9b5370260aa6b556e5d62f8b4/lark_oapi-1.4.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "fe512d0000a9f9433f2dec679e304c8cdd99bb858e214cad52723c0c7fbeb7e5",
"md5": "a1dea3a72f3b005d2894d102b9d1ac40",
"sha256": "f06bdf2b4ed41821aa40bb633c4be8631f97933c3d773c9082d32fc59cd7612f"
},
"downloads": -1,
"filename": "lark-oapi-1.4.0.tar.gz",
"has_sig": false,
"md5_digest": "a1dea3a72f3b005d2894d102b9d1ac40",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.7",
"size": 1359445,
"upload_time": "2024-11-19T11:57:59",
"upload_time_iso_8601": "2024-11-19T11:57:59.319933Z",
"url": "https://files.pythonhosted.org/packages/fe/51/2d0000a9f9433f2dec679e304c8cdd99bb858e214cad52723c0c7fbeb7e5/lark-oapi-1.4.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-11-19 11:57:59",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "larksuite",
"github_project": "oapi-sdk-python",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"lcname": "lark-oapi"
}