PHP验证Paypal webhook签名

kcugc4gi  于 2022-12-10  发布在  PHP
关注(0)|答案(2)|浏览(255)

我有麻烦尝试验证贝宝webhook签名与PHP。使用新的V2的贝宝API我收到贝宝webhook在我的网页上。但我似乎不能成功地验证签名。
从链接HERE我得到了一些样本webhook验证PHP代码从贝宝。
我不能让它工作,我不知道我应该从哪里得到bootstrap.php在贝宝代码。贝宝信息似乎不完整或半生不熟。贝宝似乎是可怕的设置相比,条纹。
有没有人有经验的验证贝宝webhook签名与PHP时,使用V2的贝宝API?

b1zrtrql

b1zrtrql1#

我得出的结论是,贝宝开发者的信息是相当贫乏的,它是分散在各地,在多个不同的网页和网站。他们在贝宝开发者网站HERE上给予的例子并不是一个完整的图片是什么需要验证一个webhook签名。条纹开发者文档是更好的格式和简洁。
安装Paypal Checkout V2 SDK并没有给予你必要的开发工具来验证Paypal webhook签名,也就是说,你可以处理付款和接收webhook,但你不能验证webhook签名....我知道愚蠢。提示不要直接下载SDK,因为你不会包括所需的autoload.php文件。使用composer安装Paypal Checkout V2 SDK,这样你就可以得到autoload.php文件。
一旦你到了一个点,你可以处理付款和接收webhooks从贝宝你需要安装另一个SKD称为贝宝Rest API SDK.再次使用composer安装SDK,这样你就得到了一个autoload.php文件,你将需要.
当你安装Paypal Rest API SDK时,你仍然会丢失验证Payapl Webhook签名所需的文件。我在Paypal开发者网站上找不到任何提到这些的地方。
Bootstrap . php和公共. php
感谢@Grumpy,我在github HERE上得到了一些样品
请注意,您可能需要对示例进行一些修改,以便让它们在您的网站上工作。提示:如果您没有必要的访问权限进行写入,请将logger设置为false,这样可以保存一些麻烦。
一旦你创建了bootstrap.php和common.php文件,你就可以为你的webhook端点页面写代码了,即paypal发送webhook到的页面。我已经包含了我的PHP代码,下面是如何验证和处理paypal webhook的代码。提示在下面的代码中,你需要指定webhook ID,你在贝宝中创建的每一个webhook都有一个唯一的ID。2当你在测试的时候,你不能使用webhook模拟器,因为这会导致验证失败,您可以使用沙盒帐户详细信息手动进行支付,这将触发Webhook支付事件。
Paypal确实不容易,他们的文档与Stripe相比到处都是。Paypal webhook有时需要几分钟才能在付款后到达,调试时非常令人沮丧。还有,他们在Paypal开发者网站上有一个webhook模拟器,不能用来验证签名,这有点可笑......如果Stripe能做到,为什么Paypal不能呢?

<?php



//get the webhook payload

$requestBody = file_get_contents('php://input');

//check if webhook payload has data
if($requestBody) {
//request body is set
} else {
//request body is not set
exit(); 
}



use \PayPal\Api\VerifyWebhookSignature;
use \PayPal\Api\WebhookEvent;

$apiContext = require __DIR__ . '/bootstrap.php';



//Receive HTTP headers that you received from PayPal webhook.

$headers = getallheaders();

//need header keys to be UPPERCASE

$headers = array_change_key_case($headers, CASE_UPPER);

/*

example header paypal signature content for webhook, these values are recieved as an array, we then need to use this data to verify the payload

CONTENT-LENGTH : 1376

CORRELATION-ID : 6db85170269e7

USER-AGENT : PayPal/AUHD-214.0-54377828

CONTENT-TYPE: application/json

PAYPAL-AUTH-ALGO : SHA256withRSA

PAYPAL-CERT-URL : https://api.paypal.com/v1/notifications/certs/CERT-360caa42-fca2a784-5edc0ebc

PAYPAL-AUTH-VERSION : v2

PAYPAL-TRANSMISSION-SIG : Hc2lsDedYdSjOM4/t3T/ioAVQqFPNVB/AY/EyPNlavXk5WYUfnAmt9dyEP6neAPOjFHiVkXMK+JlLODbr6dalw6i26aFQdsPXqGl38Mafuu9elPE74qgsqNferUFgHi9QFXL+UZCNYcb4mvlDePXZIIAPbB0gOuFGOdEv2uqNwTCSAa/D8aguv1/51FWb3RkytFuVwXK/XNfIEy2oJCpDs8dgtYAZeojH8qO6IAwchdSpttMods5YfNBzT7oCoxO80hncVorBtjj1zQrkoynEB9WNNN9ytepNCkT8l29fQ4Sx/WRndm/PESCqxqmRoYJoiSosxYU3bZP7QTtILDykQ==

PAYPAL-TRANSMISSION-TIME : 2020-04-05T14:40:43Z

PAYPAL-TRANSMISSION-ID : 6dec99b0-774b-11ea-b306-c3ed128f0c4b

*/

//if any of the relevant paypal signature headers are not set exit()

if(
(!array_key_exists('PAYPAL-AUTH-ALGO', $headers)) ||
(!array_key_exists('PAYPAL-TRANSMISSION-ID', $headers)) ||
(!array_key_exists('PAYPAL-CERT-URL', $headers)) ||
(!array_key_exists('PAYPAL-TRANSMISSION-SIG', $headers)) ||
(!array_key_exists('PAYPAL-TRANSMISSION-TIME', $headers)) 
)
{

exit();     
}

//specify the ID for the webhook that you have set up on the paypal developer website, each web hook that you create has a unique ID

$webhookID = "ENTER_YOUR_WEBHOOK_ID_HERE";



//start paypal webhook signature validation 

$signatureVerification = new VerifyWebhookSignature();
$signatureVerification->setAuthAlgo($headers['PAYPAL-AUTH-ALGO']);
$signatureVerification->setTransmissionId($headers['PAYPAL-TRANSMISSION-ID']);
$signatureVerification->setCertUrl($headers['PAYPAL-CERT-URL']);
$signatureVerification->setWebhookId($webhookID); 
$signatureVerification->setTransmissionSig($headers['PAYPAL-TRANSMISSION-SIG']);
$signatureVerification->setTransmissionTime($headers['PAYPAL-TRANSMISSION-TIME']);

$signatureVerification->setRequestBody($requestBody);
$request = clone $signatureVerification;

try {

$output = $signatureVerification->post($apiContext);

} catch (Exception $ex) {

//error during signature validation, capture error and exit

ResultPrinter::printError("Validate Received Webhook Event", "WebhookEvent", null, $request->toJSON(), $ex);
exit(1);

}

$sigVerificationResult = $output->getVerificationStatus();

// $sigVerificationResult is a string and will either be "SUCCESS" or "FAILURE"

//if not webhook signature failed validation exit
if($sigVerificationResult != "SUCCESS"){

exit(); 
}
else if($sigVerificationResult == "SUCCESS"){

//paypay webhook signature is valid

//proceed to process webhook payload

//decode raw request body

$requestBodyDecode = json_decode($requestBody);

//pull whatever info required from decoded request body, some examples below

$paymentSystemID = $requestBodyDecode->id;

$eventType = $requestBodyDecode->event_type;

//do something with info captured from the webhook payload

}
nvbavucw

nvbavucw2#

这似乎与php 8.1一起工作:

if (openssl_verify(
        data: implode(separator: '|', array: [
            $httpPayPalTransmissionId,
            $httpPayPalTransmissionTime,
            $webhookID,
            crc32(string: $rawRequestBody),
        ]),
        signature: base64_decode(string: $httpPayPalTransmissionSignature),
        public_key: openssl_pkey_get_public(public_key: file_get_contents(filename: $cachedHttpPayPalCertUrl)),
        algorithm: 'sha256WithRSAEncryption'
    ) === 1) {
    die('OK');
} else {
    die('FAILED');
}

相关问题