Php 如何验证Paypal webhook通知DIY样式(不使用Paypal SDK)

Php 如何验证Paypal webhook通知DIY样式(不使用Paypal SDK),php,paypal,paypal-webhooks,Php,Paypal,Paypal Webhooks,集成Paypal的智能按钮后,我在验证Paypal发送的webhook通知时遇到问题。我发现的例子要么已经过时,要么不起作用 是否有一种方法可以验证webhook通知,最好是采用DIY方式(即不必使用庞大而复杂的Paypal API)?据我所知,这段代码是唯一一段真正有效的代码。我在堆栈溢出上发现的所有其他示例都不起作用,因为在编写签名字符串时,它们没有传递webhook本身的ID,而是使用webhook事件的ID,因此验证将失败 一旦在Paypal的开发者后端添加webhook,就会生成web

集成Paypal的智能按钮后,我在验证Paypal发送的webhook通知时遇到问题。我发现的例子要么已经过时,要么不起作用


是否有一种方法可以验证webhook通知,最好是采用DIY方式(即不必使用庞大而复杂的Paypal API)?

据我所知,这段代码是唯一一段真正有效的代码。我在堆栈溢出上发现的所有其他示例都不起作用,因为在编写签名字符串时,它们没有传递webhook本身的ID,而是使用webhook事件的ID,因此验证将失败

一旦在Paypal的开发者后端添加webhook,就会生成webhook ID。创建webhook后,您将在已安装的webhook列表中看到它的id

剩下的很简单:我们得到了头和HTTP主体,并使用Paypal的配方编写了签名:

为了生成签名,PayPal连接并分离这些签名 具有管道(|)字符的项目

“这些项目”是:传输id、传输日期、webhook id和HTTP主体上的CRC。前两个可以在请求的头中找到,开发人员后端的webhook id(当然,该id永远不会改变),CRC的计算如下所示

证书的位置也在头中,因此我们加载它并提取私钥

最后要注意的是:Paypal提供的算法名称(同样在标题字段中)与PHP理解的不完全相同。Paypal称之为“sha256WithRSA”,但
openssl\u verify
将预期为“sha256WithRSA加密”


对此做出响应以避免潜在的麻烦,但上面的示例不起作用,因为认证令牌需要与证书文件的get请求一起发送“
file\u get\u contents($header['Paypal-cert-Url'))
”本身无法工作


只需将您的身份验证令牌包含在标题中,它就可以工作。

我从2020年年中开始使用此代码,与图中所示完全相同,并且它的工作方式肯定与图中所示相同。百分之百。
// 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
    ...
}