条纹Webhook签名失败-Stripe.net [英] Stripe webhook signature failed - Stripe.net

查看:297
本文介绍了条纹Webhook签名失败-Stripe.net的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用Jayme Davis的c#库Stripe.net实现条纹webhook。我已经在条纹仪表板中设置了测试端点,并生成了机密信息。端点运行良好,并将使用StripeEventUtility.ParseEvent生成StripeEvent。问题是使用ConstructEvent函数,我无法获得匹配的签名。任何帮助或建议,将不胜感激。

Im trying to implement a stripe webhook using the the c# library Stripe.net by Jayme Davis. i have set up the test endpoint in the stripe dashboard and generated the secret. The endpoint is being hit fine, and will generate the StripeEvent using the StripeEventUtility.ParseEvent. The problem is with using the ConstructEvent function i cant get the signatures to match. Any help or suggestions would be much appreciated.

isSignaturePresent返回false

isSignaturePresent is returning false

//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;
    }
}


推荐答案

I在上面的评论中回答,但要回顾一下,问题在于提供给 ConstructEvent 方法的 json 字符串不包含

I answered in comments above, but to recap, the issue was that the json string provided to the ConstructEvent method did not contain the exact payload sent by Stripe.

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

Rather, you initialized the payload with:

var json = JsonSerializer.SerializeToString(request);

即您重新序列化了反序列化请求的正文。但是,您不太可能获得与Stripe发送的原始有效载荷相同的字符串。例如。条带可以发送此有效负载:

i.e. you reserialized the deserialized request's body. However, it's very unlikely that you would get the same string as the original payload sent by Stripe. E.g. Stripe could send this payload:

{
  "a_key": "a_value",
  "another_key": "another_value"
}

,但是在反序列化和重新序列化之后,您的JSON字符串可能包含此内容值:

but after deserializing+reserializing, your JSON string could contain this value:

{"another_key": "another_value","a_key": "a_value"}

,因为不能保证键顺序得到维护,并且其他格式选项(换行符,缩进)也可以发挥作用。

as the key order is not guaranteed to be maintained, and other formatting options (newlines, indents) come into play.

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

Webhook signatures are generated using the exact payload (as a raw string), so when verifying signatures, you must also provide that exact payload, as passed by your web server or framework.

这篇关于条纹Webhook签名失败-Stripe.net的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆