我得出结论,Paypal开发者信息非常不好,分散在多个不同的页面和网站上。他们在
这里提供的示例并不是验证Webhook签名所需的完整图片。相比之下,Stripe开发者文档的格式更好,更简洁。
安装Paypal Checkout V2 SDK并不能为您提供必要的开发工具来验证paypal webhook签名,也就是说,您可以处理付款并接收webhook,但无法验证webhook签名......很愚蠢。提示:不要直接下载SDK,因为您将不会包含所需的autoload.php文件。使用composer安装Paypal Checkout V2 SDK,以便获取autoload.php文件。
一旦您能够处理付款并从paypal接收webhook,您需要安装另一个名为Paypal Rest API SDK的SDK。同样,请使用composer安装SDK,以便获取所需的autoload.php文件。
当您安装Paypal Rest API SDK时,仍然缺少验证Payapl webhook签名所需的文件。我找不到任何地方提到这些。bootstrap.php和common.php
感谢@Grumpy在github上提供了一些示例
这里
请注意,您可能需要修改示例才能使其与您的网站配合使用。提示:将记录器设置为false,并节省一些麻烦,如果您没有必要的访问权限来编写。
创建bootstrap.php和common.php文件后,您可以编写Webhook端点页面的代码,即Paypal发送Webhook的页面。我在下面包含了我的PHP代码,以验证并处理paypal webhook。提示:在下面的代码中,您需要指定Webhook ID,每个在paypal中创建的Webhook都有唯一的ID。此外,在测试时,您无法使用Webhook模拟器,因为这将导致验证失败,您可以使用沙箱账户详细信息手动进行付款,这将触发Webhook付款事件。
Paypal肯定不会让它变得容易,他们的文档比Stripe分散得多。Paypal Webhooks有时需要数分钟才能在付款后到达,这让人非常沮丧。此外,他们在paypal开发者网站上有一个Webhook模拟器,但不能用于验证签名......如果Stripe可以做到,为什么Paypal不能呢?
<?php
$requestBody = file_get_contents('php://input');
if($requestBody) {
} else {
exit();
}
use \PayPal\Api\VerifyWebhookSignature;
use \PayPal\Api\WebhookEvent;
$apiContext = require __DIR__ . '/bootstrap.php';
$headers = getallheaders();
$headers = array_change_key_case($headers, CASE_UPPER);
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();
}
$webhookID = "ENTER_YOUR_WEBHOOK_ID_HERE";
$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) {
ResultPrinter::printError("Validate Received Webhook Event", "WebhookEvent", null, $request->toJSON(), $ex);
exit(1);
}
$sigVerificationResult = $output->getVerificationStatus();
if($sigVerificationResult != "SUCCESS"){
exit();
}
else if($sigVerificationResult == "SUCCESS"){
$requestBodyDecode = json_decode($requestBody);
$paymentSystemID = $requestBodyDecode->id;
$eventType = $requestBodyDecode->event_type;
}