如何在Teams Bot的onTeamsMembersAddedEvent中读取网站安装按钮传递的configDataId参数
首先得明确一点:默认情况下,onTeamsMembersAddedEvent 触发时,Teams传递给Bot的turnContext里不会直接包含你在安装深度链接里设置的configDataId参数。因为这个事件的核心是通知Bot“有成员加入了团队/安装了个人应用”,它的payload里并没有携带安装时的自定义参数。
不过我们可以通过「中间存储+配置页面」的方式来实现关联,下面是具体的解决方案:
核心思路
当用户通过你的网站深度链接安装Teams应用时,引导用户进入应用的自定义配置页面,在这个页面里捕获configDataId,并将它和当前的团队ID/用户ID绑定存储到你的后端数据库。之后Bot在onTeamsMembersAddedEvent触发时,通过事件里的团队/用户ID去数据库中查询对应的configDataId。
具体步骤
1. 配置Teams应用的自定义配置页面
在你的Teams应用清单(manifest.json)中,为应用添加配置页面的URL。比如:
"configurableTabs": [ { "configurationUrl": "https://your-website.com/teams-config?configDataId={configDataId}", "canUpdateConfiguration": true, "scopes": ["team", "groupChat", "personal"] } ]
注意:构造安装深度链接时,要把configDataId正确拼接到链接中,比如:https://teams.microsoft.com/l/app/你的应用ID?configDataId=id-2,这样Teams会把这个参数传递到配置页面的URL中。
2. 在配置页面中捕获并存储参数
在你的配置页面前端代码中,通过Teams JS SDK获取当前的上下文(团队ID/用户ID),同时从URL参数中提取configDataId,然后把这组关联数据发送到你的后端存储:
// 初始化Teams JS SDK await microsoftTeams.initialize(); // 获取当前Teams上下文(包含团队ID、用户ID、租户ID等) const context = await microsoftTeams.getContext(); // 从URL查询参数中获取configDataId const urlParams = new URLSearchParams(window.location.search); const configDataId = urlParams.get('configDataId'); // 将关联数据发送到后端存储 await fetch('https://your-backend-api.com/save-config', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ entityId: context.teamId || context.userId, // 团队场景用teamId,个人场景用userId tenantId: context.tenantId, configDataId: configDataId }) });
3. 在Bot的onTeamsMembersAddedEvent中查询参数
当Bot触发onTeamsMembersAddedEvent时,从turnContext中提取团队ID或用户ID,然后调用你的后端接口查询对应的configDataId:
// 以C# Bot SDK为例 protected override async Task OnTeamsMembersAddedAsync(IList<ChannelAccount> membersAdded, TeamInfo teamInfo, ITurnContext<IConversationUpdateActivity> turnContext, CancellationToken cancellationToken) { // 获取团队ID(团队场景)或用户ID(个人场景) string targetId = turnContext.Activity.Team?.Id ?? turnContext.Activity.From.Id; string tenantId = turnContext.Activity.Conversation.TenantId; // 调用后端接口查询configDataId var configData = await _yourConfigService.GetConfigByEntityIdAsync(targetId, tenantId); if (configData != null) { string configDataId = configData.ConfigDataId; // 在这里使用configDataId做后续逻辑处理 await turnContext.SendActivityAsync($"获取到的configDataId: {configDataId}", cancellationToken: cancellationToken); } await base.OnTeamsMembersAddedAsync(membersAdded, teamInfo, turnContext, cancellationToken); }
注意事项
- 确保你的配置页面域名已经添加到Teams应用清单的
validDomains数组中,否则会被Teams拦截无法加载。 - 如果是多租户应用,存储时一定要关联
tenantId,避免不同租户下的团队/用户ID冲突。 - 若你的应用是纯个人应用(不需要加入团队),可以直接用
userId作为关联键,流程和团队场景一致。
备注:内容来源于stack exchange,提问作者avneetmalhotra

