编程语言
首页 > 编程语言> > C#-条纹Webhook签名失败-Stripe.net

C#-条纹Webhook签名失败-Stripe.net

作者:互联网

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

isSignaturePresent返回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;
    }
}

解决方法:

我在上面的评论中回答了,但总而言之,问题是提供给ConstructEvent方法的json字符串不包含Stripe发送的确切负载.

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

var json = JsonSerializer.SerializeToString(request);

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

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

但是在反序列化反序列化之后,您的JSON字符串可能包含以下值:

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

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

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

标签:stripe-payments,webhooks,digital-signature,c,stripe-net
来源: https://codeday.me/bug/20191026/1933140.html