Python SDK 提供了 register_app(同步)和 aregister_app(异步)方法,基于 OAuth 2.0 Device Authorization Grant(RFC 8628)协议实现一键创建应用。

调用该方法会返回一个验证链接,用户在飞书或 Lark 中打开该链接(或扫码)完成授权后,即可自动注册应用并获取凭据(App ID 和 App Secret),无需手动前往开发者后台创建。

查看源码:oapi-sdk-python

前提条件

  • Python 版本 >= 3.8

  • 安装或升级 lark-oapi 至 1.5.5 及以上版本:

  pip install lark-oapi

快速开始示例

同步版

import lark_oapi as lark
def handle_qr(info):
    print(f"请扫码: {info['url']}")
    print(f"有效期 {info['expire_in']} 秒")
def handle_status(info):
    print(f"状态: {info['status']}", info.get("interval", ""))
try:
    result = lark.register_app(
        on_qr_code=handle_qr,
        on_status_change=handle_status,
    )
    print(f"App ID: {result['client_id']}")
    print(f"App Secret: {result['client_secret']}")
    print(f"User Info: {result.get('user_info')}")
except Exception as e:
    print(f"失败: {e}")

异步版

import asyncio
import lark_oapi as lark
async def main():
    result = await lark.aregister_app(
        on_qr_code=lambda info: print(f"请扫码: {info['url']}"),
    )
    print(f"App ID: {result['client_id']}")
    print(f"App Secret: {result['client_secret']}")
asyncio.run(main())

自定义权限/事件/回调与更新已有应用

创建应用时,可通过 addons 在平台基础模板上增量申请权限、事件订阅和回调。这些配置会预填到用户扫码后的确认页中,用户确认后生效:

result = lark.register_app(
    on_qr_code=on_qr_code,
    addons={
        "scopes": {
            "tenant": ["im:message:send_as_bot"],
            "user": ["calendar:calendar:read"],
        },
        "events": {"items": {"tenant": ["im.message.receive_v1"]}},
        "callbacks": {"items": ["card.action.trigger"]},
    },
    create_only=True,
)

lark.register_app(
    on_qr_code=on_qr_code,
    app_id="cli_xxx",
    addons={"scopes": {"tenant": ["drive:drive.metadata:readonly"]}},
)
  • addons 仅支持在基础模板上增量叠加,不支持删减基础权限。
  • addons.preset 控制底座模板:缺省或 True 使用默认底座模板;False 切换为最小基础模板,最终配置只包含 addons 显式声明的内容。传 "preset": False 时,addons 可以不带任何增量条目。
  • 仅支持 5 类公开配置:应用/用户身份权限、应用/用户身份事件、回调。敏感配置(事件请求地址、security.*、加密 key 等)不能通过 addons 传入。
  • SDK 只校验数据形状,不校验权限点/事件/回调名称是否存在;平台目录中不存在的名称会被确认页忽略。

如需不使用 mock、真实跑一遍手动 E2E:

python3 samples/registration/app_preset_live_e2e.py --open

API 描述

函数签名

函数 签名 说明
register_app (on_qr_code, on_status_change=None, source=None, cancel_event=None, domain=..., lark_domain=...) -> dict 同步版,阻塞当前线程直到完成
aregister_app async (on_qr_code, on_status_change=None, source=None, domain=..., lark_domain=...) -> dict 异步版,返回 coroutine

register_app 参数

参数 描述 类型 必填 默认值
on_qr_code 验证链接就绪时的回调,参数为 {"url": str, "expire_in": int} function 是 -
on_status_change 轮询状态变化回调,状态包括 polling、slow_down、domain_switched function 否 -
source 来源标识,会拼入二维码 URL 的 source 参数,格式为 python-sdk/{source} string 否 python-sdk
cancel_event 用于取消同步轮询的 threading.Event threading.Event 否 -
domain 自定义飞书账号域名 base URL string 否 https://accounts.feishu.cn
lark_domain 自定义 Lark 账号域名 base URL,检测到 Lark 租户时使用 string 否 https://accounts.larksuite.com
app_preset 创建页预填信息。所有字段都是选填,用户扫码后仍可在页面手动修改。调用方传原始值,SDK 自动 URL Encode dict 否 -
app_preset.avatar 应用头像 URL,支持 1-6 个;传多个时默认选中第一个。图片格式由 Web 页面处理:png / jpg / jpeg / webp / gif string 或 list[string] 否 -
app_preset.name 应用名称,支持 {user} 占位符,由 Web 页面替换为扫码用户名称 string 否 -
app_preset.desc 应用描述,支持 {user} 占位符 string 否 -
addons 增量权限/事件/回调配置,预填到扫码后的确认页,用户确认后生效 dict 否 -
addons.preset 底座模板开关。缺省或 True 使用默认底座模板;False 切换为最小基础模板,应用配置完全由 addons 显式声明 bool 否 True
addons.scopes.tenant 应用身份权限列表,如 im:message:send_as_bot list[string] 否 -
addons.scopes.user 用户身份权限列表,如 calendar:calendar:read list[string] 否 -
addons.events.items.tenant 应用身份事件列表,如 im.message.receive_v1 list[string] 否 -
addons.events.items.user 用户身份事件列表,如 calendar.calendar.event.changed_v4 list[string] 否 -
addons.callbacks.items 回调列表,如 card.action.trigger list[string] 否 -
create_only 为 True 时落地页仅允许创建新应用,隐藏「选择已有应用」入口。与 app_id 同时传入时优先级更高 bool 否 -
app_id 已有应用的 App ID(cli_ 开头)。传入后流程变为更新该应用配置;二维码 URL 上使用平台参数 clientID string 否 -

on_qr_code 回调参数

字段 类型 说明
url str 完整的二维码 URL(已拼好 from、tp、source 参数)
expire_in int 二维码有效期(秒)

on_status_change 回调参数

字段 类型 说明
status str 状态:polling / slow_down / domain_switched
interval int(可选) 当前轮询间隔(秒),slow_down 时有值

返回值

返回一个 dict,包含: | 字段 | 类型 | 说明 | | --------------- | ---------- | ---------------------------------------------------- | | client_id | str | App ID | | client_secret | str | App Secret | | user_info | dict(可选) | 扫码用户信息,含 open_id、tenant_brand(feishu 或 lark) |

异常类型

异常 触发条件
AppAccessDeniedError 用户主动拒绝授权
AppExpiredError 二维码过期或轮询超时
RegisterAppError 其他错误(携带 code、description 属性)
* * *

进阶用法

同步版:取消轮询

import threading
import lark_oapi as lark
cancel_event = threading.Event()

# 另一个线程里可以随时取消

# cancel_event.set()

result = lark.register_app(
    on_qr_code=handle_qr,
    cancel_event=cancel_event,
)

异步版:取消任务

import asyncio
import lark_oapi as lark
async def main():
    task = asyncio.create_task(lark.aregister_app(on_qr_code=handle_qr))
    # 某个时刻取消

task.cancel()
    try:
        result = await task
    except asyncio.CancelledError:
        print("已取消")
asyncio.run(main())

拿到凭据后初始化 Client

result = lark.register_app(on_qr_code=handle_qr)
client = lark.Client.builder() \
    .app_id(result['client_id']) \
    .app_secret(result['client_secret']) \
    .build()