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 Psr\Container\ContainerInterface;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Authentication\Bearer;
|
use WooCommerce\PayPalCommerce\ApiClient\Authentication\Bearer;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Authentication\PayPalBearer;
|
use WooCommerce\PayPalCommerce\ApiClient\Authentication\PayPalBearer;
|
||||||
|
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\BillingAgreementsEndpoint;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\IdentityToken;
|
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\IdentityToken;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\LoginSeller;
|
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\LoginSeller;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\OrderEndpoint;
|
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\WebhookEventFactory;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Factory\WebhookFactory;
|
use WooCommerce\PayPalCommerce\ApiClient\Factory\WebhookFactory;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Helper\Cache;
|
use WooCommerce\PayPalCommerce\ApiClient\Helper\Cache;
|
||||||
|
use WooCommerce\PayPalCommerce\ApiClient\Helper\CurrencySupport;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Helper\DccApplies;
|
use WooCommerce\PayPalCommerce\ApiClient\Helper\DccApplies;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Repository\ApplicationContextRepository;
|
use WooCommerce\PayPalCommerce\ApiClient\Repository\ApplicationContextRepository;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Repository\CartRepository;
|
use WooCommerce\PayPalCommerce\ApiClient\Repository\CartRepository;
|
||||||
|
@ -190,6 +192,13 @@ return array(
|
||||||
$subscription_helper
|
$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 {
|
'api.repository.paypal-request-id' => static function( ContainerInterface $container ) : PayPalRequestIdRepository {
|
||||||
return new PayPalRequestIdRepository();
|
return new PayPalRequestIdRepository();
|
||||||
},
|
},
|
||||||
|
@ -302,4 +311,7 @@ return array(
|
||||||
'api.helpers.dccapplies' => static function ( ContainerInterface $container ) : DccApplies {
|
'api.helpers.dccapplies' => static function ( ContainerInterface $container ) : DccApplies {
|
||||||
return new 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()
|
clear()
|
||||||
{
|
{
|
||||||
if (! this.wrapper.classList.contains('woocommerce-error')) {
|
if (this.messagesList === null) {
|
||||||
return;
|
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';
|
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.
|
* Checks if the PayPal Express Checkout plugin is active.
|
||||||
*
|
*
|
||||||
|
|
|
@ -37,9 +37,11 @@ class Renderer {
|
||||||
foreach ( $items as $item ) {
|
foreach ( $items as $item ) {
|
||||||
?>
|
?>
|
||||||
<tr>
|
<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 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>
|
</tr>
|
||||||
<?php
|
<?php
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,10 +15,14 @@ use Interop\Container\ServiceProviderInterface;
|
||||||
use Psr\Container\ContainerInterface;
|
use Psr\Container\ContainerInterface;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Authentication\Bearer;
|
use WooCommerce\PayPalCommerce\ApiClient\Authentication\Bearer;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Authentication\PayPalBearer;
|
use WooCommerce\PayPalCommerce\ApiClient\Authentication\PayPalBearer;
|
||||||
|
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\BillingAgreementsEndpoint;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
|
use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
|
||||||
|
use WooCommerce\PayPalCommerce\ApiClient\Helper\CurrencySupport;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Helper\DccApplies;
|
use WooCommerce\PayPalCommerce\ApiClient\Helper\DccApplies;
|
||||||
use WooCommerce\PayPalCommerce\Button\Helper\MessagesApply;
|
use WooCommerce\PayPalCommerce\Button\Helper\MessagesApply;
|
||||||
|
use WooCommerce\PayPalCommerce\Compat\PPEC\PPECHelper;
|
||||||
use WooCommerce\PayPalCommerce\Onboarding\State;
|
use WooCommerce\PayPalCommerce\Onboarding\State;
|
||||||
|
use WooCommerce\PayPalCommerce\Webhooks\WebhookInfoStorage;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class StatusReportModule
|
* Class StatusReportModule
|
||||||
|
@ -44,6 +48,8 @@ class StatusReportModule implements ModuleInterface {
|
||||||
add_action(
|
add_action(
|
||||||
'woocommerce_system_status_report',
|
'woocommerce_system_status_report',
|
||||||
function () use ( $c ) {
|
function () use ( $c ) {
|
||||||
|
$settings = $c->get( 'wcgateway.settings' );
|
||||||
|
assert( $settings instanceof ContainerInterface );
|
||||||
|
|
||||||
/* @var State $state The state. */
|
/* @var State $state The state. */
|
||||||
$state = $c->get( 'onboarding.state' );
|
$state = $c->get( 'onboarding.state' );
|
||||||
|
@ -51,44 +57,102 @@ class StatusReportModule implements ModuleInterface {
|
||||||
/* @var Bearer $bearer The bearer. */
|
/* @var Bearer $bearer The bearer. */
|
||||||
$bearer = $c->get( 'api.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. */
|
/* @var DccApplies $dcc_applies The ddc applies. */
|
||||||
$dcc_applies = $c->get( 'api.helpers.dccapplies' );
|
$dcc_applies = $c->get( 'api.helpers.dccapplies' );
|
||||||
|
|
||||||
/* @var MessagesApply $messages_apply The messages apply. */
|
/* @var MessagesApply $messages_apply The messages apply. */
|
||||||
$messages_apply = $c->get( 'button.helper.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. */
|
/* @var Renderer $renderer The renderer. */
|
||||||
$renderer = $c->get( 'status-report.renderer' );
|
$renderer = $c->get( 'status-report.renderer' );
|
||||||
|
|
||||||
|
$had_ppec_plugin = PPECHelper::is_plugin_configured();
|
||||||
|
|
||||||
$items = array(
|
$items = array(
|
||||||
array(
|
array(
|
||||||
'label' => esc_html__( 'Onboarded', 'woocommerce-paypal-payments' ),
|
'label' => esc_html__( 'Onboarded', 'woocommerce-paypal-payments' ),
|
||||||
|
'exported_label' => 'Onboarded',
|
||||||
'description' => esc_html__( 'Whether PayPal account is correctly configured or not.', 'woocommerce-paypal-payments' ),
|
'description' => esc_html__( 'Whether PayPal account is correctly configured or not.', 'woocommerce-paypal-payments' ),
|
||||||
'value' => $this->onboarded( $bearer, $state ),
|
'value' => $this->bool_to_html(
|
||||||
|
$this->onboarded( $bearer, $state )
|
||||||
|
),
|
||||||
),
|
),
|
||||||
array(
|
array(
|
||||||
'label' => esc_html__( 'Shop country code', 'woocommerce-paypal-payments' ),
|
'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' ),
|
'description' => esc_html__( 'Country / State value on Settings / General / Store Address.', 'woocommerce-paypal-payments' ),
|
||||||
'value' => wc_get_base_location()['country'],
|
'value' => wc_get_base_location()['country'],
|
||||||
),
|
),
|
||||||
|
array(
|
||||||
|
'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(
|
array(
|
||||||
'label' => esc_html__( 'PayPal card processing available in country', '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' ),
|
'description' => esc_html__( 'Whether PayPal card processing is available in country or not.', 'woocommerce-paypal-payments' ),
|
||||||
'value' => $dcc_applies->for_country_currency()
|
'value' => $this->bool_to_html(
|
||||||
? esc_html__( 'Yes', 'woocommerce-paypal-payments' )
|
$dcc_applies->for_country_currency()
|
||||||
: esc_html__( 'No', 'woocommerce-paypal-payments' ),
|
),
|
||||||
),
|
),
|
||||||
array(
|
array(
|
||||||
'label' => esc_html__( 'Pay Later messaging available in country', 'woocommerce-paypal-payments' ),
|
'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' ),
|
'description' => esc_html__( 'Whether Pay Later is available in country or not.', 'woocommerce-paypal-payments' ),
|
||||||
'value' => $messages_apply->for_country()
|
'value' => $this->bool_to_html(
|
||||||
? esc_html__( 'Yes', 'woocommerce-paypal-payments' )
|
$messages_apply->for_country()
|
||||||
: esc_html__( 'No', 'woocommerce-paypal-payments' ),
|
),
|
||||||
|
),
|
||||||
|
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(
|
array(
|
||||||
'label' => esc_html__( 'Vault enabled', 'woocommerce-paypal-payments' ),
|
'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' ),
|
'description' => esc_html__( 'Whether vaulting is enabled on PayPal account or not.', 'woocommerce-paypal-payments' ),
|
||||||
'value' => $this->vault_enabled( $bearer ),
|
'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 Bearer $bearer The bearer.
|
||||||
* @param State $state The state.
|
* @param State $state The state.
|
||||||
* @return string
|
* @return bool
|
||||||
*/
|
*/
|
||||||
private function onboarded( $bearer, $state ): string {
|
private function onboarded( Bearer $bearer, State $state ): bool {
|
||||||
try {
|
try {
|
||||||
$token = $bearer->bearer();
|
$token = $bearer->bearer();
|
||||||
} catch ( RuntimeException $exception ) {
|
} catch ( RuntimeException $exception ) {
|
||||||
return esc_html__( 'No', 'woocommerce-paypal-payments' );
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$current_state = $state->current_state();
|
$current_state = $state->current_state();
|
||||||
if ( $token->is_valid() && $current_state === $state::STATE_ONBOARDED ) {
|
return $token->is_valid() && $current_state === $state::STATE_ONBOARDED;
|
||||||
return esc_html__( 'Yes', 'woocommerce-paypal-payments' );
|
|
||||||
}
|
|
||||||
|
|
||||||
return esc_html__( 'No', 'woocommerce-paypal-payments' );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* It returns whether vaulting is enabled or not.
|
* It returns whether vaulting is enabled or not.
|
||||||
*
|
*
|
||||||
* @param Bearer $bearer The bearer.
|
* @param Bearer $bearer The bearer.
|
||||||
* @return string
|
* @return bool
|
||||||
*/
|
*/
|
||||||
private function vault_enabled( $bearer ) {
|
private function vault_enabled( Bearer $bearer ): bool {
|
||||||
try {
|
try {
|
||||||
$token = $bearer->bearer();
|
$token = $bearer->bearer();
|
||||||
return $token->vaulting_available()
|
return $token->vaulting_available();
|
||||||
? esc_html__( 'Yes', 'woocommerce-paypal-payments' )
|
|
||||||
: esc_html__( 'No', 'woocommerce-paypal-payments' );
|
|
||||||
} catch ( RuntimeException $exception ) {
|
} 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' );
|
$factory = $container->get( 'api.factory.webhook' );
|
||||||
$endpoint = $container->get( 'api.endpoint.webhook' );
|
$endpoint = $container->get( 'api.endpoint.webhook' );
|
||||||
$rest_endpoint = $container->get( 'webhook.endpoint.controller' );
|
$rest_endpoint = $container->get( 'webhook.endpoint.controller' );
|
||||||
|
$last_webhook_storage = $container->get( 'webhook.last-webhook-storage' );
|
||||||
$logger = $container->get( 'woocommerce.logger.woocommerce' );
|
$logger = $container->get( 'woocommerce.logger.woocommerce' );
|
||||||
return new WebhookRegistrar(
|
return new WebhookRegistrar(
|
||||||
$factory,
|
$factory,
|
||||||
$endpoint,
|
$endpoint,
|
||||||
$rest_endpoint,
|
$rest_endpoint,
|
||||||
|
$last_webhook_storage,
|
||||||
$logger
|
$logger
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
@ -48,6 +50,7 @@ return array(
|
||||||
$verify_request = ! defined( 'PAYPAL_WEBHOOK_REQUEST_VERIFICATION' ) || PAYPAL_WEBHOOK_REQUEST_VERIFICATION;
|
$verify_request = ! defined( 'PAYPAL_WEBHOOK_REQUEST_VERIFICATION' ) || PAYPAL_WEBHOOK_REQUEST_VERIFICATION;
|
||||||
$webhook_event_factory = $container->get( 'api.factory.webhook-event' );
|
$webhook_event_factory = $container->get( 'api.factory.webhook-event' );
|
||||||
$simulation = $container->get( 'webhook.status.simulation' );
|
$simulation = $container->get( 'webhook.status.simulation' );
|
||||||
|
$last_webhook_storage = $container->get( 'webhook.last-webhook-storage' );
|
||||||
|
|
||||||
return new IncomingWebhookEndpoint(
|
return new IncomingWebhookEndpoint(
|
||||||
$webhook_endpoint,
|
$webhook_endpoint,
|
||||||
|
@ -56,6 +59,7 @@ return array(
|
||||||
$verify_request,
|
$verify_request,
|
||||||
$webhook_event_factory,
|
$webhook_event_factory,
|
||||||
$simulation,
|
$simulation,
|
||||||
|
$last_webhook_storage,
|
||||||
... $handler
|
... $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 {
|
'webhook.module-url' => static function ( ContainerInterface $container ): string {
|
||||||
return plugins_url(
|
return plugins_url(
|
||||||
'/modules/ppcp-webhooks/',
|
'/modules/ppcp-webhooks/',
|
||||||
|
|
|
@ -76,6 +76,13 @@ class IncomingWebhookEndpoint {
|
||||||
*/
|
*/
|
||||||
private $simulation;
|
private $simulation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The last webhook info storage.
|
||||||
|
*
|
||||||
|
* @var WebhookInfoStorage
|
||||||
|
*/
|
||||||
|
private $last_webhook_storage;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* IncomingWebhookEndpoint constructor.
|
* IncomingWebhookEndpoint constructor.
|
||||||
*
|
*
|
||||||
|
@ -85,6 +92,7 @@ class IncomingWebhookEndpoint {
|
||||||
* @param bool $verify_request Whether requests need to be verified or not.
|
* @param bool $verify_request Whether requests need to be verified or not.
|
||||||
* @param WebhookEventFactory $webhook_event_factory The webhook event factory.
|
* @param WebhookEventFactory $webhook_event_factory The webhook event factory.
|
||||||
* @param WebhookSimulation $simulation The simulation handler.
|
* @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.
|
* @param RequestHandler ...$handlers The handlers, which process a request in the end.
|
||||||
*/
|
*/
|
||||||
public function __construct(
|
public function __construct(
|
||||||
|
@ -94,6 +102,7 @@ class IncomingWebhookEndpoint {
|
||||||
bool $verify_request,
|
bool $verify_request,
|
||||||
WebhookEventFactory $webhook_event_factory,
|
WebhookEventFactory $webhook_event_factory,
|
||||||
WebhookSimulation $simulation,
|
WebhookSimulation $simulation,
|
||||||
|
WebhookInfoStorage $last_webhook_storage,
|
||||||
RequestHandler ...$handlers
|
RequestHandler ...$handlers
|
||||||
) {
|
) {
|
||||||
|
|
||||||
|
@ -103,6 +112,7 @@ class IncomingWebhookEndpoint {
|
||||||
$this->logger = $logger;
|
$this->logger = $logger;
|
||||||
$this->verify_request = $verify_request;
|
$this->verify_request = $verify_request;
|
||||||
$this->webhook_event_factory = $webhook_event_factory;
|
$this->webhook_event_factory = $webhook_event_factory;
|
||||||
|
$this->last_webhook_storage = $last_webhook_storage;
|
||||||
$this->simulation = $simulation;
|
$this->simulation = $simulation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -176,6 +186,8 @@ class IncomingWebhookEndpoint {
|
||||||
public function handle_request( \WP_REST_Request $request ): \WP_REST_Response {
|
public function handle_request( \WP_REST_Request $request ): \WP_REST_Response {
|
||||||
$event = $this->event_from_request( $request );
|
$event = $this->event_from_request( $request );
|
||||||
|
|
||||||
|
$this->last_webhook_storage->save( $event );
|
||||||
|
|
||||||
if ( $this->simulation->is_simulation_event( $event ) ) {
|
if ( $this->simulation->is_simulation_event( $event ) ) {
|
||||||
$this->logger->info( 'Received simulated webhook.' );
|
$this->logger->info( 'Received simulated webhook.' );
|
||||||
$this->simulation->receive( $event );
|
$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;
|
private $rest_endpoint;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The last webhook info storage.
|
||||||
|
*
|
||||||
|
* @var WebhookInfoStorage
|
||||||
|
*/
|
||||||
|
private $last_webhook_storage;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The logger.
|
* The logger.
|
||||||
*
|
*
|
||||||
|
@ -57,18 +64,21 @@ class WebhookRegistrar {
|
||||||
* @param WebhookFactory $webhook_factory The Webhook factory.
|
* @param WebhookFactory $webhook_factory The Webhook factory.
|
||||||
* @param WebhookEndpoint $endpoint The Webhook endpoint.
|
* @param WebhookEndpoint $endpoint The Webhook endpoint.
|
||||||
* @param IncomingWebhookEndpoint $rest_endpoint The WordPress Rest API 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.
|
* @param LoggerInterface $logger The logger.
|
||||||
*/
|
*/
|
||||||
public function __construct(
|
public function __construct(
|
||||||
WebhookFactory $webhook_factory,
|
WebhookFactory $webhook_factory,
|
||||||
WebhookEndpoint $endpoint,
|
WebhookEndpoint $endpoint,
|
||||||
IncomingWebhookEndpoint $rest_endpoint,
|
IncomingWebhookEndpoint $rest_endpoint,
|
||||||
|
WebhookInfoStorage $last_webhook_storage,
|
||||||
LoggerInterface $logger
|
LoggerInterface $logger
|
||||||
) {
|
) {
|
||||||
|
|
||||||
$this->webhook_factory = $webhook_factory;
|
$this->webhook_factory = $webhook_factory;
|
||||||
$this->endpoint = $endpoint;
|
$this->endpoint = $endpoint;
|
||||||
$this->rest_endpoint = $rest_endpoint;
|
$this->rest_endpoint = $rest_endpoint;
|
||||||
|
$this->last_webhook_storage = $last_webhook_storage;
|
||||||
$this->logger = $logger;
|
$this->logger = $logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,6 +102,7 @@ class WebhookRegistrar {
|
||||||
self::KEY,
|
self::KEY,
|
||||||
$created->to_array()
|
$created->to_array()
|
||||||
);
|
);
|
||||||
|
$this->last_webhook_storage->clear();
|
||||||
$this->logger->info( 'Webhooks subscribed.' );
|
$this->logger->info( 'Webhooks subscribed.' );
|
||||||
return true;
|
return true;
|
||||||
} catch ( RuntimeException $error ) {
|
} catch ( RuntimeException $error ) {
|
||||||
|
@ -120,6 +131,7 @@ class WebhookRegistrar {
|
||||||
|
|
||||||
if ( $success ) {
|
if ( $success ) {
|
||||||
delete_option( self::KEY );
|
delete_option( self::KEY );
|
||||||
|
$this->last_webhook_storage->clear();
|
||||||
$this->logger->info( 'Webhooks deleted.' );
|
$this->logger->info( 'Webhooks deleted.' );
|
||||||
}
|
}
|
||||||
return $success;
|
return $success;
|
||||||
|
|
|
@ -12,20 +12,23 @@ class RendererTest extends TestCase
|
||||||
{
|
{
|
||||||
$items = [
|
$items = [
|
||||||
[
|
[
|
||||||
'label' => 'Foo',
|
'label' => 'Translated Foo',
|
||||||
|
'exported_label' => 'Foo',
|
||||||
'description' => 'Bar',
|
'description' => 'Bar',
|
||||||
'value' => 'Baz'
|
'value' => 'Baz'
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
|
||||||
when('esc_attr')->returnArg();
|
when('esc_attr')->returnArg();
|
||||||
|
when('wp_kses_post')->returnArg();
|
||||||
when('wc_help_tip')->returnArg();
|
when('wc_help_tip')->returnArg();
|
||||||
|
|
||||||
$testee = new Renderer();
|
$testee = new Renderer();
|
||||||
$result = $testee->render('Some title here', $items);
|
$result = $testee->render('Some title here', $items);
|
||||||
|
|
||||||
self::assertStringContainsString('<h2>Some title here</h2>', $result);
|
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 class="help">Bar</td>', $result);
|
||||||
self::assertStringContainsString('<td>Baz</td>', $result);
|
self::assertStringContainsString('<td>Baz</td>', $result);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue