Насколько мне известно, этот код - единственный, который действительно работает. Все другие примеры переполнения стека, которые я нашел, не будут работать, потому что вместо передачи идентификатора веб-перехватчика самого при составлении строки подписи они используют идентификатор события веб-перехватчика, поэтому проверка не удастся.
Идентификатор веб-перехватчика будет сгенерирован после добавления веб-перехватчика в серверную часть Paypal для разработчиков. После создания веб-перехватчика вы увидите его идентификатор в списке установленных веб-перехватчиков.
Остальное довольно просто: мы получаем заголовки и тело HTTP и составляем подпись, используя рецепт Paypal:
Чтобы создать подпись, PayPal объединяет и разделяет эти элементы вертикальной чертой (|).
«Эти элементы»: идентификатор передачи, дата передачи, идентификатор веб-перехватчика. и CR C по телу HTTP. Первые два можно найти в заголовке запроса, идентификаторе веб-перехватчика в бэкэнде разработчика (конечно, этот идентификатор никогда не изменится), CR C рассчитывается, как показано ниже.
Сертификат местоположение также находится в заголовке, поэтому мы загружаем его и извлекаем закрытый ключ.
Последнее, на что нужно обратить внимание: имя алгоритма, предоставляемого 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
...
}