我正在使用 NuGet 的 Stripe.net SDK。我总是得到
Webhook 的签名不存在于 Stripe-Signature 标头中。
StripeEventUtility.ConstructEvent
方法的例外。
[HttpPost]
public void Test([FromBody] JObject incoming)
{
var stripeEvent = StripeEventUtility.ConstructEvent(incoming.ToString(), Request.Headers["Stripe-Signature"], Constants.STRIPE_LISTENER_KEY);
}
WebHook 密钥正确,请求标头包含“Stripe-Signature”密钥。
我正确接收来自 Webhook 测试器实用程序的传入数据(使用 nGrok 和 Visual Studio)。
secureCompare
方法似乎是罪魁祸首 => StripeEventUtility.cs
我尝试操作来自 Stripe 的传入数据(Jobject、字符串、序列化...)。有效负载签名可能会导致一些问题。
有人遇到同样的问题吗?
根据@Josh的评论,我收到了同样的错误
Webhook 的签名不存在于 Stripe-Signature 标头中。
这是因为我错误地使用了 API 密钥(以
sk_
开头)来验证 EventUtility.ConstructEvent
上的 HMAC。
相反,Stripe WebHook 有效负载是使用 Web Hook 签名密钥(以
whsec_
开头)进行签名,如 根据文档
Web Hook Signing Secret
可以从Developers -> WebHooks
页面获取:
由于您使用的是 Stripe 仪表板中的密钥,也可能会发生该错误。如果您使用 CLI 进行测试,则需要使用 stripe cli 生成的临时文件。
要获取它,请运行以下命令:
stripe listen --print-secret
当我在调试器中查看时,我也收到了相同的异常消息,但是当我
Console.WriteLine(e.Message);
时,我收到了不同的异常消息。
收到 API 版本为 2020-08-27 的事件,但 Stripe.net 40.5.0 预计 API 版本为 2022-08-01。我们建议您使用此 API 版本创建 WebhookEndpoint。否则,您可以通过将
传递给throwOnApiVersionMismatch: false
或Stripe.EventUtility.ParseEvent
来禁用此异常,但要小心对象可能会被错误地反序列化。Stripe.EventUtility.ConstructEvent
我想你最好的选择是将
throwOnApiVersionMismatch
设置为 false
;
EventUtility.ParseEvent(json, header, secret, throwOnApiVersionMismatch: false)
我不确定这样做的原因,但是从
Request.Body
读取的 Json 的结构与用 [FromBody]
解析并序列化为字符串的结构有点不同。
此外,您需要删除
[FromBody] JObject incoming
,因为这样 Request.Body
将为空。
您需要的解决方案是:
[HttpPost]
public void Test()
{
string bodyStr = "";
using (var rd = new System.IO.StreamReader(Request.Body))
{
bodyStr = await rd.ReadToEndAsync();
}
var stripeEvent = StripeEventUtility.ConstructEvent(bodyStr, Request.Headers["Stripe-Signature"], Constants.STRIPE_LISTENER_KEY);
}
试试这个方法!
当您测试时使用 vscode :https://docs.stripe.com/stripe-vscode
在这里替换stripe cli生成的密钥
var WebhookSecret = "your-Key-here";
var stripeSigniture = req.Headers.GetValues("Stripe-Signature").FirstOrDefault(); stripeEvent = EventUtility.ConstructEvent( json, stripeSigniture, WebhookSecret, 300, throwOnApiVersionMismatch: false);