1 回答

TA貢獻1725條經驗 獲得超8個贊
據我所知,這段代碼只是一個真正有效的代碼。我在堆棧溢出中找到的所有其他示例都不起作用,因為在編寫簽名字符串時,它們不是傳遞 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 關注
- 306 瀏覽
添加回答
舉報