ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

飞书与腾讯会议API对接实践:一句话建会与会议纪要自动化

飞书与腾讯会议API对接实践:一句话建会与会议纪要自动化 我先讲一个每天都会发生的真实场景公司内部用飞书做消息协作对外沟通却要用腾讯会议。每次约外部的人开会都得先在飞书群里确认时间然后手动打开腾讯会议客户端创建会议把会议号、入会链接、密码复制回群聊。会开完了还要找录制回放、统计谁参加、整理成表格。这些事情单拎出来都不难可如果一周有几十场会议组织者至少要多花几个小时在复制粘贴和整理信息上。我这次做的“飞书 - 腾讯会议对接实践”就是把这套流程压到最低在飞书群里给机器人发一句“帮我约明天下午3点的一小时需求评审”后端自动完成鉴权、建会、回传会议卡片会后再把回放链接和参会明细汇总成飞书表格。整套方案跑起来之后组织一场会议从原来两三分钟变成十几秒。这篇我会把方案思路、两边的配置细节、核心代码、常见坑都讲清楚给正在做飞书和腾讯会议集成的朋友一条能直接抄作业的路径。1. 项目概述与需求拆解1.1 双协作平台并存带来的实际问题先说说我在实际环境里观察到的痛点。企业内部用飞书做日常沟通是因为飞书在群聊、文档、审批、知识库这些场景确实顺手。但对外协作往往绕不开腾讯会议尤其很多客户、供应商、外包团队都已经习惯用腾讯会议开会。于是大多数团队会处于一种“飞书管日常、腾讯会议管开会”的分裂状态。这种分裂状态最直接的影响是信息断层。会议号散落在各个聊天记录里临时找人开会先要去翻历史消息会议室预订在飞书日历里但会议号要到腾讯会议客户端创建部分同事还不爱开客户端经常找不到入会入口。时间一长组织会议的同事积累了大量的搬运工作而参会人员的体验也不稳定经常出现“群里发了个链接但点进去是错误会议号”的情况。另一个容易被忽略的问题是数据无法沉淀。会议结束后谁来了、谁没来、会议录音录制备份在哪、有没有待办结论这些信息散落在参会人的个人笔记里。管理者想了解一个项目的会议频率、参与率、关键资料的归档情况几乎只能靠人工打听。对于稍微大一点的团队这已经不只是效率问题而是管理盲区。我这次做对接本质上不是单纯追求“自动化建会”而是想把会议这个高频动作变成一个能从“发起、通知、执行、回顾”全链路留痕的闭环。飞书承担统一入口和文档沉淀腾讯会议承担音视频能力中间由后端把两边缝起来。1.2 对接后要达到的核心目标我在项目启动前整理了一份功能清单目标是让会议组织者不再需要在飞书和腾讯会议之间来回切换一句话建会在飞书群里AT机器人用自然语言描述会议主题、时间、时长机器人自动创建腾讯会议。卡片通知回传会议创建成功后会议主题、时间、会议号、入会链接、会议密码以消息卡片形式推回飞书群。会后数据归档会议结束后通过腾讯会议接口查询录制文件、参会成员列表汇总写入飞书云文档表格。可扩展的入口后续可以加“日程同步”“周期性会议”“自动提醒”等能力而不需要推翻主流程。这些目标看起来不复杂但真正做起来两边的鉴权方式、权限点、事件回调机制、字段格式都各有各的坑。如果不提前把方案想清楚很容易在联调阶段反复返工。1.3 这套方案适合谁参考如果你属于下面几种情况这篇内容对你会有直接帮助后端开发或效率工程师接到“把飞书和腾讯会议打通”这类需求需要快速了解整体方案和落地细节。团队负责人或IT管理员想评估这套对接能解决什么问题、需要申请哪些平台权限、数据流程是否安全可控。同时使用飞书和腾讯会议的企业用户希望通过低代码或自建服务降低会议组织成本。另外我采用的“消息事件订阅 开放API 数据回写”的思路并不局限于飞书和腾讯会议。飞书和其他视频会议系统对接或者换成企业微信、自有会议系统整体框架也基本一致核心是先把消息入口和业务系统之间的边界想清楚。2. 技术方案选型与整体架构2.1 对比三种落地方案为什么选开放API在决定技术路线之前我认真比较过三种方案。第一种是客户端级自动化。在本地启动一个程序模拟鼠标键盘操作腾讯会议桌面客户端点击“快速会议”、复制会议号、再回到飞书粘贴。这种方案听起来很“直接”但实际上非常脆弱腾讯会议客户端一升级UI元素的位置和控件名都可能变化脚本就会挂掉而且模拟键鼠在后台不稳定电脑一锁屏、弹窗一遮挡流程就断了。我完全不建议在生产环境用这种方案它只适合个人电脑上的一次性实验。第二种是定时轮询。每隔一段时间去腾讯会议接口拉取会议室列表看哪些会议快开始了再通知飞书群。这种方案能解决一部分提醒需求但“临时发起的会议”无法被主动感知做不到“创建会议后立刻回传链接”的实时体验还会平白增加接口调用量容易触发平台的频控限制。第三种就是我用官方开放平台能力来做。飞书开放平台提供事件订阅、机器人、云文档API腾讯会议开放平台提供创建会议、查询会议、获取录制等API。两边都是标准的HTTP接口和JSON数据后端服务可以把它们编排成一条完整链路。虽然前期需要申请应用、配权限、联调鉴权但一旦跑通稳定性好数据可审计后续扩展也方便。这也是目前企业自建集成的常见做法。三种方案对比如下方案实时性稳定性开发成本适用场景客户端模拟操作低低易受版本影响低但维护成本高个人临时场景不推荐定时轮询接口中中依赖频率设置中只做提醒不需要实时建会官方开放API 事件订阅高高前期略高后期稳定企业内正式使用推荐2.2 整体联动流程设计最终我采用的流程是这样的用户在飞书群里AT机器人发送“创建会议 主题需求评审 时间明天15:00 时长60分钟”这类消息。飞书平台把这条消息通过事件订阅推送到我们后端服务配置的回调地址。后端先校验事件消息的合法性再解析出会议主题、开始时间、时长等参数。后端拿飞书应用的App ID和App Secret换取租户访问令牌同时拿腾讯会议应用的凭证换取腾讯会议访问令牌。后端调用腾讯会议“创建会议”接口拿到会议号、入会链接、会议密码等数据。后端调用飞书消息接口把会议信息以消息卡片形式发送回原群聊。会议结束后可以由定时任务或回调触发调用腾讯会议查询接口获取录制文件和参会信息再写入飞书表格。这套流程的关键点在于飞书侧和腾讯会议侧之间的状态管理全部由我们的后端服务来承担。两边的API不应该互相直接调用而是通过后端统一调度。这样设计一方面方便在中间做参数转换、日志记录、错误重试另一方面也是为了安全避免把腾讯会议的密钥暴露在飞书机器人配置里。2.3 两边开放平台的关键能力梳理我画过一张很简单的能力对照表整理飞书和腾讯会议两边各自要用的能力能力维度飞书开放平台腾讯会议开放平台应用类型企业自建应用企业自建应用主要鉴权方式tenant_access_token / user_access_tokenOAuth2 access_token新版本较多核心接口发送消息、读取用户、云文档表格读写、事件订阅创建会议、查询会议、获取参会成员、获取录制文件权限控制权限点 管理员审核应用权限 企业管理员审核消息交互机器人、消息卡片回调、API返回从这张表能看出两边都提供了比较完整的开放体系但权限模型差异很大。飞书把权限拆得很细比如“发送消息”“上传文件”“读写表格”是不同的权限点腾讯会议则更偏重“应用级”的整体授权。实际联调时最容易出的问题就是两边权限都对不上你以为某个接口能调用结果报403这时候第一步永远是去控制台确认当前账户是否有对应权限而不是急着改代码。3. 实操落地把一条“建会指令”跑通3.1 飞书侧配置自建应用、机器人、事件订阅飞书侧的准备工作不算难但步骤比较多每一步都有对应的坑。第一步进入飞书开放平台选择“企业自建应用”创建一个应用。创建成功之后先记下两个关键信息App ID和App Secret。App Secret相当于应用密码一定要保存在后端服务的环境变量或密钥管理服务里不要写进前端代码或飞书机器人配置里。第二步在“应用能力”中启用机器人能力。启用后飞书会给应用分配一个机器人你可以把机器人加到需要的群聊里。这里有个细节机器人加群之后默认只能收到被AT时的消息事件如果你希望机器人监听群里的关键词需要额外配置事件订阅。第三步配置权限点。我这边主要开通了这些权限发送消息、上传文件、读写云文档表格、读取用户基本信息、读取群组信息。权限点开通后一定要记得在“版本管理与发布”里创建一个新版本并提交审核审核通过后权限才真正生效。这一步很多人会漏掉结果代码写完调接口一直提示无权限还以为是token的问题。第四步配置事件订阅。在飞书开放平台的应用“事件订阅”页面把“请求地址”填为我们后端服务可被外网访问的回调地址然后订阅im.message.receive_v1消息事件。配置保存时飞书会向这个地址发送一条验证请求如果你的后端没有正确处理页面会直接报错。验证请求的处理逻辑是这样的飞书会POST一个JSON过来里面包含challenge字段你的接口只要原样返回这个字段即可。如果在应用配置里开启了“加密模式”那么推送的内容是加密过的需要先用应用配置的Encrypt Key解密拿到明文之后再把challenge返回给飞书。我没用官方SDK而是自己按照文档实现了解密。实际上更省事的做法是直接用飞书官方SDK里面的回调处理模块已经封装好了验证和解密逻辑建议优先使用官方SDK避免自己实现时遗漏细节。3.2 腾讯会议侧配置企业自建应用与密钥腾讯会议开放平台的配置相对集中但鉴权方式在版本演进中变化较大需要特别留意。登录腾讯会议开放平台后通过“企业自建应用”入口创建应用。创建完成后控制台会给出client_id和client_secret这两个是我们的核心凭证。部分旧版本还会使用类似SecretID、SecretKey的命名并且要求通过JWT签名去生成token。如果你用的是新版控制台大概率是OAuth2的client_credentials流程也就是用client_id和client_secret直接换access_token。具体以你申请到的文档为准但核心思想是一致的拿应用身份凭证换临时访问令牌。配置完应用之后需要在控制台开通接口权限。我这里开通了创建会议、查询会议、获取参会成员列表、获取录制文件这几个接口。腾讯会议的权限审核一般是企业管理员审批审批通过之后接口才能正常调用。另外有一个容易被忽略的点部分腾讯会议接口会校验调用方的IP白名单。部署后端的服务器IP最好提前加到应用配置里否则本地调试没问题一部署到线上就报来源不可信的错误。3.3 后端核心流程实现后端我用的是Python框架是FastAPI。整体逻辑可以拆成四个部分飞书token获取、腾讯会议token获取、创建会议、回传飞书消息。先看飞书token的获取。飞书的tenant_access_token相当于“应用身份”的服务端令牌大多数服务端API都要用到。它有效期一般是2小时需要在后端做缓存避免每次请求都重新申请。import requests import time import json FEISHU_APP_ID cli_xxx FEISHU_APP_SECRET your_app_secret feishu_token_cache {token: None, expire_at: 0} def get_feishu_tenant_token(): if feishu_token_cache[token] and feishu_token_cache[expire_at] time.time() 60: return feishu_token_cache[token] resp requests.post( https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal, json{app_id: FEISHU_APP_ID, app_secret: FEISHU_APP_SECRET}, timeout10, ) data resp.json() if data.get(code) ! 0: raise Exception(fget feishu token failed: {data}) feishu_token_cache[token] data[tenant_access_token] feishu_token_cache[expire_at] time.time() data[expire] return feishu_token_cache[token]腾讯会议侧的token获取新版一般是OAuth2的client_credentials模式。我这边用了一个简单的缓存避免每次建会都重复获取。MEETING_CLIENT_ID your_client_id MEETING_CLIENT_SECRET your_client_secret meeting_token_cache {token: None, expire_at: 0} def get_tencent_meeting_token(): if meeting_token_cache[token] and meeting_token_cache[expire_at] time.time() 60: return meeting_token_cache[token] resp requests.post( https://api.meeting.qq.com/v2/oauth2/access_token, json{ client_id: MEETING_CLIENT_ID, client_secret: MEETING_CLIENT_SECRET, grant_type: client_credentials, }, timeout10, ) data resp.json() access_token data.get(access_token) expires_in data.get(expires_in, 7200) meeting_token_cache[token] access_token meeting_token_cache[expire_at] time.time() expires_in return access_token拿到腾讯会议token之后就能调用创建会议接口了。创建会议时时间参数是一个重点我在后面的常见问题里会详细说。这里先给核心代码def create_meeting(subject, start_timestamp, duration_minutes, host_userid): token get_tencent_meeting_token() end_timestamp start_timestamp duration_minutes * 60 headers { Authorization: fBearer {token}, X-TC-Key: MEETING_CLIENT_ID, Content-Type: application/json, } body { subject: subject, start_time: str(start_timestamp), end_time: str(end_timestamp), hosts: [{userid: host_userid}], settings: { enable_record: True, mute_enable: False, allow_enter_early: 5, }, } resp requests.post( https://api.meeting.qq.com/v1/meetings, headersheaders, jsonbody, timeout15, ) if resp.status_code ! 200: raise Exception(fcreate meeting failed: {resp.text}) data resp.json() meeting_info data[meeting_info_list][0] return { meeting_id: meeting_info[meeting_id], join_url: meeting_info[join_url], meeting_code: meeting_info.get(meeting_code, ), subject: subject, }会议创建成功之后下一步就是回传飞书消息。这里我用的是消息卡片用户在群里看到的不是干巴巴的文本而是一张带按钮的卡片可以直接点“加入会议”打开链接体验比纯文本好很多。def send_meeting_card(chat_id, meeting, start_time_str): feishu_token get_feishu_tenant_token() card_content { config: {wide_screen_mode: True}, header: { title: {tag: plain_text, content: f会议已创建{meeting[subject]}}, template: green, }, elements: [ { tag: div, text: { tag: lark_md, content: f**开始时间**{start_time_str}\n**会议号**{meeting[meeting_code]}\n**会议ID**{meeting[meeting_id]}, }, }, { tag: action, actions: [ { tag: button, text: {tag: plain_text, content: 加入会议}, url: meeting[join_url], type: primary, } ], }, ], } resp requests.post( https://open.feishu.cn/open-apis/im/v1/messages, params{receive_id_type: chat_id}, headers{ Authorization: fBearer {feishu_token}, Content-Type: application/json, }, json{ receive_id: chat_id, msg_type: interactive, content: json.dumps(card_content, ensure_asciiFalse), }, timeout10, ) if resp.status_code ! 200: raise Exception(fsend feishu message failed: {resp.text})这一段代码跑通之后最基本的建会闭环就完成了。我建议你第一次联调时不要把功能做得多复杂先让机器人能解析一条固定格式的指令成功建会并发卡片后面再慢慢扩展自然语言解析、周期会议、自动归档这些能力。3.4 让机器人把会议纪要和录制写进飞书表格建会、发卡片是主链路但真正做到“会议资产沉淀”还需要把会后的数据写进飞书云文档表格。飞书云文档表格的写入流程大致是先用API创建一个电子表格得到spreadsheet_token和默认sheet的sheet_id然后调用“插入数据行”接口把会议主题、时间、会议号、录制链接、参会人数这些字段逐行写入。这里要注意一个权限问题如果你的后端只想用应用身份自动汇总数据建议创建一个专门用于存放会议记录的表格写入时使用tenant_access_token作为鉴权。如果你希望用某个用户自己的身份去写私人表格就必须走user_access_token的OAuth2授权流程首次使用还需要用户手动点击授权链接。我最初做的时候想直接往用户的私人表格里写数据结果一直报权限错误。后来改成“先让用户把表格共享给飞书应用或者直接让应用创建一个新的汇总表格”问题就解决了。对于团队内部场景我更推荐应用自建表格的方式省去授权流程数据也统一。这里还有一个实用技巧写入表格时尽量用批量写入接口一次写入多行而不是for循环里逐行插入。飞书表格接口对请求频率有控制逐行插入很容易触发限流。批量插入在数据量大的时候性能差距非常明显。我简单给一个创建表格并插入首行数据行的示意代码具体接口字段以飞书最新文档为准def create_sheet_and_insert(title, records): feishu_token get_feishu_tenant_token() headers {Authorization: fBearer {feishu_token}} # 创建电子表格 resp requests.post( https://open.feishu.cn/open-apis/sheets/v3/spreadsheets, headersheaders, json{title: title}, timeout10, ) sheet_token resp.json()[data][spreadsheet][spreadsheet_token] sheet_id resp.json()[data][spreadsheet][sheets][0][sheet_id] # 插入数据行 rows [ [会议主题, 开始时间, 会议号, 录制链接, 参会人数], ] for r in records: rows.append([ r[subject], r[start_time], r[meeting_code], r[record_url], r[attendee_count] ]) insert_resp requests.post( fhttps://open.feishu.cn/open-apis/sheets/v2/spreadsheets/{sheet_token}/sheets/{sheet_id}/insertDataRows, headersheaders, json{values: rows}, timeout15, ) if insert_resp.status_code ! 200: raise Exception(finsert rows failed: {insert_resp.text}) return sheet_token有了这张表格之后机器人还可以在会议结束后把表格链接推送到群里让所有人都能看到归档结果。这样就完成了从建会到归档的闭环。4. 常见问题与排查实录4.1 首次对接飞书云文档授权凭证怎么拿很多朋友第一次接触飞书云文档API时都会被授权凭证搞晕。我给一个比较直白的区分tenant_access_token应用身份令牌代表的是“这个应用”在平台上执行操作。适合后端服务做批量写入、读取已授权的资源。user_access_token用户身份令牌代表某个真实用户授权应用代为操作。适合操作该用户私有的文档、日程等资源。初次对接时如果只是想把会议数据汇总到一个统一表格优先走tenant_access_token申请表格读写权限即可。不需要额外弹出授权页面。你要是在网上看到别人项目里出现“授权凭证”多半指的是user_access_token的换取链接那是给有私有文档操作需求的场景用的。我踩过的坑是拿到tenant_access_token之后去读取一个用户私人创建的表格结果返回“无权限”。这不是token问题而是表格归属权问题。解决办法很简单让表格所有者把表格权限改为“组织内可编辑”或者干脆把表格复制到应用可管理的空间里。4.2 飞书事件订阅验证失败或一直收不到消息回调这个问题的排查思路比较固定。第一步确认回调地址是否真的能被公网访问最简单的方式是直接在浏览器里访问一下如果不能打开就先解决网络暴露问题。第二步看飞书控制台的“事件订阅”调试功能手动模拟推送一条消息看后端是否能收到。第三步检查后端返回的结果验证模式下必须返回纯JSON字符串并且包含challenge不能有多余的HTML或换行。我遇到过一个很隐蔽的问题为了避免重复代码我在回调入口统一做了签名校验但在验证URL时飞书还没有配置App Secret的签名上下文导致验证请求被拒。后来我把“验证URL”和“正式事件”分开处理验证URL只校验challenge正式事件再走完整签名校验问题就解决了。4.3 时间格式和时区问题时间问题是建会接口最让我头疼的一环。腾讯会议创建会议接口在历史版本中用的是Unix秒有些版本支持毫秒而且不同文档里字段名也可能不一样。最安全的方式是在后端把它统一转成整型秒数再转成字符串传入。还有一个经典的时区坑用户说“明天上午10点”如果你在服务器上直接取datetime.now()加上一天很可能算出的是UTC时间结果会议的本地时间差了8个小时。我这边统一用“Asia/Shanghai”时区来做时间解析所有输入都先转成带时区的datetime对象再转成时间戳。这样不管服务器部署在哪个区域结果都能保持一致。会议时长也建议在后端计算好。不要只传开始时间然后让会议默认开一小时如果传了end_time就必须保证end_time start_time。给用户配置了默认时长之后我一般会在创建前做一次参数校验避免脏数据传入API。4.4 腾讯会议客户端摄像头和设备问题有一个搜索热词是“腾讯会议不能使用电脑自带摄像头吗”这个跟API对接本身没有关系但是实践中确实会收到用户反馈。会议创建成功了用户点链接入会结果发现画面黑屏或者提示找不到摄像头第一反应往往是“是不是机器人建会有问题”。实际上这是客户端设备权限问题。腾讯会议桌面版调用摄像头需要操作系统授予相机权限尤其是macOS和Windows都有隐私设置。我在会议卡片的“加入会议”按钮下面加了一行小字提示“如无法开启摄像头请检查系统‘隐私-相机’或‘隐私-麦克风’权限。”加上这个提示后类似的求助明显少了。这也说明对接工作不只是把接口调通还包含用户侧体验设计。一个小提示能省去大量客服解释工作。4.5 接口频控限流和幂等重试两边接口都有频控限制。飞书侧对发送消息接口的频控比较严格腾讯会议侧对创建会议、查询会议接口同样有限流。我在联调阶段就碰到过往多个群同时发卡片结果部分消息发送失败返回429。解决办法有两个一是做token缓存减少鉴权接口的调用量二是在发送消息和创建会议的外层加一个带指数退避的重试逻辑。第一次失败等1秒第二次等2秒第三次等4秒最多重试三次。还要注意幂等问题。网络抖动时创建会议接口请求超时了但腾讯会议后台可能已经创建成功。如果此时直接重试就会建出两个会议。我这边在创建会议请求里加了一个meeting_id或instanceid之类的业务幂等标识或者在后端记录“上一次创建结果”超时就先按meeting_id查询一下再决定是否重试。这个细节在会议量大的时候非常重要否则会出现同一时间有两个相似会议号的尴尬情况。4.6 问题排查速查表我整理了一张排错速查表方便遇到问题时先对照一遍现象常见原因处理建议飞书接口返回401App Secret错误或token过期检查环境变量刷新token缓存飞书接口返回403权限点未开通或应用未重新发布到开放平台核对权限重新发布版本腾讯会议接口返回401/403client_secret错误或IP白名单不匹配核对密钥添加服务器IP到白名单创建会议报参数错误时间格式、时区、body字段不对打印请求体对照官方文档逐项核对事件订阅验证失败返回内容不是纯JSON或未处理challenge先关闭加密返回challenge再逐步加签名校验消息卡片发送成功但按钮打不开入会链接是腾讯会议客户端协议链接确认链接类型必要时拼接Web入会地址写表格无权限token身份与表格归属不一致使用tenant_access_token并共享表格给应用这张表覆盖了我实际开发中遇到的大部分问题遇到报错先按表格排查能节省不少时间。5. 一点实操感悟这套“飞书 - 腾讯会议对接”做下来我最深的体会是集成类项目的难点通常不在某一个单点技术上而在把多个系统的边界和约定对齐。飞书有飞书的权限模型腾讯会议有腾讯会议的鉴权版本任何一个字段理解偏差都可能让整条链路卡住。所以不要一开始就追求把所有功能做完先把“一句话建会卡片回传”这条最小链路跑通再逐步加入录制查询、表格归档、提醒通知等等。另外密钥和token的管理一定要认真对待。App Secret、client_secret这些东西不要直接写死在代码里也不要提交到Git仓库。我习惯用环境变量或者专门的密钥管理服务并且给密钥设置定期轮换。权限方面尽量开最小够用权限宁可后续再补也不要一上来把所有接口权限全部打开。最后再说一个小技巧联调阶段可以用飞书开放平台自带的API调试器和腾讯会议开放平台的调试工具先把接口跑通确认两边的请求参数和响应结构再写后端代码。这样可以减少大量试错。两边平台文档更新频率不低写作时我提到的部分字段可能已经升级实际开发时以你申请到的应用版本和最新文档为准。这套方案的框架不会变剩下的就是耐心把细节磨平。
返回列表