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

ASP.NET MVC生成Lemon Squeezy X-Signature哈希不匹配求助

解决Lemon Squeezy Webhook签名验证哈希不匹配问题

核心问题分析

你的代码存在两个关键错误:

  • 最初使用SHA256.Create()直接拼接payload与密钥,这和PHP的hash_hmac逻辑完全不同(HMAC是用密钥对消息做哈希运算,而非简单拼接后哈希)
  • 换成HMACSHA256.Create()后,仍未正确传入密钥,且可能受请求流读取方式影响导致计算偏差

修正后的C#代码

[HttpPost]
public ActionResult lsHook()
{
    string signingSecret = "你的Lemon Squeezy签名密钥";
    string receivedSignature = Request.Headers["X-Signature"];
    
    if (string.IsNullOrEmpty(receivedSignature))
    {
        return new HttpStatusCodeResult(HttpStatusCode.BadRequest, "缺少签名头");
    }

    // 重置请求流指针,确保读取原始请求体(避免模型绑定已读取流导致内容异常)
    Request.InputStream.Seek(0, SeekOrigin.Begin);
    using (var streamReader = new StreamReader(Request.InputStream, Encoding.UTF8))
    {
        string payload = streamReader.ReadToEnd();
        
        // 正确计算HMAC-SHA256哈希
        using (var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(signingSecret)))
        {
            byte[] hashBytes = hmac.ComputeHash(Encoding.UTF8.GetBytes(payload));
            string computedHash = BitConverter.ToString(hashBytes).Replace("-", "").ToLowerInvariant();
            
            if (!computedHash.Equals(receivedSignature.ToLowerInvariant()))
            {
                return new HttpStatusCodeResult(HttpStatusCode.Unauthorized, "签名验证失败");
            }
            
            // 验证通过,手动反序列化处理业务逻辑
            var webhookData = JsonConvert.DeserializeObject<LemonsqueezyWebhook>(payload);
            // ... 你的业务代码
            return new HttpStatusCodeResult(HttpStatusCode.OK);
        }
    }
}

关键注意事项

  • 避免模型绑定干扰:如果原方法参数包含LemonsqueezyWebhook lemonsqueezyWebhook,ASP.NET MVC会自动读取请求流进行反序列化,导致后续Seek(0)读取的内容不完整或为空。建议去掉模型绑定参数,手动反序列化payload;或者配置Request.BufferInput = true确保流可重复读取。
  • 编码一致性:全程使用Encoding.UTF8处理字节转换,和PHP的file_get_contents默认编码保持一致,不要使用Encoding.Default。
  • HMAC正确用法:HMACSHA256构造函数需传入签名密钥,再调用ComputeHash传入payload字节数组,这才和PHP的hash_hmac('sha256', $payload, $secret)逻辑完全匹配。
  • 大小写统一:将计算出的哈希与接收的签名统一转为小写(或大写)后再对比,避免大小写差异导致的不匹配。

额外排查步骤

  1. 确认签名密钥和Lemon Squeezy后台设置完全一致,无空格、换行或特殊字符错误。
  2. 打印payload和receivedSignature的原始值,与Lemon Squeezy测试工具中的payload对比,确保未被ASP.NET自动修改(如添加转义字符、改变JSON格式)。
  3. 用PHP代码和C#代码分别计算相同payload与密钥的哈希,对比结果是否一致,定位问题出在计算逻辑还是请求读取环节。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 02:33:23