我对SSL和证书不是很了解。我在PHP上用了“如何使用hash_hmac()和“SHA256withRSA”?”看看我是否可以在PayPal工作的情况下获得webhook。
我的问题是我得到以下错误后调用openssl_verify()
和返回结果(0):
OpenSSL错误openssl_verify错误:04091068:rsa例程:INT_RSA_VERIFY:错误签名
我试图解决这个问题,但留档在错误和网络周围的功能是最小的。
我当前的代码如下所示:
// 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_pkey_get_details($pubKey)
,因为除了现有的签名错误之外,我还会得到以下错误:
OpenSSL错误openssl_verify错误:0906D06C:PEM例程:PEM_read_bio:无起始行OpenSSL错误openssl_verify错误:04091068:rsa例程:INT_RSA_VERIFY:错误签名
此外,我尝试了一种变体,在标头上不使用base64_decode()
,但会得到相同的返回结果(0),并错误地指出:
OpenSSL错误openssl_verify错误: 04091077:rsa例程:INT_RSA_VERIFY:错误的签名长度
签名有什么问题?
您可能想要使用这段代码:
$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');
}
公式是
这可能不是您想要的,但是使用OpenSSL手动验证签名的替代方法可能是使用PayPalPHPRestfulAPI。
PayPalRestfulAPI公开了一个endpoint,允许您验证网络钩子: /v1/notifications/verify-网络钩子签名
PayPal-PHP-SDK提供了一个VerifyWebhookSignature
类,可以轻松调用该终端。
他们还有一个示例脚本,说明如何使用VerifyWebhookSignature
类。