gocardless PHP hmac 签名不匹配

问题描述 投票:0回答:3

我正在使用 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 ...但没有成功。

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

提前致谢!

php sandbox signature hmac gocardless
3个回答
2
投票

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


1
投票

我们更新了开发人员文档,您可以在 https://developer.gocardless.com/getting-started/api/staying-up-to-date-with-webhooks/? 找到验证 webhook 签名的示例lang=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");
}

0
投票

如果你遇到这个问题,这意味着 laravel 已经更改了传入的请求正文,因此你需要将其恢复为正常形式,如下所示

  $request_data = json_decode($request->getContent(), true);
  $corrected_request_json = json_encode($request_data, JSON_UNESCAPED_SLASHES);

$calculated_signature = hash_hmac("sha256", $corrected_request_json, $token);
最新问题
© www.soinside.com 2019 - 2025. All rights reserved.