如何将Microsoft Teams传入Webhook消息转发至指定聊天?
Teams消息转发至指定聊天的实现方案
可行性说明
完全可行,但Teams传入Webhook是单向的(仅支持向Teams发送消息,无法监听接收Teams内的消息),因此需要借助Microsoft Graph API完成转发需求,核心是获取目标聊天的Chat ID,并通过Graph API发送消息。
步骤1:获取目标聊天的Chat ID
两种便捷获取方式:
- Teams客户端提取:打开目标聊天窗口,点击右上角「更多选项」→「获取链接」,链接中的
threadId参数值即为Chat ID(格式类似19:xxxxxx@thread.tacv2)。 - Graph API查询:调用
GET /me/chats(委派权限)或GET /users/{user-id}/chats(应用权限)接口,返回结果中每个聊天对象的id字段就是Chat ID。
步骤2:注册Azure AD应用并配置权限
要使用Graph API发送消息,需先在Azure AD中注册应用:
- 注册应用后,添加Microsoft Graph权限:
- 后台运行场景(无用户交互):添加
ChatMessage.Send应用权限,并完成管理员同意。 - 用户交互场景:添加
ChatMessage.Send委派权限。
- 后台运行场景(无用户交互):添加
- 记录应用的
Client ID、Client Secret(应用权限),或配置授权码流(委派权限),用于获取Graph API访问令牌。
步骤3:C#实现代码示例
场景1:发送原消息时同步转发(适用于你的代码推送消息到Webhook时,同时转发到目标Chat)
using System.Net.Http.Headers; using System.Text; using System.Text.Json; // 配置参数 var teamsWebhookUrl = "你的传入Webhook地址"; var targetChatId = "目标聊天的Chat ID"; var azureAdClientId = "你的Azure AD应用Client ID"; var azureAdClientSecret = "你的Azure AD应用Client Secret"; var tenantId = "你的租户ID"; // 1. 发送消息到原Teams Webhook var messageContent = new { text = $"Application started by {Environment.UserName}" }; using (var httpClient = new HttpClient()) { var webhookContent = new StringContent( JsonSerializer.Serialize(messageContent), Encoding.UTF8, "application/json"); await httpClient.PostAsync(teamsWebhookUrl, webhookContent); } // 2. 获取Graph API访问令牌(应用权限流) using (var tokenClient = new HttpClient()) { var tokenRequest = new FormUrlEncodedContent(new[] { new KeyValuePair<string, string>("grant_type", "client_credentials"), new KeyValuePair<string, string>("client_id", azureAdClientId), new KeyValuePair<string, string>("client_secret", azureAdClientSecret), new KeyValuePair<string, string>("scope", "https://graph.microsoft.com/.default") }); var tokenResponse = await tokenClient.PostAsync( $"https://login.microsoftonline.com/{tenantId}/oauth2/v2.0/token", tokenRequest); var tokenData = JsonSerializer.Deserialize<JsonElement>(await tokenResponse.Content.ReadAsStringAsync()); var accessToken = tokenData.GetProperty("access_token").GetString(); // 3. 转发消息到目标Chat using (var graphClient = new HttpClient()) { graphClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken); var chatMessage = new { body = new { content = messageContent.text } }; var chatContent = new StringContent( JsonSerializer.Serialize(chatMessage), Encoding.UTF8, "application/json"); await graphClient.PostAsync( $"https://graph.microsoft.com/v1.0/chats/{targetChatId}/messages", chatContent); } }
场景2:监听Teams聊天消息自动转发(适用于Teams内收到消息后自动转发到目标Chat)
需使用Graph API订阅功能监听消息创建事件,再触发转发:
- 创建消息订阅:
// 配置参数 var sourceChatId = "需要监听的源聊天ID"; var notificationUrl = "你的公网通知端点(接收Graph事件通知)"; var accessToken = "已获取的Graph API访问令牌"; var subscription = new { changeType = "created", notificationUrl = notificationUrl, resource = $"chats/{sourceChatId}/messages", expirationDateTime = DateTime.UtcNow.AddDays(3), clientState = "随机验证字符串" }; using (var graphClient = new HttpClient()) { graphClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken); var subscriptionContent = new StringContent( JsonSerializer.Serialize(subscription), Encoding.UTF8, "application/json"); await graphClient.PostAsync("https://graph.microsoft.com/v1.0/subscriptions", subscriptionContent); }
- 通知端点处理转发逻辑(以ASP.NET Core为例):
using System.Net.Http.Headers; using System.Text.Json; [HttpPost("teams-message-notification")] public async Task<IActionResult> HandleMessageNotification([FromBody] JsonElement notification) { // 解析通知中的消息ID var resourceData = notification.GetProperty("resourceData"); var messageId = resourceData.GetProperty("id").GetString(); var sourceChatId = "源聊天ID"; var targetChatId = "目标聊天ID"; var accessToken = "Graph API访问令牌"; // 获取完整消息内容 using (var graphClient = new HttpClient()) { graphClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken); var messageResponse = await graphClient.GetAsync( $"https://graph.microsoft.com/v1.0/chats/{sourceChatId}/messages/{messageId}"); var message = JsonSerializer.Deserialize<JsonElement>(await messageResponse.Content.ReadAsStringAsync()); var messageContent = message.GetProperty("body").GetProperty("content").GetString(); // 转发到目标Chat var chatMessage = new { body = new { content = messageContent } }; var chatContent = new StringContent( JsonSerializer.Serialize(chatMessage), Encoding.UTF8, "application/json"); await graphClient.PostAsync( $"https://graph.microsoft.com/v1.0/chats/{targetChatId}/messages", chatContent); } return Ok(); }
内容的提问来源于stack exchange,提问作者A. Drews
相关产品推荐
相关产品推荐

