1 回答
TA贡献1725条经验 获得超7个赞
据我所知,这段代码只是一个真正有效的代码。我在堆栈溢出中找到的所有其他示例都不起作用,因为在编写签名字符串时,它们不是传递 webhook本身的 ID,而是使用 webhook 事件的 ID,因此验证将失败。
在 Paypal 开发者后端添加 webhook 后,将生成 webhook ID。创建 Webhook 后,您将在已安装的 Webhook 列表中看到其 ID。
其余部分非常简单:我们获取标头和 HTTP 正文,并使用 Paypal 的配方组成签名:
为了生成签名,PayPal 使用竖线 (|) 字符连接和分隔这些项目。
“这些项目”是:传输 ID、传输日期、Webhook ID 和 HTTP 正文上的 CRC。前两个可以在请求的 header 中找到,开发者后端的 webhook id(当然,该 id 永远不会改变),CRC 的计算如下所示。
证书的位置也位于标头中,因此我们加载它并提取私钥。
最后要注意的是:Paypal 提供的算法名称(同样在标头字段中)与 PHP 所理解的并不完全相同。Paypal 将其称为“sha256WithRSA”,但openssl_verify
期望为“sha256WithRSAEncryption”。
// get request headers
$headers=apache_request_headers();
// get http payload
$body=file_get_contents('php://input');
// compose signature string: The third part is the ID of the webhook ITSELF(!),
// NOT the ID of the webhook event sent. You find the ID of the webhook
// in Paypal's developer backend where you have created the webhook
$data=
$headers['Paypal-Transmission-Id'].'|'.
$headers['Paypal-Transmission-Time'].'|'.
'[THE_ID_OF_THE_WEBHOOK_ACCORDING_TO_DEVELOPER_BACKEND]'.'|'.
crc32($body);
// load certificate and extract public key
$pubKey=openssl_pkey_get_public(file_get_contents($headers['Paypal-Cert-Url']));
$key=openssl_pkey_get_details($pubKey)['key'];
// verify data against provided signature
$result=openssl_verify(
$data,
base64_decode($headers['Paypal-Transmission-Sig']),
$key,
'sha256WithRSAEncryption'
);
if ($result==1) {
// webhook notification is verified
...
}
elseif ($result==0) {
// webhook notification is NOT verified
...
}
else {
// there was an error verifying this
...
}
- 1 回答
- 0 关注
- 183 浏览
添加回答
举报