Files
apache
wp-content
mu-plugins
plugins
activitypub
audioigniter
authldap
companion-auto-update
easy-digital-downloads
assets
includes
adjustments
admin
api
blocks
cart
checkout
compat
currency
customers
database
downloads
emails
extensions
gateways
libs
paypal
admin
exceptions
webhooks
events
class-webhook-handler.php
class-webhook-validator.php
functions.php
buy-now.php
checkout-actions.php
class-account-status-validator.php
class-merchant-account.php
class-paypal-api.php
class-token.php
deprecated.php
functions.php
gateway-filters.php
integrations.php
ipn.php
paypal.php
refunds.php
scripts.php
stripe
actions.php
amazon-payments.php
functions.php
manual.php
paypal-standard.php
libraries
logs
models
notes
orders
payments
reports
traits
users
utils
EDD_SL_Plugin_Updater.php
actions.php
ajax-functions.php
class-base-object.php
class-component.php
class-easy-digital-downloads.php
class-edd-cache-helper.php
class-edd-cli.php
class-edd-cron.php
class-edd-customer-query.php
class-edd-customer.php
class-edd-db-customer-meta.php
class-edd-db-customers.php
class-edd-db.php
class-edd-discount.php
class-edd-download.php
class-edd-fees.php
class-edd-html-elements.php
class-edd-license-handler.php
class-edd-logging.php
class-edd-register-meta.php
class-edd-requirements-check.php
class-edd-roles.php
class-edd-session.php
class-edd-stats.php
class-stats.php
class-structured-data.php
class-utilities.php
compat-functions.php
component-functions.php
country-functions.php
customer-functions.php
date-functions.php
deprecated-functions.php
deprecated-hooks.php
discount-functions.php
download-functions.php
error-tracking.php
formatting.php
install.php
interface-edd-exception.php
mime-types.php
misc-functions.php
plugin-compatibility.php
post-types.php
privacy-functions.php
process-download.php
process-purchase.php
query-filters.php
refund-functions.php
scripts.php
shortcodes.php
tax-functions.php
template-actions.php
template-functions.php
theme-compatibility.php
user-functions.php
widgets.php
languages
src
templates
vendor
easy-digital-downloads.php
license.txt
readme.txt
uninstall.php
gitium
gp-premium
jetpack-protect
menu-icons
simple-local-avatars
smtp-mailer
two-factor
w3-total-cache
wp-piwik
wp-webauthn
index.php
themes
w3tc-config
index.php
.dbsetup
.gitignore
htaccess
php.ini
laipower/wp-content/plugins/easy-digital-downloads/includes/gateways/paypal/webhooks/class-webhook-validator.php

169 lines
3.6 KiB
PHP

<?php
/**
* Webhook Validator
*
* @link https://developer.paypal.com/docs/api/webhooks/v1/#verify-webhook-signature_post
*
* @package easy-digital-downloads
* @subpackage Gateways\PayPal\Webhooks
* @copyright Copyright (c) 2021, Sandhills Development, LLC
* @license GPL2+
* @since 2.11
*/
namespace EDD\Gateways\PayPal\Webhooks;
use EDD\Gateways\PayPal\API;
use EDD\Gateways\PayPal\Exceptions\API_Exception;
class Webhook_Validator {
/**
* Headers from the webhook
*
* @var array
* @since 2.11
*/
private $headers;
/**
* Webhook event
*
* @var object
* @since 2.11
*/
private $event;
/**
* Maps the incoming header key to the outgoing API request key.
*
* @var string[]
* @since 2.11
*/
private $header_map = array(
'PAYPAL-AUTH-ALGO' => 'auth_algo',
'PAYPAL-CERT-URL' => 'cert_url',
'PAYPAL-TRANSMISSION-ID' => 'transmission_id',
'PAYPAL-TRANSMISSION-SIG' => 'transmission_sig',
'PAYPAL-TRANSMISSION-TIME' => 'transmission_time'
);
/**
* Webhook_Validator constructor.
*
* @param array $headers
* @param object $event
*
* @since 2.11
*/
public function __construct( $headers, $event ) {
$this->headers = array_change_key_case( $headers, CASE_UPPER );
$this->event = $event;
}
/**
* Verifies the signature.
*
* @since 2.11
* @return true
* @throws API_Exception
* @throws \InvalidArgumentException
*/
public function verify_signature() {
$api = new API();
$response = $api->make_request( 'v1/notifications/verify-webhook-signature', $this->get_body() );
if ( 200 !== $api->last_response_code ) {
throw new API_Exception( sprintf(
'Invalid response code: %d. Response: %s',
$api->last_response_code,
json_encode( $response )
) );
}
if ( empty( $response->verification_status ) || 'SUCCESS' !== strtoupper( $response->verification_status ) ) {
throw new API_Exception( sprintf(
'Verification failure. Response: %s',
json_encode( $response )
) );
}
return true;
}
/**
* Validates that we have all the required headers.
*
* @since 2.11
* @throws \InvalidArgumentException
*/
private function validate_headers() {
foreach ( array_keys( $this->header_map ) as $required_key ) {
if ( ! array_key_exists( $required_key, $this->headers ) ) {
throw new \InvalidArgumentException( sprintf(
'Missing PayPal header %s',
$required_key
) );
}
}
}
/**
* Retrieves the webhook ID for the current mode.
*
* @since 2.11
* @return string
* @throws \Exception
*/
private function get_webhook_id() {
$id = get_webhook_id();
if ( empty( $id ) ) {
throw new \Exception( 'No webhook created in current mode.' );
}
return $id;
}
/**
* Builds arguments for the body of the API request.
*
* @return array
* @throws \InvalidArgumentException
* @throws \Exception
*/
private function get_body() {
$this->validate_headers();
$body = array(
'webhook_id' => $this->get_webhook_id(),
'webhook_event' => $this->event
);
// Add arguments from the headers.
foreach ( $this->header_map as $header_key => $body_key ) {
$body[ $body_key ] = $this->headers[ $header_key ];
}
return $body;
}
/**
* Validates the webhook from the current request.
*
* @param object $event Webhook event.
*
* @since 2.11
* @return true
* @throws API_Exception
* @throws \InvalidArgumentException
*/
public static function validate_from_request( $event ) {
$validator = new Webhook_Validator( getallheaders(), $event );
return $validator->verify_signature();
}
}