mirror of
https://github.com/woocommerce/woocommerce-paypal-payments.git
synced 2025-09-06 09:08:09 +08:00
Merge branch 'trunk' into PCP-359-customer-details-not-available-i
This commit is contained in:
commit
b3b1237247
12 changed files with 468 additions and 44 deletions
|
@ -12,6 +12,7 @@ namespace WooCommerce\PayPalCommerce\ApiClient;
|
|||
use Psr\Container\ContainerInterface;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Authentication\Bearer;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Authentication\PayPalBearer;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\BillingAgreementsEndpoint;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\IdentityToken;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\LoginSeller;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\OrderEndpoint;
|
||||
|
@ -39,6 +40,7 @@ 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\CurrencySupport;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Helper\DccApplies;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Repository\ApplicationContextRepository;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Repository\CartRepository;
|
||||
|
@ -190,6 +192,13 @@ return array(
|
|||
$subscription_helper
|
||||
);
|
||||
},
|
||||
'api.endpoint.billing-agreements' => static function ( ContainerInterface $container ): BillingAgreementsEndpoint {
|
||||
return new BillingAgreementsEndpoint(
|
||||
$container->get( 'api.host' ),
|
||||
$container->get( 'api.bearer' ),
|
||||
$container->get( 'woocommerce.logger.woocommerce' )
|
||||
);
|
||||
},
|
||||
'api.repository.paypal-request-id' => static function( ContainerInterface $container ) : PayPalRequestIdRepository {
|
||||
return new PayPalRequestIdRepository();
|
||||
},
|
||||
|
@ -302,4 +311,7 @@ return array(
|
|||
'api.helpers.dccapplies' => static function ( ContainerInterface $container ) : DccApplies {
|
||||
return new DccApplies();
|
||||
},
|
||||
'api.helpers.currency-support' => static function ( ContainerInterface $container ) : CurrencySupport {
|
||||
return new CurrencySupport();
|
||||
},
|
||||
);
|
||||
|
|
|
@ -0,0 +1,134 @@
|
|||
<?php
|
||||
/**
|
||||
* The billing agreements endpoint.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\ApiClient\Endpoint
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\ApiClient\Endpoint;
|
||||
|
||||
use stdClass;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Authentication\Bearer;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Exception\PayPalApiException;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
/**
|
||||
* Class BillingAgreementsEndpoint
|
||||
*/
|
||||
class BillingAgreementsEndpoint {
|
||||
use RequestTrait;
|
||||
|
||||
/**
|
||||
* The host.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $host;
|
||||
|
||||
/**
|
||||
* The bearer.
|
||||
*
|
||||
* @var Bearer
|
||||
*/
|
||||
private $bearer;
|
||||
|
||||
/**
|
||||
* The logger.
|
||||
*
|
||||
* @var LoggerInterface
|
||||
*/
|
||||
private $logger;
|
||||
|
||||
/**
|
||||
* BillingAgreementsEndpoint constructor.
|
||||
*
|
||||
* @param string $host The host.
|
||||
* @param Bearer $bearer The bearer.
|
||||
* @param LoggerInterface $logger The logger.
|
||||
*/
|
||||
public function __construct(
|
||||
string $host,
|
||||
Bearer $bearer,
|
||||
LoggerInterface $logger
|
||||
) {
|
||||
$this->host = $host;
|
||||
$this->bearer = $bearer;
|
||||
$this->logger = $logger;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a billing agreement token.
|
||||
*
|
||||
* @param string $description The description.
|
||||
* @param string $return_url The return URL.
|
||||
* @param string $cancel_url The cancel URL.
|
||||
*
|
||||
* @throws RuntimeException If the request fails.
|
||||
* @throws PayPalApiException If the request fails.
|
||||
*/
|
||||
public function create_token( string $description, string $return_url, string $cancel_url ): stdClass {
|
||||
$data = array(
|
||||
'description' => $description,
|
||||
'payer' => array(
|
||||
'payment_method' => 'PAYPAL',
|
||||
),
|
||||
'plan' => array(
|
||||
'type' => 'MERCHANT_INITIATED_BILLING',
|
||||
'merchant_preferences' => array(
|
||||
'return_url' => $return_url,
|
||||
'cancel_url' => $cancel_url,
|
||||
'skip_shipping_address' => true,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
$bearer = $this->bearer->bearer();
|
||||
$url = trailingslashit( $this->host ) . 'v1/billing-agreements/agreement-tokens';
|
||||
$args = array(
|
||||
'method' => 'POST',
|
||||
'headers' => array(
|
||||
'Authorization' => 'Bearer ' . $bearer->token(),
|
||||
'Content-Type' => 'application/json',
|
||||
),
|
||||
'body' => wp_json_encode( $data ),
|
||||
);
|
||||
$response = $this->request( $url, $args );
|
||||
|
||||
if ( is_wp_error( $response ) || ! is_array( $response ) ) {
|
||||
throw new RuntimeException( 'Not able to create a billing agreement token.' );
|
||||
}
|
||||
|
||||
$json = json_decode( $response['body'] );
|
||||
$status_code = (int) wp_remote_retrieve_response_code( $response );
|
||||
if ( 201 !== $status_code ) {
|
||||
throw new PayPalApiException(
|
||||
$json,
|
||||
$status_code
|
||||
);
|
||||
}
|
||||
|
||||
return $json;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if reference transactions are enabled in account.
|
||||
*
|
||||
* @throws RuntimeException If the request fails (no auth, no connection, etc.).
|
||||
*/
|
||||
public function reference_transaction_enabled(): bool {
|
||||
try {
|
||||
$this->create_token(
|
||||
'Checking if reference transactions are enabled',
|
||||
'https://example.com/return',
|
||||
'https://example.com/cancel'
|
||||
);
|
||||
|
||||
return true;
|
||||
} catch ( PayPalApiException $exception ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
70
modules/ppcp-api-client/src/Helper/CurrencySupport.php
Normal file
70
modules/ppcp-api-client/src/Helper/CurrencySupport.php
Normal file
|
@ -0,0 +1,70 @@
|
|||
<?php
|
||||
/**
|
||||
* Checks if the current installation uses supported currency.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\ApiClient\Helper
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\ApiClient\Helper;
|
||||
|
||||
/**
|
||||
* Class CurrencySupport
|
||||
*/
|
||||
class CurrencySupport {
|
||||
|
||||
/**
|
||||
* Currencies supported by PayPal.
|
||||
*
|
||||
* From https://developer.paypal.com/docs/reports/reference/paypal-supported-currencies/
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
private $supported_currencies = array(
|
||||
'AUD',
|
||||
'BRL',
|
||||
'CAD',
|
||||
'CNY',
|
||||
'CZK',
|
||||
'DKK',
|
||||
'EUR',
|
||||
'HKD',
|
||||
'HUF',
|
||||
'ILS',
|
||||
'JPY',
|
||||
'MYR',
|
||||
'MXN',
|
||||
'TWD',
|
||||
'NZD',
|
||||
'NOK',
|
||||
'PHP',
|
||||
'PLN',
|
||||
'GBP',
|
||||
'RUB',
|
||||
'SGD',
|
||||
'SEK',
|
||||
'CHF',
|
||||
'THB',
|
||||
'USD',
|
||||
);
|
||||
|
||||
/**
|
||||
* Returns whether the given currency is supported.
|
||||
*
|
||||
* @param string $currency 3-letter currency code.
|
||||
* @return bool
|
||||
*/
|
||||
public function supports_currency( string $currency ): bool {
|
||||
return in_array( $currency, $this->supported_currencies, true );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the current WC currency is supported.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function supports_wc_currency(): bool {
|
||||
return $this->supports_currency( get_woocommerce_currency() );
|
||||
}
|
||||
}
|
|
@ -73,11 +73,11 @@ class ErrorHandler {
|
|||
|
||||
clear()
|
||||
{
|
||||
if (! this.wrapper.classList.contains('woocommerce-error')) {
|
||||
if (this.messagesList === null) {
|
||||
return;
|
||||
}
|
||||
this.wrapper.classList.remove('woocommerce-error');
|
||||
this.wrapper.innerText = '';
|
||||
|
||||
this.messagesList.innerHTML = '';
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -29,6 +29,15 @@ class PPECHelper {
|
|||
const PPEC_SETTINGS_OPTION_NAME = 'woocommerce_ppec_paypal_settings';
|
||||
|
||||
|
||||
/**
|
||||
* Checks if the PayPal Express Checkout plugin was configured previously.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function is_plugin_configured() {
|
||||
return is_array( get_option( self::PPEC_SETTINGS_OPTION_NAME ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the PayPal Express Checkout plugin is active.
|
||||
*
|
||||
|
|
|
@ -37,9 +37,11 @@ class Renderer {
|
|||
foreach ( $items as $item ) {
|
||||
?>
|
||||
<tr>
|
||||
<td data-export-label="<?php echo esc_attr( $item['label'] ); ?>"><?php echo esc_attr( $item['label'] ); ?></td>
|
||||
<td data-export-label="<?php echo esc_attr( $item['exported_label'] ?? $item['label'] ); ?>">
|
||||
<?php echo esc_attr( $item['label'] ); ?>
|
||||
</td>
|
||||
<td class="help"><?php echo wc_help_tip( $item['description'] ); ?></td>
|
||||
<td><?php echo esc_attr( $item['value'] ); ?></td>
|
||||
<td><?php echo wp_kses_post( $item['value'] ); ?></td>
|
||||
</tr>
|
||||
<?php
|
||||
}
|
||||
|
|
|
@ -15,10 +15,14 @@ use Interop\Container\ServiceProviderInterface;
|
|||
use Psr\Container\ContainerInterface;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Authentication\Bearer;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Authentication\PayPalBearer;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\BillingAgreementsEndpoint;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Helper\CurrencySupport;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Helper\DccApplies;
|
||||
use WooCommerce\PayPalCommerce\Button\Helper\MessagesApply;
|
||||
use WooCommerce\PayPalCommerce\Compat\PPEC\PPECHelper;
|
||||
use WooCommerce\PayPalCommerce\Onboarding\State;
|
||||
use WooCommerce\PayPalCommerce\Webhooks\WebhookInfoStorage;
|
||||
|
||||
/**
|
||||
* Class StatusReportModule
|
||||
|
@ -44,6 +48,8 @@ class StatusReportModule implements ModuleInterface {
|
|||
add_action(
|
||||
'woocommerce_system_status_report',
|
||||
function () use ( $c ) {
|
||||
$settings = $c->get( 'wcgateway.settings' );
|
||||
assert( $settings instanceof ContainerInterface );
|
||||
|
||||
/* @var State $state The state. */
|
||||
$state = $c->get( 'onboarding.state' );
|
||||
|
@ -51,44 +57,102 @@ class StatusReportModule implements ModuleInterface {
|
|||
/* @var Bearer $bearer The bearer. */
|
||||
$bearer = $c->get( 'api.bearer' );
|
||||
|
||||
$currency_support = $c->get( 'api.helpers.currency-support' );
|
||||
assert( $currency_support instanceof CurrencySupport );
|
||||
|
||||
/* @var DccApplies $dcc_applies The ddc applies. */
|
||||
$dcc_applies = $c->get( 'api.helpers.dccapplies' );
|
||||
|
||||
/* @var MessagesApply $messages_apply The messages apply. */
|
||||
$messages_apply = $c->get( 'button.helper.messages-apply' );
|
||||
|
||||
$last_webhook_storage = $c->get( 'webhook.last-webhook-storage' );
|
||||
assert( $last_webhook_storage instanceof WebhookInfoStorage );
|
||||
|
||||
$billing_agreements_endpoint = $c->get( 'api.endpoint.billing-agreements' );
|
||||
assert( $billing_agreements_endpoint instanceof BillingAgreementsEndpoint );
|
||||
|
||||
/* @var Renderer $renderer The renderer. */
|
||||
$renderer = $c->get( 'status-report.renderer' );
|
||||
|
||||
$had_ppec_plugin = PPECHelper::is_plugin_configured();
|
||||
|
||||
$items = array(
|
||||
array(
|
||||
'label' => esc_html__( 'Onboarded', 'woocommerce-paypal-payments' ),
|
||||
'description' => esc_html__( 'Whether PayPal account is correctly configured or not.', 'woocommerce-paypal-payments' ),
|
||||
'value' => $this->onboarded( $bearer, $state ),
|
||||
'label' => esc_html__( 'Onboarded', 'woocommerce-paypal-payments' ),
|
||||
'exported_label' => 'Onboarded',
|
||||
'description' => esc_html__( 'Whether PayPal account is correctly configured or not.', 'woocommerce-paypal-payments' ),
|
||||
'value' => $this->bool_to_html(
|
||||
$this->onboarded( $bearer, $state )
|
||||
),
|
||||
),
|
||||
array(
|
||||
'label' => esc_html__( 'Shop country code', 'woocommerce-paypal-payments' ),
|
||||
'description' => esc_html__( 'Country / State value on Settings / General / Store Address.', 'woocommerce-paypal-payments' ),
|
||||
'value' => wc_get_base_location()['country'],
|
||||
'label' => esc_html__( 'Shop country code', 'woocommerce-paypal-payments' ),
|
||||
'exported_label' => 'Shop country code',
|
||||
'description' => esc_html__( 'Country / State value on Settings / General / Store Address.', 'woocommerce-paypal-payments' ),
|
||||
'value' => wc_get_base_location()['country'],
|
||||
),
|
||||
array(
|
||||
'label' => esc_html__( 'PayPal card processing available in country', 'woocommerce-paypal-payments' ),
|
||||
'description' => esc_html__( 'Whether PayPal card processing is available in country or not.', 'woocommerce-paypal-payments' ),
|
||||
'value' => $dcc_applies->for_country_currency()
|
||||
? esc_html__( 'Yes', 'woocommerce-paypal-payments' )
|
||||
: esc_html__( 'No', 'woocommerce-paypal-payments' ),
|
||||
'label' => esc_html__( 'WooCommerce currency supported', 'woocommerce-paypal-payments' ),
|
||||
'exported_label' => 'WooCommerce currency supported',
|
||||
'description' => esc_html__( 'Whether PayPal supports the default store currency or not.', 'woocommerce-paypal-payments' ),
|
||||
'value' => $this->bool_to_html(
|
||||
$currency_support->supports_wc_currency()
|
||||
),
|
||||
),
|
||||
array(
|
||||
'label' => esc_html__( 'Pay Later messaging available in country', 'woocommerce-paypal-payments' ),
|
||||
'description' => esc_html__( 'Whether Pay Later is available in country or not.', 'woocommerce-paypal-payments' ),
|
||||
'value' => $messages_apply->for_country()
|
||||
? esc_html__( 'Yes', 'woocommerce-paypal-payments' )
|
||||
: esc_html__( 'No', 'woocommerce-paypal-payments' ),
|
||||
'label' => esc_html__( 'PayPal card processing available in country', 'woocommerce-paypal-payments' ),
|
||||
'exported_label' => 'PayPal card processing available in country',
|
||||
'description' => esc_html__( 'Whether PayPal card processing is available in country or not.', 'woocommerce-paypal-payments' ),
|
||||
'value' => $this->bool_to_html(
|
||||
$dcc_applies->for_country_currency()
|
||||
),
|
||||
),
|
||||
array(
|
||||
'label' => esc_html__( 'Vault enabled', 'woocommerce-paypal-payments' ),
|
||||
'description' => esc_html__( 'Whether vaulting is enabled on PayPal account or not.', 'woocommerce-paypal-payments' ),
|
||||
'value' => $this->vault_enabled( $bearer ),
|
||||
'label' => esc_html__( 'Pay Later messaging available in country', 'woocommerce-paypal-payments' ),
|
||||
'exported_label' => 'Pay Later messaging available in country',
|
||||
'description' => esc_html__( 'Whether Pay Later is available in country or not.', 'woocommerce-paypal-payments' ),
|
||||
'value' => $this->bool_to_html(
|
||||
$messages_apply->for_country()
|
||||
),
|
||||
),
|
||||
array(
|
||||
'label' => esc_html__( 'Webhook status', 'woocommerce-paypal-payments' ),
|
||||
'exported_label' => 'Webhook status',
|
||||
'description' => esc_html__( 'Whether we received webhooks successfully.', 'woocommerce-paypal-payments' ),
|
||||
'value' => $this->bool_to_html( ! $last_webhook_storage->is_empty() ),
|
||||
),
|
||||
array(
|
||||
'label' => esc_html__( 'Vault enabled', 'woocommerce-paypal-payments' ),
|
||||
'exported_label' => 'Vault enabled',
|
||||
'description' => esc_html__( 'Whether vaulting is enabled on PayPal account or not.', 'woocommerce-paypal-payments' ),
|
||||
'value' => $this->bool_to_html(
|
||||
$this->vault_enabled( $bearer )
|
||||
),
|
||||
),
|
||||
array(
|
||||
'label' => esc_html__( 'Logging enabled', 'woocommerce-paypal-payments' ),
|
||||
'exported_label' => 'Logging enabled',
|
||||
'description' => esc_html__( 'Whether logging of plugin events and errors is enabled.', 'woocommerce-paypal-payments' ),
|
||||
'value' => $this->bool_to_html(
|
||||
$settings->has( 'logging_enabled' ) && $settings->get( 'logging_enabled' )
|
||||
),
|
||||
),
|
||||
array(
|
||||
'label' => esc_html__( 'Reference Transactions', 'woocommerce-paypal-payments' ),
|
||||
'exported_label' => 'Reference Transactions',
|
||||
'description' => esc_html__( 'Whether Reference Transactions are enabled for the connected account', 'woocommerce-paypal-payments' ),
|
||||
'value' => $this->bool_to_html(
|
||||
$this->reference_transaction_enabled( $billing_agreements_endpoint )
|
||||
),
|
||||
),
|
||||
array(
|
||||
'label' => esc_html__( 'Used PayPal Checkout plugin', 'woocommerce-paypal-payments' ),
|
||||
'exported_label' => 'Used PayPal Checkout plugin',
|
||||
'description' => esc_html__( 'Whether the PayPal Checkout Gateway plugin was configured previously or not', 'woocommerce-paypal-payments' ),
|
||||
'value' => $this->bool_to_html(
|
||||
$had_ppec_plugin
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
|
@ -112,37 +176,56 @@ class StatusReportModule implements ModuleInterface {
|
|||
*
|
||||
* @param Bearer $bearer The bearer.
|
||||
* @param State $state The state.
|
||||
* @return string
|
||||
* @return bool
|
||||
*/
|
||||
private function onboarded( $bearer, $state ): string {
|
||||
private function onboarded( Bearer $bearer, State $state ): bool {
|
||||
try {
|
||||
$token = $bearer->bearer();
|
||||
} catch ( RuntimeException $exception ) {
|
||||
return esc_html__( 'No', 'woocommerce-paypal-payments' );
|
||||
return false;
|
||||
}
|
||||
|
||||
$current_state = $state->current_state();
|
||||
if ( $token->is_valid() && $current_state === $state::STATE_ONBOARDED ) {
|
||||
return esc_html__( 'Yes', 'woocommerce-paypal-payments' );
|
||||
}
|
||||
|
||||
return esc_html__( 'No', 'woocommerce-paypal-payments' );
|
||||
return $token->is_valid() && $current_state === $state::STATE_ONBOARDED;
|
||||
}
|
||||
|
||||
/**
|
||||
* It returns whether vaulting is enabled or not.
|
||||
*
|
||||
* @param Bearer $bearer The bearer.
|
||||
* @return string
|
||||
* @return bool
|
||||
*/
|
||||
private function vault_enabled( $bearer ) {
|
||||
private function vault_enabled( Bearer $bearer ): bool {
|
||||
try {
|
||||
$token = $bearer->bearer();
|
||||
return $token->vaulting_available()
|
||||
? esc_html__( 'Yes', 'woocommerce-paypal-payments' )
|
||||
: esc_html__( 'No', 'woocommerce-paypal-payments' );
|
||||
return $token->vaulting_available();
|
||||
} catch ( RuntimeException $exception ) {
|
||||
return esc_html__( 'No', 'woocommerce-paypal-payments' );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if reference transactions are enabled in account.
|
||||
*
|
||||
* @param BillingAgreementsEndpoint $billing_agreements_endpoint The endpoint.
|
||||
*/
|
||||
private function reference_transaction_enabled( BillingAgreementsEndpoint $billing_agreements_endpoint ): bool {
|
||||
try {
|
||||
return $billing_agreements_endpoint->reference_transaction_enabled();
|
||||
} catch ( RuntimeException $exception ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the bool value to "yes" icon or dash.
|
||||
*
|
||||
* @param bool $value The value.
|
||||
* @return string
|
||||
*/
|
||||
private function bool_to_html( bool $value ): string {
|
||||
return $value
|
||||
? '<mark class="yes"><span class="dashicons dashicons-yes"></span></mark>'
|
||||
: '<mark class="no">–</mark>';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,11 +32,13 @@ return array(
|
|||
$factory = $container->get( 'api.factory.webhook' );
|
||||
$endpoint = $container->get( 'api.endpoint.webhook' );
|
||||
$rest_endpoint = $container->get( 'webhook.endpoint.controller' );
|
||||
$last_webhook_storage = $container->get( 'webhook.last-webhook-storage' );
|
||||
$logger = $container->get( 'woocommerce.logger.woocommerce' );
|
||||
return new WebhookRegistrar(
|
||||
$factory,
|
||||
$endpoint,
|
||||
$rest_endpoint,
|
||||
$last_webhook_storage,
|
||||
$logger
|
||||
);
|
||||
},
|
||||
|
@ -48,6 +50,7 @@ return array(
|
|||
$verify_request = ! defined( 'PAYPAL_WEBHOOK_REQUEST_VERIFICATION' ) || PAYPAL_WEBHOOK_REQUEST_VERIFICATION;
|
||||
$webhook_event_factory = $container->get( 'api.factory.webhook-event' );
|
||||
$simulation = $container->get( 'webhook.status.simulation' );
|
||||
$last_webhook_storage = $container->get( 'webhook.last-webhook-storage' );
|
||||
|
||||
return new IncomingWebhookEndpoint(
|
||||
$webhook_endpoint,
|
||||
|
@ -56,6 +59,7 @@ return array(
|
|||
$verify_request,
|
||||
$webhook_event_factory,
|
||||
$simulation,
|
||||
$last_webhook_storage,
|
||||
... $handler
|
||||
);
|
||||
},
|
||||
|
@ -183,6 +187,13 @@ return array(
|
|||
);
|
||||
},
|
||||
|
||||
'webhook.last-webhook-storage' => static function ( ContainerInterface $container ): WebhookInfoStorage {
|
||||
return new WebhookInfoStorage( $container->get( 'webhook.last-webhook-storage.key' ) );
|
||||
},
|
||||
'webhook.last-webhook-storage.key' => static function ( ContainerInterface $container ): string {
|
||||
return 'ppcp-last-webhook';
|
||||
},
|
||||
|
||||
'webhook.module-url' => static function ( ContainerInterface $container ): string {
|
||||
return plugins_url(
|
||||
'/modules/ppcp-webhooks/',
|
||||
|
|
|
@ -76,6 +76,13 @@ class IncomingWebhookEndpoint {
|
|||
*/
|
||||
private $simulation;
|
||||
|
||||
/**
|
||||
* The last webhook info storage.
|
||||
*
|
||||
* @var WebhookInfoStorage
|
||||
*/
|
||||
private $last_webhook_storage;
|
||||
|
||||
/**
|
||||
* IncomingWebhookEndpoint constructor.
|
||||
*
|
||||
|
@ -85,6 +92,7 @@ class IncomingWebhookEndpoint {
|
|||
* @param bool $verify_request Whether requests need to be verified or not.
|
||||
* @param WebhookEventFactory $webhook_event_factory The webhook event factory.
|
||||
* @param WebhookSimulation $simulation The simulation handler.
|
||||
* @param WebhookInfoStorage $last_webhook_storage The last webhook info storage.
|
||||
* @param RequestHandler ...$handlers The handlers, which process a request in the end.
|
||||
*/
|
||||
public function __construct(
|
||||
|
@ -94,6 +102,7 @@ class IncomingWebhookEndpoint {
|
|||
bool $verify_request,
|
||||
WebhookEventFactory $webhook_event_factory,
|
||||
WebhookSimulation $simulation,
|
||||
WebhookInfoStorage $last_webhook_storage,
|
||||
RequestHandler ...$handlers
|
||||
) {
|
||||
|
||||
|
@ -103,6 +112,7 @@ class IncomingWebhookEndpoint {
|
|||
$this->logger = $logger;
|
||||
$this->verify_request = $verify_request;
|
||||
$this->webhook_event_factory = $webhook_event_factory;
|
||||
$this->last_webhook_storage = $last_webhook_storage;
|
||||
$this->simulation = $simulation;
|
||||
}
|
||||
|
||||
|
@ -176,6 +186,8 @@ class IncomingWebhookEndpoint {
|
|||
public function handle_request( \WP_REST_Request $request ): \WP_REST_Response {
|
||||
$event = $this->event_from_request( $request );
|
||||
|
||||
$this->last_webhook_storage->save( $event );
|
||||
|
||||
if ( $this->simulation->is_simulation_event( $event ) ) {
|
||||
$this->logger->info( 'Received simulated webhook.' );
|
||||
$this->simulation->receive( $event );
|
||||
|
|
76
modules/ppcp-webhooks/src/WebhookInfoStorage.php
Normal file
76
modules/ppcp-webhooks/src/WebhookInfoStorage.php
Normal file
|
@ -0,0 +1,76 @@
|
|||
<?php
|
||||
/**
|
||||
* Stores the info about webhook events.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\Webhooks
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\Webhooks;
|
||||
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\WebhookEvent;
|
||||
|
||||
/**
|
||||
* Class WebhookInfoStorage
|
||||
*/
|
||||
class WebhookInfoStorage {
|
||||
|
||||
/**
|
||||
* The WP option key.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $key;
|
||||
|
||||
/**
|
||||
* WebhookInfoStorage constructor.
|
||||
*
|
||||
* @param string $key The WP option key.
|
||||
*/
|
||||
public function __construct(
|
||||
string $key
|
||||
) {
|
||||
$this->key = $key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the info about webhook event.
|
||||
*
|
||||
* @param WebhookEvent $webhook_event The webhook event to save.
|
||||
*/
|
||||
public function save( WebhookEvent $webhook_event ): void {
|
||||
$data = array(
|
||||
'id' => $webhook_event->id(),
|
||||
'received_time' => time(),
|
||||
);
|
||||
|
||||
update_option( $this->key, $data );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the stored data or null.
|
||||
*/
|
||||
public function get_data(): ?array {
|
||||
$data = get_option( $this->key );
|
||||
if ( ! $data || ! is_array( $data ) ) {
|
||||
return null;
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if there is any stored data.
|
||||
*/
|
||||
public function is_empty(): bool {
|
||||
$data = get_option( $this->key );
|
||||
return ! $data || ! is_array( $data );
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the stored data.
|
||||
*/
|
||||
public function clear(): void {
|
||||
delete_option( $this->key );
|
||||
}
|
||||
}
|
|
@ -44,6 +44,13 @@ class WebhookRegistrar {
|
|||
*/
|
||||
private $rest_endpoint;
|
||||
|
||||
/**
|
||||
* The last webhook info storage.
|
||||
*
|
||||
* @var WebhookInfoStorage
|
||||
*/
|
||||
private $last_webhook_storage;
|
||||
|
||||
/**
|
||||
* The logger.
|
||||
*
|
||||
|
@ -57,19 +64,22 @@ class WebhookRegistrar {
|
|||
* @param WebhookFactory $webhook_factory The Webhook factory.
|
||||
* @param WebhookEndpoint $endpoint The Webhook endpoint.
|
||||
* @param IncomingWebhookEndpoint $rest_endpoint The WordPress Rest API endpoint.
|
||||
* @param WebhookInfoStorage $last_webhook_storage The last webhook info storage.
|
||||
* @param LoggerInterface $logger The logger.
|
||||
*/
|
||||
public function __construct(
|
||||
WebhookFactory $webhook_factory,
|
||||
WebhookEndpoint $endpoint,
|
||||
IncomingWebhookEndpoint $rest_endpoint,
|
||||
WebhookInfoStorage $last_webhook_storage,
|
||||
LoggerInterface $logger
|
||||
) {
|
||||
|
||||
$this->webhook_factory = $webhook_factory;
|
||||
$this->endpoint = $endpoint;
|
||||
$this->rest_endpoint = $rest_endpoint;
|
||||
$this->logger = $logger;
|
||||
$this->webhook_factory = $webhook_factory;
|
||||
$this->endpoint = $endpoint;
|
||||
$this->rest_endpoint = $rest_endpoint;
|
||||
$this->last_webhook_storage = $last_webhook_storage;
|
||||
$this->logger = $logger;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -92,6 +102,7 @@ class WebhookRegistrar {
|
|||
self::KEY,
|
||||
$created->to_array()
|
||||
);
|
||||
$this->last_webhook_storage->clear();
|
||||
$this->logger->info( 'Webhooks subscribed.' );
|
||||
return true;
|
||||
} catch ( RuntimeException $error ) {
|
||||
|
@ -120,6 +131,7 @@ class WebhookRegistrar {
|
|||
|
||||
if ( $success ) {
|
||||
delete_option( self::KEY );
|
||||
$this->last_webhook_storage->clear();
|
||||
$this->logger->info( 'Webhooks deleted.' );
|
||||
}
|
||||
return $success;
|
||||
|
|
|
@ -12,20 +12,23 @@ class RendererTest extends TestCase
|
|||
{
|
||||
$items = [
|
||||
[
|
||||
'label' => 'Foo',
|
||||
'label' => 'Translated Foo',
|
||||
'exported_label' => 'Foo',
|
||||
'description' => 'Bar',
|
||||
'value' => 'Baz'
|
||||
],
|
||||
];
|
||||
|
||||
when('esc_attr')->returnArg();
|
||||
when('wp_kses_post')->returnArg();
|
||||
when('wc_help_tip')->returnArg();
|
||||
|
||||
$testee = new Renderer();
|
||||
$result = $testee->render('Some title here', $items);
|
||||
|
||||
self::assertStringContainsString('<h2>Some title here</h2>', $result);
|
||||
self::assertStringContainsString('<td data-export-label="Foo">Foo</td>', $result);
|
||||
self::assertStringContainsString('data-export-label="Foo"', $result);
|
||||
self::assertStringContainsString('Translated Foo', $result);
|
||||
self::assertStringContainsString('<td class="help">Bar</td>', $result);
|
||||
self::assertStringContainsString('<td>Baz</td>', $result);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue