mirror of
https://github.com/woocommerce/woocommerce-paypal-payments.git
synced 2025-09-12 01:18:39 +08:00
Add webhook simulation
This commit is contained in:
parent
0268524261
commit
ea2f728cd8
14 changed files with 896 additions and 20 deletions
|
@ -35,6 +35,7 @@ use WooCommerce\PayPalCommerce\ApiClient\Factory\PaymentTokenFactory;
|
|||
use WooCommerce\PayPalCommerce\ApiClient\Factory\PurchaseUnitFactory;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Factory\SellerStatusFactory;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Factory\ShippingFactory;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Factory\WebhookEventFactory;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Factory\WebhookFactory;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Helper\Cache;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Helper\DccApplies;
|
||||
|
@ -114,6 +115,7 @@ return array(
|
|||
$container->get( 'api.host' ),
|
||||
$container->get( 'api.bearer' ),
|
||||
$container->get( 'api.factory.webhook' ),
|
||||
$container->get( 'api.factory.webhook-event' ),
|
||||
$container->get( 'woocommerce.logger.woocommerce' )
|
||||
);
|
||||
},
|
||||
|
@ -214,6 +216,9 @@ return array(
|
|||
'api.factory.webhook' => static function ( $container ): WebhookFactory {
|
||||
return new WebhookFactory();
|
||||
},
|
||||
'api.factory.webhook-event' => static function ( $container ): WebhookEventFactory {
|
||||
return new WebhookEventFactory();
|
||||
},
|
||||
'api.factory.capture' => static function ( $container ): CaptureFactory {
|
||||
|
||||
$amount_factory = $container->get( 'api.factory.amount' );
|
||||
|
|
|
@ -11,8 +11,10 @@ namespace WooCommerce\PayPalCommerce\ApiClient\Endpoint;
|
|||
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Authentication\Bearer;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\Webhook;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\WebhookEvent;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Exception\PayPalApiException;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Factory\WebhookEventFactory;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Factory\WebhookFactory;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
|
@ -44,6 +46,13 @@ class WebhookEndpoint {
|
|||
*/
|
||||
private $webhook_factory;
|
||||
|
||||
/**
|
||||
* The webhook event factory.
|
||||
*
|
||||
* @var WebhookEventFactory
|
||||
*/
|
||||
private $webhook_event_factory;
|
||||
|
||||
/**
|
||||
* The logger.
|
||||
*
|
||||
|
@ -54,22 +63,25 @@ class WebhookEndpoint {
|
|||
/**
|
||||
* WebhookEndpoint constructor.
|
||||
*
|
||||
* @param string $host The host.
|
||||
* @param Bearer $bearer The bearer.
|
||||
* @param WebhookFactory $webhook_factory The webhook factory.
|
||||
* @param LoggerInterface $logger The logger.
|
||||
* @param string $host The host.
|
||||
* @param Bearer $bearer The bearer.
|
||||
* @param WebhookFactory $webhook_factory The webhook factory.
|
||||
* @param WebhookEventFactory $webhook_event_factory The webhook event factory.
|
||||
* @param LoggerInterface $logger The logger.
|
||||
*/
|
||||
public function __construct(
|
||||
string $host,
|
||||
Bearer $bearer,
|
||||
WebhookFactory $webhook_factory,
|
||||
WebhookEventFactory $webhook_event_factory,
|
||||
LoggerInterface $logger
|
||||
) {
|
||||
|
||||
$this->host = $host;
|
||||
$this->bearer = $bearer;
|
||||
$this->webhook_factory = $webhook_factory;
|
||||
$this->logger = $logger;
|
||||
$this->host = $host;
|
||||
$this->bearer = $bearer;
|
||||
$this->webhook_factory = $webhook_factory;
|
||||
$this->webhook_event_factory = $webhook_event_factory;
|
||||
$this->logger = $logger;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -189,6 +201,51 @@ class WebhookEndpoint {
|
|||
return wp_remote_retrieve_response_code( $response ) === 204;
|
||||
}
|
||||
|
||||
/**
|
||||
* Request a simulated webhook to be sent.
|
||||
*
|
||||
* @param Webhook $hook The webhook subscription to use.
|
||||
* @param string $event_type The event type, such as CHECKOUT.ORDER.APPROVED.
|
||||
*
|
||||
* @return WebhookEvent
|
||||
* @throws RuntimeException If the request fails.
|
||||
* @throws PayPalApiException If the request fails.
|
||||
*/
|
||||
public function simulate( Webhook $hook, string $event_type ): WebhookEvent {
|
||||
$bearer = $this->bearer->bearer();
|
||||
$url = trailingslashit( $this->host ) . 'v1/notifications/simulate-event';
|
||||
$args = array(
|
||||
'method' => 'POST',
|
||||
'headers' => array(
|
||||
'Authorization' => 'Bearer ' . $bearer->token(),
|
||||
'Content-Type' => 'application/json',
|
||||
),
|
||||
'body' => wp_json_encode(
|
||||
array(
|
||||
'webhook_id' => $hook->id(),
|
||||
'event_type' => $event_type,
|
||||
)
|
||||
),
|
||||
);
|
||||
$response = $this->request( $url, $args );
|
||||
|
||||
if ( is_wp_error( $response ) ) {
|
||||
throw new RuntimeException(
|
||||
__( 'Not able to simulate webhook.', 'woocommerce-paypal-payments' )
|
||||
);
|
||||
}
|
||||
$json = json_decode( $response['body'] );
|
||||
$status_code = (int) wp_remote_retrieve_response_code( $response );
|
||||
if ( 202 !== $status_code ) {
|
||||
throw new PayPalApiException(
|
||||
$json,
|
||||
$status_code
|
||||
);
|
||||
}
|
||||
|
||||
return $this->webhook_event_factory->from_paypal_response( $json );
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies if a webhook event is legitimate.
|
||||
*
|
||||
|
|
170
modules/ppcp-api-client/src/Entity/class-webhookevent.php
Normal file
170
modules/ppcp-api-client/src/Entity/class-webhookevent.php
Normal file
|
@ -0,0 +1,170 @@
|
|||
<?php
|
||||
/**
|
||||
* The Webhook event notification object.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\ApiClient\Entity
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\ApiClient\Entity;
|
||||
|
||||
use DateTime;
|
||||
use stdClass;
|
||||
|
||||
/**
|
||||
* Class WebhookEvent
|
||||
*/
|
||||
class WebhookEvent {
|
||||
|
||||
/**
|
||||
* The ID of the event notification.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $id;
|
||||
|
||||
/**
|
||||
* The date and time when the event notification was created.
|
||||
*
|
||||
* @var DateTime|null
|
||||
*/
|
||||
private $create_time;
|
||||
|
||||
/**
|
||||
* The name of the resource related to the webhook notification event, such as 'checkout-order'.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $resource_type;
|
||||
|
||||
/**
|
||||
* The event version in the webhook notification, such as '1.0'.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $event_version;
|
||||
|
||||
/**
|
||||
* The event that triggered the webhook event notification, such as 'CHECKOUT.ORDER.APPROVED'.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $event_type;
|
||||
|
||||
/**
|
||||
* A summary description for the event notification.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $summary;
|
||||
|
||||
/**
|
||||
* The resource version in the webhook notification, such as '1.0'.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $resource_version;
|
||||
|
||||
/**
|
||||
* The resource that triggered the webhook event notification.
|
||||
*
|
||||
* @var stdClass
|
||||
*/
|
||||
private $resource;
|
||||
|
||||
/**
|
||||
* WebhookEvent constructor.
|
||||
*
|
||||
* @param string $id The ID of the event notification.
|
||||
* @param DateTime|null $create_time The date and time when the event notification was created.
|
||||
* @param string $resource_type The name of the resource related to the webhook notification event, such as 'checkout-order'.
|
||||
* @param string $event_version The event version in the webhook notification, such as '1.0'.
|
||||
* @param string $event_type The event that triggered the webhook event notification, such as 'CHECKOUT.ORDER.APPROVED'.
|
||||
* @param string $summary A summary description for the event notification.
|
||||
* @param string $resource_version The resource version in the webhook notification, such as '1.0'.
|
||||
* @param stdClass $resource The resource that triggered the webhook event notification.
|
||||
*/
|
||||
public function __construct( string $id, ?DateTime $create_time, string $resource_type, string $event_version, string $event_type, string $summary, string $resource_version, stdClass $resource ) {
|
||||
$this->id = $id;
|
||||
$this->create_time = $create_time;
|
||||
$this->resource_type = $resource_type;
|
||||
$this->event_version = $event_version;
|
||||
$this->event_type = $event_type;
|
||||
$this->summary = $summary;
|
||||
$this->resource_version = $resource_version;
|
||||
$this->resource = $resource;
|
||||
}
|
||||
|
||||
/**
|
||||
* The ID of the event notification.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function id(): string {
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* The date and time when the event notification was created.
|
||||
*
|
||||
* @return DateTime|null
|
||||
*/
|
||||
public function create_time(): ?DateTime {
|
||||
return $this->create_time;
|
||||
}
|
||||
|
||||
/**
|
||||
* The name of the resource related to the webhook notification event, such as 'checkout-order'.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function resource_type(): string {
|
||||
return $this->resource_type;
|
||||
}
|
||||
|
||||
/**
|
||||
* The event version in the webhook notification, such as '1.0'.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function event_version(): string {
|
||||
return $this->event_version;
|
||||
}
|
||||
|
||||
/**
|
||||
* The event that triggered the webhook event notification, such as 'CHECKOUT.ORDER.APPROVED'.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function event_type(): string {
|
||||
return $this->event_type;
|
||||
}
|
||||
|
||||
/**
|
||||
* A summary description for the event notification.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function summary(): string {
|
||||
return $this->summary;
|
||||
}
|
||||
|
||||
/**
|
||||
* The resource version in the webhook notification, such as '1.0'.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function resource_version(): string {
|
||||
return $this->resource_version;
|
||||
}
|
||||
|
||||
/**
|
||||
* The resource that triggered the webhook event notification.
|
||||
*
|
||||
* @return stdClass
|
||||
*/
|
||||
public function resource(): stdClass {
|
||||
return $this->resource;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
<?php
|
||||
/**
|
||||
* Creates WebhookEvent.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\ApiClient\Factory
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\ApiClient\Factory;
|
||||
|
||||
use DateTime;
|
||||
use stdClass;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\WebhookEvent;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
|
||||
|
||||
/**
|
||||
* Class WebhookEventFactory
|
||||
*/
|
||||
class WebhookEventFactory {
|
||||
|
||||
/**
|
||||
* Returns a webhook from a given data array.
|
||||
*
|
||||
* @param array $data The data array.
|
||||
*
|
||||
* @return WebhookEvent
|
||||
*/
|
||||
public function from_array( array $data ): WebhookEvent {
|
||||
return $this->from_paypal_response( (object) $data );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a Webhook based of a PayPal JSON response.
|
||||
*
|
||||
* @param stdClass $data The JSON object.
|
||||
*
|
||||
* @return WebhookEvent
|
||||
* @throws RuntimeException When JSON object is malformed.
|
||||
*/
|
||||
public function from_paypal_response( stdClass $data ): WebhookEvent {
|
||||
if ( ! isset( $data->id ) ) {
|
||||
throw new RuntimeException(
|
||||
__( 'ID for webhook event not found.', 'woocommerce-paypal-payments' )
|
||||
);
|
||||
}
|
||||
if ( ! isset( $data->event_type ) ) {
|
||||
throw new RuntimeException(
|
||||
__( 'Event type for webhook event not found.', 'woocommerce-paypal-payments' )
|
||||
);
|
||||
}
|
||||
|
||||
$create_time = ( isset( $data->create_time ) ) ?
|
||||
DateTime::createFromFormat( 'Y-m-d\TH:i:sO', $data->create_time )
|
||||
: null;
|
||||
|
||||
// Sometimes the time may be in weird format 2018-12-19T22:20:32.000Z (at least in simulation),
|
||||
// we do not care much about time, so just ignore on failure.
|
||||
if ( false === $create_time ) {
|
||||
$create_time = null;
|
||||
}
|
||||
|
||||
return new WebhookEvent(
|
||||
(string) $data->id,
|
||||
$create_time,
|
||||
(string) $data->resource_type ?? '',
|
||||
(string) $data->event_version ?? '',
|
||||
(string) $data->event_type,
|
||||
(string) $data->summary ?? '',
|
||||
(string) $data->resource_version ?? '',
|
||||
(object) $data->resource ?? ( new stdClass() )
|
||||
);
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue