1

我正在使用 gocardless hooks ,并且我坚持使用沙盒环境验证 hmac 签名。

所以我在沙盒中生成了 webhook 测试,它给了我发送的请求正文和标头。

据我了解,我必须获取请求正文并使用密钥生成散列,并将其与 webhook 签名标头散列进行比较(听起来并不复杂)。

所以我使用邮递员在我的本地环境中复制它,附加相同的标题和相同的正文,但签名从不匹配。

这是我尝试过的:

 $signature = hash_hmac('sha256',$request->getContent(), 'secret');

请注意,我正在使用 laravel 框架,所以我的第一个想法可能是框架在内部操纵请求,所以我尝试了这个:

 $request_data = file_get_contents('php://input');
 $signature = hash_hmac('sha256',$request_data, 'secret');

但仍然不匹配,我注意到了一些新行,也许这可能会修改结果,所以我清理了它......

 $request_data = str_replace(array('.', ' ', "\n", "\t", "\r"), '', $request_data);

但仍然不匹配,而且我尝试将正文数据转换为 utf8 ,并使 hmac 返回原始数据并将其编码为 base64 ......但没有成功。

那么这里有什么问题呢?也许签名在沙盒环境中不起作用?有人处理过吗?

提前致谢!

4

2 回答 2

2

最后我发现了问题,在 goocardless 的沙箱面板中,他们显示请求未缩小,所以长度不同,只需缩小它,您就可以测试了!现在签名匹配!

于 2016-07-31T13:12:05.230 回答
1

我们更新了我们的开发人员文档,您可以在https://developer.gocardless.com/getting-started/api/staying-up-to-date-with-webhooks/?lang=找到验证 webhook 签名的示例php#building-a-webhook-handler

你想做类似的事情

<?php
// We recommend storing your webhook endpoint secret in an environment variable
// for security, but you could include it as a string directly in your code
$token = getenv("GC_WEBHOOK_SECRET");

$raw_payload = file_get_contents('php://input');

$headers = getallheaders();
$provided_signature = $headers["Webhook-Signature"];

$calculated_signature = hash_hmac("sha256", $raw_payload, $token);

if ($provided_signature == $calculated_signature) {
  // Process the events

  header("HTTP/1.1 200 OK");
} else {
  header("HTTP/1.1 498 Invalid Token");
}
于 2016-09-16T14:42:52.667 回答