You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Teams出站Webhook调用Azure Functions报错排查求助

问题排查与解决方案

1. 未实现Teams Webhook请求签名验证

Teams出站Webhook会为每个请求添加签名,你的Azure Function必须验证该签名以完成信任校验,否则Teams会直接拒绝交互。你已配置密钥,但代码中缺少验证逻辑,这是核心问题之一。

验证步骤:

  • 从请求头中提取Authorization字段(格式为HMAC <signature>)
  • 用配置的Webhook密钥,结合请求体内容重新计算HMAC SHA256签名
  • 对比计算出的签名与请求头中的签名,不一致则返回403

2. 响应格式不符合Teams要求

Teams期望的响应是JSON结构对象,而非纯字符串。你的代码返回纯文本,Teams无法解析,因此抛出错误。正确响应需包含text字段(或attachments),示例结构:

{
  "text": "Hello, xxx. 请求处理成功。"
}

3. 请求体解析逻辑错误

Teams发送的请求体中,@提及的内容不在name字段内,而是存储在text(原始消息文本)或entities(提及对象数组)中。你的代码尝试读取data?.name会得到空值,需调整解析逻辑。


修改后的Azure Function代码示例

#r "Newtonsoft.Json"

using System.Net;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Primitives;
using Newtonsoft.Json;
using System.Security.Cryptography;
using System.Text;

public static async Task<IActionResult> Run(HttpRequest req, ILogger log)
{
    log.LogInformation("C# HTTP trigger function processed a request.");

    // 验证Teams请求签名
    var secret = Environment.GetEnvironmentVariable("TeamsWebhookSecret");
    if (!string.IsNullOrEmpty(secret))
    {
        var authHeader = req.Headers["Authorization"].FirstOrDefault();
        if (string.IsNullOrEmpty(authHeader) || !authHeader.StartsWith("HMAC "))
        {
            return new ForbidResult();
        }

        var incomingSignature = authHeader.Substring(5);
        req.Body.Position = 0;
        var requestBody = await new StreamReader(req.Body).ReadToEndAsync();
        req.Body.Position = 0;

        using (var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(secret)))
        {
            var hash = hmac.ComputeHash(Encoding.UTF8.GetBytes(requestBody));
            var computedSignature = Convert.ToBase64String(hash);
            if (!computedSignature.Equals(incomingSignature))
            {
                return new ForbidResult();
            }
        }
    }

    // 解析Teams请求体
    string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
    dynamic data = JsonConvert.DeserializeObject(requestBody);
    string userName = data?.from?.name ?? "访客";
    string messageText = data?.text ?? string.Empty;

    // 构造符合Teams要求的响应
    string responseText = string.IsNullOrEmpty(messageText)
        ? "请求处理成功,请发送消息获取个性化回复。"
        : $"你好,{userName}!你发送的内容是:{messageText}";

    return new OkObjectResult(new { text = responseText });
}

额外配置检查

  • 确认Azure Function的TeamsWebhookSecret配置项已正确存储Teams出站Webhook的密钥
  • 将Azure Function的访问权限设置为允许匿名访问(Teams无法携带Function Key,匿名访问是适配方案)
  • 查看Azure Function日志流(门户→Function应用→监测→日志流),排查是否有请求体解析失败、验证失败等具体错误信息

内容的提问来源于stack exchange,提问作者Ashok

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 04:15:39