首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Sstripeweb钩子签名失败- Stripe.net

Sstripeweb钩子签名失败- Stripe.net
EN

Stack Overflow用户
提问于 2017-05-10 09:32:55
回答 3查看 5.4K关注 0票数 6

我试图使用Jayme的c#库Stripe.net实现一个条形网络钩子。我已经在条形仪表板中设置了测试端点,并生成了这个秘密。端点正被很好地击中,并将使用StripeEvent生成StripeEventUtility.ParseEvent。问题是使用ConstructEvent函数时,我无法获得匹配的签名。如有任何帮助或建议,将不胜感激。

isSignaturePresent返回false

代码语言:javascript
复制
//call to create event
stripeEvent = ConstructEvent(json, Request.Headers["Stripe-Signature"], 
SecretFromStripeDashBoard);


private StripeEvent ConstructEvent(string json, string 
stripeSignatureHeader, string secret, int tolerance = 300)
    {
        var signatureItems = parseStripeSignature(stripeSignatureHeader);

        var signature = computeSignature(secret, signatureItems["t"].FirstOrDefault(), json);

        if (!isSignaturePresent(signature, signatureItems["v1"]))
            throw new Exception("The signature for the webhook is not present in the Stripe-Signature header.");

        //var utcNow = EpochUtcNowOverride ?? DateTime.UtcNow.ConvertDateTimeToEpoch();
        //var webhookUtc = Convert.ToInt32(signatureItems["t"].FirstOrDefault());

        //if (utcNow - webhookUtc > tolerance)
        //    throw new Exception("The webhook cannot be processed because the current timestamp is above the allowed tolerance.");

        return Mapper<StripeEvent>.MapFromJson(json);
    }

    private ILookup<string, string> parseStripeSignature(string stripeSignatureHeader)
    {
        return stripeSignatureHeader.Trim()
            .Split(',')
            .Select(item => item.Trim().Split('='))
            .ToLookup(item => item[0], item => item[1]);
    }

    private bool isSignaturePresent(string signature, IEnumerable<string> signatures)
    {
        return signatures.Any(key => secureCompare(key, signature));
    }

    private string computeSignature(string secret, string timestamp, string payload)
    {
        var secretBytes = Encoding.UTF8.GetBytes(secret);
        var payloadBytes = Encoding.UTF8.GetBytes($"{timestamp}.{payload}");

        var cryptographer = new HMACSHA256(secretBytes);
        var hash = cryptographer.ComputeHash(payloadBytes);

        return BitConverter.ToString(hash).Replace("-", "").ToLower();
    }

    private bool secureCompare(string a, string b)
    {
        if (a.Length != b.Length) return false;

        var result = 0;

        for (var i = 0; i < a.Length; i++)
        {
            result |= a[i] ^ b[i];
        }

        return result == 0;
    }
}
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2017-05-10 13:42:27

我在上面的注释中回答了这个问题,但是简单地说,问题是提供给ConstructEvent方法的ConstructEvent字符串没有包含由Stripe发送的确切的有效负载。

相反,您可以使用以下方法初始化有效负载:

代码语言:javascript
复制
var json = JsonSerializer.SerializeToString(request);

也就是说,您重新序列化了反序列化请求的主体。但是,您不太可能得到与Stripe发送的原始有效负载相同的字符串。例如,条纹可以发送这个有效载荷:

代码语言:javascript
复制
{
  "a_key": "a_value",
  "another_key": "another_value"
}

但是在deserializing+reserializing之后,JSON字符串可能包含以下值:

代码语言:javascript
复制
{"another_key": "another_value","a_key": "a_value"}

由于键顺序不一定会被维护,其他格式选项(换行符、缩进)也将发挥作用。

Web钩子签名是使用确切的有效载荷(作为原始字符串)生成的,因此在验证签名时,还必须提供web服务器或框架传递的确切有效载荷。

票数 7
EN

Stack Overflow用户

发布于 2020-10-26 11:49:10

正如前面的答案所指出的,json字符串应该与由stripe发送的播放负载相同。在我的情况下,我不得不删除\r以使它像遵循var json = (await stripStream.ReadToEndAsync()).Replace("\r", "");那样工作,下面是代码:

代码语言:javascript
复制
 [HttpPost("webhook")]
    public async Task<IActionResult> Index()
    {
        try
        {
            using (var stripStream = new StreamReader(HttpContext.Request.Body))
            {
                var json = (await stripStream.ReadToEndAsync()).Replace("\r", "");
                var secretKey = _settings.Value.StripeSettings.WebhookSecretKey;
                // validate webhook called by stripe only
                Logger.Information($"[WEBHOOK]: Validating webhook signature {secretKey.Substring(0, 4)}**********");
                var stripeEvent = EventUtility.ConstructEvent(json, Request.Headers["Stripe-Signature"], secretKey);
                Logger.Information($"[WEBHOOK]: Webhook signature validated");

                // handle stripe event
                await this._stripeWebhookService.HandleAsync(stripeEvent);

                return Ok();
            }
        }catch(Exception){ // handle exception}
票数 1
EN

Stack Overflow用户

发布于 2020-12-29 14:48:04

我的应用程序在这一点上也一直抛出一个异常。

代码语言:javascript
复制
 var stripeEvent = EventUtility.ConstructEvent(
              json,
              Request.Headers["Stripe-Signature"],
              secret
            );

阅读异常日志时,它说我使用的是新版本的NuGet包stripe.net和条带仪表板中的旧版本。我更新我的帐户到最新的API版本,我不再收到错误。

如果在其他应用程序中使用旧版本,请小心更新仪表板中的版本。如果仪表板中的更新破坏了其他应用程序,则您有72小时的时间来撤消它。我是从零开始的,所以更新对我来说没什么大不了的。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/43888618

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档