如何在PHP中验证Paypal webhook签名?
我对SSL和证书不是很了解。我用的是邮局 “看看我能不能让PayPal的网络钩子正常工作 我遇到的问题是,在调用如何在PHP中验证Paypal webhook签名?,php,ssl,paypal,openssl,webhooks,Php,Ssl,Paypal,Openssl,Webhooks,我对SSL和证书不是很了解。我用的是邮局 “看看我能不能让PayPal的网络钩子正常工作 我遇到的问题是,在调用openssl\u verify()并返回结果(0)后,出现以下错误: OpenSSL错误OpenSSL_验证错误:04091068:rsa例程:INT_rsa_验证:错误签名 我试图解决这个问题,但是关于错误和web函数的文档很少甚至没有 我当前的代码如下所示: // get the header post to my php file by PayPal $headers =
openssl\u verify()
并返回结果(0)后,出现以下错误:
OpenSSL错误OpenSSL_验证错误:04091068:rsa例程:INT_rsa_验证:错误签名
我试图解决这个问题,但是关于错误和web函数的文档很少甚至没有
我当前的代码如下所示:
// get the header post to my php file by PayPal
$headers = apache_request_headers();
// get the body post to me php file by PayPal
$body = @file_get_contents('php://input');
$json = json_decode($body);
// TransmissionId|TransmissionTimeStamp|WebhookId|CRC32 as per PayPal documentation
$sigString = $headers['Paypal-Transmission-Id'].'|'.$headers['Paypal-Transmission-Time'].'|'.$json->id.'|'.crc32($body);
// $headers['Paypal-Cert-Url'] contains the "-----BEGIN CERTIFICATE---MIIHmjCCBoKgAwIBAgIQDB8 ... -----END CERTIFICATE-----"
$pubKey = openssl_pkey_get_public(file_get_contents($headers['Paypal-Cert-Url']));
// and this is the call to verify that returns result (0)
$verifyResult = openssl_verify($sigString, base64_decode($headers['Paypal-Transmission-Sig']), $pubKey, 'sha256WithRSAEncryption');
与我使用的参考代码唯一不同的是,我没有使用openssl\u pkey\u get\u details($pubKey)
,因为除了现有的签名错误之外,我还会得到以下错误:
OpenSSL错误OpenSSL_验证错误:0906D06C:PEM例程:PEM_读取\u bio:无起始行
OpenSSL错误OpenSSL_验证错误:04091068:rsa例程:INT_rsa_验证:错误签名
此外,我还尝试了一种变体,即在标头上不使用base64\u decode()
,但这将得到相同的返回结果(0),错误为:
OpenSSL错误OpenSSL_验证错误:04091077:rsa例程:INT_rsa_验证:签名长度错误
签名有什么问题?您可能需要使用以下代码:
$pubKey = openssl_pkey_get_public(file_get_contents($headers['PAYPAL-CERT-URL']));
$details = openssl_pkey_get_details($pubKey);
$verifyResult = openssl_verify($sigString, base64_decode($headers['PAYPAL-TRANSMISSION-SIG']), $details['key'], 'sha256WithRSAEncryption');
if ($verifyResult === 0) {
throw new Exception('signature incorrect');
} elseif ($verifyResult === -1) {
throw new Exception('error checking signature');
}
这可能不是您想要的,但是使用开放SSL手动验证签名的替代方法是使用PayPal PHP Restful API PayPal Restful API公开了一个允许您验证webhook的端点: 提供了一个
VerifyWebhookSignature
类,使调用该端点变得容易
他们还有一个演示如何使用
验证WebHookSignature
类的示例。公式是|| |
而不是| |
。还要注意,Webhook模拟器事件无法验证。我认为您不应该使用$json->id
,因为这是事件的id,而不是web hook的id。web钩子ID不是随事件一起发送的-您必须在这里使用常量。我想@Maxime Rainville建议的带有官方SDK的解决方案是一个更好的主意。即使您需要为此执行另一个HTTP调用。