Fix merge conflict

This commit is contained in:
dinamiko 2021-09-16 12:34:05 +02:00
commit 17de4ac1de
33 changed files with 946 additions and 341 deletions

View file

@ -36,6 +36,48 @@ trait RequestTrait {
$args['headers']['PayPal-Partner-Attribution-Id'] = 'Woo_PPCP';
}
return wp_remote_get( $url, $args );
$response = wp_remote_get( $url, $args );
$this->logger->debug( $this->request_response_string( $url, $args, $response ) );
return $response;
}
/**
* Returns request and response information as string.
*
* @param string $url The request URL.
* @param array $args The request arguments.
* @param array $response The response.
* @return string
*/
private function request_response_string( string $url, array $args, array $response ): string {
$method = $args['method'] ?? '';
$output = $method . ' ' . $url . "\n";
if ( isset( $args['body'] ) ) {
if ( ! in_array(
$url,
array(
trailingslashit( $this->host ) . 'v1/oauth2/token/',
trailingslashit( $this->host ) . 'v1/oauth2/token?grant_type=client_credentials',
),
true
) ) {
$output .= 'Request Body: ' . wc_print_r( $args['body'], true ) . "\n";
}
}
if ( isset( $response['headers']->getAll()['paypal-debug-id'] ) ) {
$output .= 'Response Debug ID: ' . $response['headers']->getAll()['paypal-debug-id'] . "\n";
}
if ( isset( $response['response'] ) ) {
$output .= 'Response: ' . wc_print_r( $response['response'], true ) . "\n";
if ( isset( $response['body'] )
&& isset( $response['response']['code'] )
&& ! in_array( $response['response']['code'], array( 200, 201, 202, 204 ), true ) ) {
$output .= 'Response Body: ' . wc_print_r( $response['body'], true ) . "\n";
}
}
return $output;
}
}

View file

@ -79,14 +79,14 @@ class WebhookEndpoint {
*
* @return Webhook
* @throws RuntimeException If the request fails.
* @throws PayPalApiException If the request fails.
*/
public function create( Webhook $hook ): Webhook {
/**
* An hook, which has an ID has already been created.
*/
// The hook was already created.
if ( $hook->id() ) {
return $hook;
}
$bearer = $this->bearer->bearer();
$url = trailingslashit( $this->host ) . 'v1/notifications/webhooks';
$args = array(
@ -100,36 +100,18 @@ class WebhookEndpoint {
$response = $this->request( $url, $args );
if ( is_wp_error( $response ) ) {
$error = new RuntimeException(
throw new RuntimeException(
__( 'Not able to create a webhook.', 'woocommerce-paypal-payments' )
);
$this->logger->log(
'warning',
$error->getMessage(),
array(
'args' => $args,
'response' => $response,
)
);
throw $error;
}
$json = json_decode( $response['body'] );
$status_code = (int) wp_remote_retrieve_response_code( $response );
if ( 201 !== $status_code ) {
$error = new PayPalApiException(
throw new PayPalApiException(
$json,
$status_code
);
$this->logger->log(
'warning',
$error->getMessage(),
array(
'args' => $args,
'response' => $response,
)
);
throw $error;
}
$hook = $this->webhook_factory->from_paypal_response( $json );
@ -160,18 +142,9 @@ class WebhookEndpoint {
$response = $this->request( $url, $args );
if ( is_wp_error( $response ) ) {
$error = new RuntimeException(
throw new RuntimeException(
__( 'Not able to delete the webhook.', 'woocommerce-paypal-payments' )
);
$this->logger->log(
'warning',
$error->getMessage(),
array(
'args' => $args,
'response' => $response,
)
);
throw $error;
}
return wp_remote_retrieve_response_code( $response ) === 204;
}

View file

@ -743,8 +743,7 @@ class SmartButton implements SmartButtonInterface {
'currency' => get_woocommerce_currency(),
'integration-date' => PAYPAL_INTEGRATION_DATE,
'components' => implode( ',', $this->components() ),
'vault' => $this->can_save_vault_token() ?
'true' : 'false',
'vault' => $this->can_save_vault_token() ? 'true' : 'false',
'commit' => is_checkout() ? 'true' : 'false',
'intent' => ( $this->settings->has( 'intent' ) ) ?
$this->settings->get( 'intent' ) : 'capture',
@ -757,11 +756,20 @@ class SmartButton implements SmartButtonInterface {
) {
$params['buyer-country'] = WC()->customer->get_billing_country();
}
$disable_funding = $this->settings->has( 'disable_funding' ) ?
$this->settings->get( 'disable_funding' ) : array();
$disable_funding = $this->settings->has( 'disable_funding' )
? $this->settings->get( 'disable_funding' )
: array();
if ( ! is_checkout() ) {
$disable_funding[] = 'card';
}
if ( is_checkout() && $this->settings->has( 'dcc_enabled' ) && $this->settings->get( 'dcc_enabled' ) ) {
$key = array_search( 'card', $disable_funding, true );
if ( false !== $key ) {
unset( $disable_funding[ $key ] );
}
}
if ( count( $disable_funding ) > 0 ) {
$params['disable-funding'] = implode( ',', array_unique( $disable_funding ) );

View file

@ -136,7 +136,7 @@ class LoginSellerEndpoint implements EndpointInterface {
$this->cache->delete( PayPalBearer::CACHE_KEY );
}
wp_schedule_single_event(
time() - 1,
time() + 5,
WebhookRegistrar::EVENT_HOOK
);
wp_send_json_success();

View file

@ -5,6 +5,8 @@
* @package WooCommerce\PayPalCommerce\WcGateway
*/
// phpcs:disable WordPress.Security.NonceVerification.Recommended
declare(strict_types=1);
namespace WooCommerce\PayPalCommerce\WcGateway;
@ -28,6 +30,7 @@ use Woocommerce\PayPalCommerce\WcGateway\Helper\DccProductStatus;
use Woocommerce\PayPalCommerce\WcGateway\Helper\SettingsStatus;
use WooCommerce\PayPalCommerce\WcGateway\Notice\AuthorizeOrderActionNotice;
use WooCommerce\PayPalCommerce\WcGateway\Notice\ConnectAdminNotice;
use WooCommerce\PayPalCommerce\WcGateway\Notice\DccWithoutPayPalAdminNotice;
use WooCommerce\PayPalCommerce\WcGateway\Processor\AuthorizedPaymentsProcessor;
use WooCommerce\PayPalCommerce\WcGateway\Processor\OrderProcessor;
use WooCommerce\PayPalCommerce\WcGateway\Processor\RefundProcessor;
@ -48,6 +51,7 @@ return array(
$state = $container->get( 'onboarding.state' );
$transaction_url_provider = $container->get( 'wcgateway.transaction-url-provider' );
$subscription_helper = $container->get( 'subscription.helper' );
$page_id = $container->get( 'wcgateway.current-ppcp-settings-page-id' );
return new PayPalGateway(
$settings_renderer,
$order_processor,
@ -58,7 +62,8 @@ return array(
$refund_processor,
$state,
$transaction_url_provider,
$subscription_helper
$subscription_helper,
$page_id
);
},
'wcgateway.credit-card-gateway' => static function ( $container ): CreditCardGateway {
@ -100,6 +105,33 @@ return array(
$settings = $container->get( 'wcgateway.settings' );
return new DisableGateways( $session_handler, $settings );
},
'wcgateway.is-wc-payments-page' => static function ( $container ): bool {
$page = isset( $_GET['page'] ) ? sanitize_text_field( wp_unslash( $_GET['page'] ) ) : '';
$tab = isset( $_GET['tab'] ) ? sanitize_text_field( wp_unslash( $_GET['tab'] ) ) : '';
return 'wc-settings' === $page && 'checkout' === $tab;
},
'wcgateway.is-ppcp-settings-page' => static function ( $container ): bool {
if ( ! $container->get( 'wcgateway.is-wc-payments-page' ) ) {
return false;
}
$section = isset( $_GET['section'] ) ? sanitize_text_field( wp_unslash( $_GET['section'] ) ) : '';
return in_array( $section, array( PayPalGateway::ID, CreditCardGateway::ID ), true );
},
'wcgateway.current-ppcp-settings-page-id' => static function ( $container ): string {
if ( ! $container->get( 'wcgateway.is-ppcp-settings-page' ) ) {
return '';
}
$section = isset( $_GET['section'] ) ? sanitize_text_field( wp_unslash( $_GET['section'] ) ) : '';
$ppcp_tab = isset( $_GET[ SectionsRenderer::KEY ] ) ? sanitize_text_field( wp_unslash( $_GET[ SectionsRenderer::KEY ] ) ) : '';
return $ppcp_tab ? $ppcp_tab : $section;
},
'wcgateway.settings' => static function ( $container ): Settings {
return new Settings();
},
@ -108,12 +140,19 @@ return array(
$settings = $container->get( 'wcgateway.settings' );
return new ConnectAdminNotice( $state, $settings );
},
'wcgateway.notice.dcc-without-paypal' => static function ( $container ): DccWithoutPayPalAdminNotice {
$state = $container->get( 'onboarding.state' );
$settings = $container->get( 'wcgateway.settings' );
$is_payments_page = $container->get( 'wcgateway.is-wc-payments-page' );
$is_ppcp_settings_page = $container->get( 'wcgateway.is-ppcp-settings-page' );
return new DccWithoutPayPalAdminNotice( $state, $settings, $is_payments_page, $is_ppcp_settings_page );
},
'wcgateway.notice.authorize-order-action' =>
static function ( $container ): AuthorizeOrderActionNotice {
return new AuthorizeOrderActionNotice();
},
'wcgateway.settings.sections-renderer' => static function ( $container ): SectionsRenderer {
return new SectionsRenderer();
return new SectionsRenderer( $container->get( 'wcgateway.current-ppcp-settings-page-id' ) );
},
'wcgateway.settings.status' => static function ( $container ): SettingsStatus {
$settings = $container->get( 'wcgateway.settings' );
@ -127,6 +166,7 @@ return array(
$messages_apply = $container->get( 'button.helper.messages-apply' );
$dcc_product_status = $container->get( 'wcgateway.helper.dcc-product-status' );
$settings_status = $container->get( 'wcgateway.settings.status' );
$page_id = $container->get( 'wcgateway.current-ppcp-settings-page-id' );
return new SettingsRenderer(
$settings,
$state,
@ -134,7 +174,8 @@ return array(
$dcc_applies,
$messages_apply,
$dcc_product_status,
$settings_status
$settings_status,
$page_id
);
},
'wcgateway.settings.listener' => static function ( $container ): SettingsListener {
@ -144,7 +185,8 @@ return array(
$state = $container->get( 'onboarding.state' );
$cache = new Cache( 'ppcp-paypal-bearer' );
$bearer = $container->get( 'api.bearer' );
return new SettingsListener( $settings, $fields, $webhook_registrar, $cache, $state, $bearer );
$page_id = $container->get( 'wcgateway.current-ppcp-settings-page-id' );
return new SettingsListener( $settings, $fields, $webhook_registrar, $cache, $state, $bearer, $page_id );
},
'wcgateway.order-processor' => static function ( $container ): OrderProcessor {
@ -646,7 +688,7 @@ return array(
'label' => sprintf(
// translators: %1$s and %2$s are the opening and closing of HTML <a> tag.
__( 'Enable saved cards and subscription features on your store. To use vaulting features, you must %1$senable vaulting on your account%2$s.', 'woocommerce-paypal-payments' ),
'<a
'<a
href="https://docs.woocommerce.com/document/woocommerce-paypal-payments/#enable-vaulting-on-your-live-account"
target="_blank"
>',
@ -1876,15 +1918,6 @@ return array(
unset( $fields['ppcp_disconnect_sandbox'] );
}
/**
* Disable card for UK.
*/
$region = wc_get_base_location();
$country = $region['country'];
if ( 'GB' === $country ) {
unset( $fields['disable_funding']['options']['card'] );
}
/**
* Depending on your store location, some credit cards can't be used.
* Here, we filter them out.

View file

@ -197,13 +197,7 @@ class CreditCardGateway extends \WC_Payment_Gateway_CC {
*/
public function init_form_fields() {
$this->form_fields = array(
'enabled' => array(
'title' => __( 'Enable/Disable', 'woocommerce-paypal-payments' ),
'type' => 'checkbox',
'label' => __( 'Enable Credit Card Payments', 'woocommerce-paypal-payments' ),
'default' => 'no',
),
'ppcp' => array(
'ppcp' => array(
'type' => 'ppcp',
),
);
@ -218,6 +212,20 @@ class CreditCardGateway extends \WC_Payment_Gateway_CC {
remove_action( 'gettext', 'replace_credit_card_cvv_label' );
}
/**
* Renders the settings.
*
* @return string
*/
public function generate_ppcp_html(): string {
ob_start();
$this->settings_renderer->render();
$content = ob_get_contents();
ob_end_clean();
return $content;
}
/**
* Replace WooCommerce credit card field label.
*
@ -314,7 +322,7 @@ class CreditCardGateway extends \WC_Payment_Gateway_CC {
* @return bool
*/
public function is_available() : bool {
return $this->config->has( 'dcc_enabled' ) && $this->config->get( 'dcc_enabled' );
return $this->is_enabled();
}
@ -349,4 +357,60 @@ class CreditCardGateway extends \WC_Payment_Gateway_CC {
return parent::get_transaction_url( $order );
}
/**
* Initialize settings for WC.
*
* @return void
*/
public function init_settings() {
parent::init_settings();
// looks like in some cases WC uses this field instead of get_option.
$this->enabled = $this->is_enabled();
}
/**
* Get the option value for WC.
*
* @param string $key The option key.
* @param mixed $empty_value Value when empty.
* @return mixed
*/
public function get_option( $key, $empty_value = null ) {
if ( 'enabled' === $key ) {
return $this->is_enabled();
}
return parent::get_option( $key, $empty_value );
}
/**
* Handle update of WC settings.
*
* @param string $key The option key.
* @param string $value The option value.
* @return bool was anything saved?
*/
public function update_option( $key, $value = '' ) {
$ret = parent::update_option( $key, $value );
if ( 'enabled' === $key ) {
$this->config->set( 'dcc_enabled', 'yes' === $value );
$this->config->persist();
return true;
}
return $ret;
}
/**
* Returns if the gateway is enabled.
*
* @return bool
*/
private function is_enabled(): bool {
return $this->config->has( 'dcc_enabled' ) && $this->config->get( 'dcc_enabled' );
}
}

View file

@ -103,6 +103,13 @@ class PayPalGateway extends \WC_Payment_Gateway {
*/
private $onboarded;
/**
* ID of the current PPCP gateway settings page, or empty if it is not such page.
*
* @var string
*/
protected $page_id;
/**
* PayPalGateway constructor.
*
@ -116,6 +123,7 @@ class PayPalGateway extends \WC_Payment_Gateway {
* @param State $state The state.
* @param TransactionUrlProvider $transaction_url_provider Service providing transaction view URL based on order.
* @param SubscriptionHelper $subscription_helper The subscription helper.
* @param string $page_id ID of the current PPCP gateway settings page, or empty if it is not such page.
*/
public function __construct(
SettingsRenderer $settings_renderer,
@ -127,7 +135,8 @@ class PayPalGateway extends \WC_Payment_Gateway {
RefundProcessor $refund_processor,
State $state,
TransactionUrlProvider $transaction_url_provider,
SubscriptionHelper $subscription_helper
SubscriptionHelper $subscription_helper,
string $page_id
) {
$this->id = self::ID;
@ -139,6 +148,7 @@ class PayPalGateway extends \WC_Payment_Gateway {
$this->session_handler = $session_handler;
$this->refund_processor = $refund_processor;
$this->transaction_url_provider = $transaction_url_provider;
$this->page_id = $page_id;
$this->onboarded = $state->current_state() === State::STATE_ONBOARDED;
if ( $this->onboarded ) {
@ -332,8 +342,7 @@ class PayPalGateway extends \WC_Payment_Gateway {
*/
private function is_credit_card_tab() : bool {
return is_admin()
&& isset( $_GET[ SectionsRenderer::KEY ] )
&& CreditCardGateway::ID === sanitize_text_field( wp_unslash( $_GET[ SectionsRenderer::KEY ] ) );
&& CreditCardGateway::ID === $this->page_id;
}
@ -345,8 +354,7 @@ class PayPalGateway extends \WC_Payment_Gateway {
private function is_paypal_tab() : bool {
return ! $this->is_credit_card_tab()
&& is_admin()
&& isset( $_GET['section'] )
&& self::ID === sanitize_text_field( wp_unslash( $_GET['section'] ) );
&& self::ID === $this->page_id;
}
// phpcs:enable WordPress.Security.NonceVerification.Recommended
@ -387,14 +395,18 @@ class PayPalGateway extends \WC_Payment_Gateway {
*
* @param string $key The option key.
* @param string $value The option value.
* @return bool|void
* @return bool was anything saved?
*/
public function update_option( $key, $value = '' ) {
parent::update_option( $key, $value );
$ret = parent::update_option( $key, $value );
if ( 'enabled' === $key ) {
$this->config->set( 'enabled', 'yes' === $value );
$this->config->persist();
return true;
}
return $ret;
}
}

View file

@ -0,0 +1,101 @@
<?php
/**
* Creates the admin message about the DCC gateway being enabled without the PayPal gateway.
*
* @package WooCommerce\PayPalCommerce\WcGateway\Notice
*/
declare(strict_types=1);
namespace WooCommerce\PayPalCommerce\WcGateway\Notice;
use WooCommerce\PayPalCommerce\AdminNotices\Entity\Message;
use WooCommerce\PayPalCommerce\Onboarding\State;
use Psr\Container\ContainerInterface;
/**
* Creates the admin message about the DCC gateway being enabled without the PayPal gateway.
*/
class DccWithoutPayPalAdminNotice {
/**
* The state.
*
* @var State
*/
private $state;
/**
* The settings.
*
* @var ContainerInterface
*/
private $settings;
/**
* Whether the current page is the WC payment page.
*
* @var bool
*/
private $is_payments_page;
/**
* Whether the current page is the PPCP settings page.
*
* @var bool
*/
private $is_ppcp_settings_page;
/**
* ConnectAdminNotice constructor.
*
* @param State $state The state.
* @param ContainerInterface $settings The settings.
* @param bool $is_payments_page Whether the current page is the WC payment page.
* @param bool $is_ppcp_settings_page Whether the current page is the PPCP settings page.
*/
public function __construct(
State $state,
ContainerInterface $settings,
bool $is_payments_page,
bool $is_ppcp_settings_page
) {
$this->state = $state;
$this->settings = $settings;
$this->is_payments_page = $is_payments_page;
$this->is_ppcp_settings_page = $is_ppcp_settings_page;
}
/**
* Returns the message.
*
* @return Message|null
*/
public function message(): ?Message {
if ( ! $this->should_display() ) {
return null;
}
$message = sprintf(
/* translators: %1$s the gateway name. */
__(
'PayPal Card Processing cannot be used without the PayPal gateway. <a href="%1$s">Enable the PayPal Gateway</a>.',
'woocommerce-paypal-payments'
),
admin_url( 'admin.php?page=wc-settings&tab=checkout&section=ppcp-gateway' )
);
return new Message( $message, 'warning' );
}
/**
* Whether the message should be displayed.
*
* @return bool
*/
protected function should_display(): bool {
return State::STATE_ONBOARDED === $this->state->current_state()
&& ( $this->is_payments_page || $this->is_ppcp_settings_page )
&& ( $this->settings->has( 'dcc_enabled' ) && $this->settings->get( 'dcc_enabled' ) )
&& ( ! $this->settings->has( 'enabled' ) || ! $this->settings->get( 'enabled' ) );
}
}

View file

@ -19,15 +19,29 @@ class SectionsRenderer {
const KEY = 'ppcp-tab';
/**
* ID of the current PPCP gateway settings page, or empty if it is not such page.
*
* @var string
*/
protected $page_id;
/**
* SectionsRenderer constructor.
*
* @param string $page_id ID of the current PPCP gateway settings page, or empty if it is not such page.
*/
public function __construct( string $page_id ) {
$this->page_id = $page_id;
}
/**
* Whether the sections tab should be rendered.
*
* @return bool
*/
public function should_render() : bool {
global $current_section;
return PayPalGateway::ID === $current_section;
return ! empty( $this->page_id );
}
/**
@ -38,8 +52,6 @@ class SectionsRenderer {
return;
}
//phpcs:ignore WordPress.Security.NonceVerification.Recommended
$current = ! isset( $_GET[ self::KEY ] ) ? PayPalGateway::ID : sanitize_text_field( wp_unslash( $_GET[ self::KEY ] ) );
$sections = array(
PayPalGateway::ID => __( 'PayPal Checkout', 'woocommerce-paypal-payments' ),
CreditCardGateway::ID => __( 'PayPal Card Processing', 'woocommerce-paypal-payments' ),
@ -51,7 +63,7 @@ class SectionsRenderer {
foreach ( $sections as $id => $label ) {
$url = admin_url( 'admin.php?page=wc-settings&tab=checkout&section=ppcp-gateway&' . self::KEY . '=' . $id );
echo '<li><a href="' . esc_url( $url ) . '" class="' . ( $current === $id ? 'current' : '' ) . '">' . esc_html( $label ) . '</a> ' . ( end( $array_keys ) === $id ? '' : '|' ) . ' </li>';
echo '<li><a href="' . esc_url( $url ) . '" class="' . ( $this->page_id === $id ? 'current' : '' ) . '">' . esc_html( $label ) . '</a> ' . ( end( $array_keys ) === $id ? '' : '|' ) . ' </li>';
}
echo '</ul><br class="clear" />';

View file

@ -25,6 +25,11 @@ class SettingsListener {
const NONCE = 'ppcp-settings';
private const CREDENTIALS_ADDED = 'credentials_added';
private const CREDENTIALS_REMOVED = 'credentials_removed';
private const CREDENTIALS_CHANGED = 'credentials_changed';
private const CREDENTIALS_UNCHANGED = 'credentials_unchanged';
/**
* The Settings.
*
@ -67,6 +72,13 @@ class SettingsListener {
*/
private $bearer;
/**
* ID of the current PPCP gateway settings page, or empty if it is not such page.
*
* @var string
*/
protected $page_id;
/**
* SettingsListener constructor.
*
@ -76,6 +88,7 @@ class SettingsListener {
* @param Cache $cache The Cache.
* @param State $state The state.
* @param Bearer $bearer The bearer.
* @param string $page_id ID of the current PPCP gateway settings page, or empty if it is not such page.
*/
public function __construct(
Settings $settings,
@ -83,7 +96,8 @@ class SettingsListener {
WebhookRegistrar $webhook_registrar,
Cache $cache,
State $state,
Bearer $bearer
Bearer $bearer,
string $page_id
) {
$this->settings = $settings;
@ -92,6 +106,7 @@ class SettingsListener {
$this->cache = $cache;
$this->state = $state;
$this->bearer = $bearer;
$this->page_id = $page_id;
}
/**
@ -218,18 +233,46 @@ class SettingsListener {
$settings = $this->read_active_credentials_from_settings( $settings );
if ( ! isset( $_GET[ SectionsRenderer::KEY ] ) || PayPalGateway::ID === $_GET[ SectionsRenderer::KEY ] ) {
$credentials_change_status = null; // Cannot detect on Card Processing page.
if ( PayPalGateway::ID === $this->page_id ) {
$settings['enabled'] = isset( $_POST['woocommerce_ppcp-gateway_enabled'] )
&& 1 === absint( $_POST['woocommerce_ppcp-gateway_enabled'] );
$this->maybe_register_webhooks( $settings );
$credentials_change_status = $this->determine_credentials_change_status( $settings );
}
// phpcs:enable phpcs:disable WordPress.Security.NonceVerification.Missing
// phpcs:enable phpcs:disable WordPress.Security.NonceVerification.Missing
if ( $credentials_change_status ) {
if ( self::CREDENTIALS_UNCHANGED !== $credentials_change_status ) {
$this->settings->set( 'products_dcc_enabled', null );
}
if ( in_array(
$credentials_change_status,
array( self::CREDENTIALS_REMOVED, self::CREDENTIALS_CHANGED ),
true
) ) {
$this->webhook_registrar->unregister();
}
}
foreach ( $settings as $id => $value ) {
$this->settings->set( $id, $value );
}
$this->settings->persist();
if ( $credentials_change_status ) {
if ( in_array(
$credentials_change_status,
array( self::CREDENTIALS_ADDED, self::CREDENTIALS_CHANGED ),
true
) ) {
$this->webhook_registrar->register();
}
}
if ( $this->cache->has( PayPalBearer::CACHE_KEY ) ) {
$this->cache->delete( PayPalBearer::CACHE_KEY );
}
@ -265,30 +308,36 @@ class SettingsListener {
}
/**
* Depending on the settings change, we might need to register or unregister the Webhooks at PayPal.
* Checks whether on the credentials changed.
*
* @param array $settings The settings.
*
* @throws \WooCommerce\PayPalCommerce\WcGateway\Exception\NotFoundException If a setting hasn't been found.
* @param array $new_settings New settings.
* @return string One of the CREDENTIALS_ constants.
*/
private function maybe_register_webhooks( array $settings ) {
private function determine_credentials_change_status( array $new_settings ): string {
$current_id = $this->settings->has( 'client_id' ) ? $this->settings->get( 'client_id' ) : '';
$current_secret = $this->settings->has( 'client_secret' ) ? $this->settings->get( 'client_secret' ) : '';
$new_id = $new_settings['client_id'] ?? '';
$new_secret = $new_settings['client_secret'] ?? '';
if ( ! $this->settings->has( 'client_id' ) && $settings['client_id'] ) {
$this->settings->set( 'products_dcc_enabled', null );
$this->webhook_registrar->register();
$had_credentials = $current_id && $current_secret;
$submitted_credentials = $new_id && $new_secret;
if ( ! $had_credentials && $submitted_credentials ) {
return self::CREDENTIALS_ADDED;
}
if ( $this->settings->has( 'client_id' ) && $this->settings->get( 'client_id' ) ) {
$current_secret = $this->settings->has( 'client_secret' ) ?
$this->settings->get( 'client_secret' ) : '';
if ( $had_credentials ) {
if ( ! $submitted_credentials ) {
return self::CREDENTIALS_REMOVED;
}
if (
$settings['client_id'] !== $this->settings->get( 'client_id' )
|| $settings['client_secret'] !== $current_secret
$current_id !== $new_id
|| $current_secret !== $new_secret
) {
$this->settings->set( 'products_dcc_enabled', null );
$this->webhook_registrar->unregister();
$this->webhook_registrar->register();
return self::CREDENTIALS_CHANGED;
}
}
return self::CREDENTIALS_UNCHANGED;
}
/**
@ -313,17 +362,13 @@ class SettingsListener {
}
if (
'dcc' === $config['gateway']
&& (
! isset( $_GET[ SectionsRenderer::KEY ] )
|| sanitize_text_field( wp_unslash( $_GET[ SectionsRenderer::KEY ] ) ) !== CreditCardGateway::ID
)
&& CreditCardGateway::ID !== $this->page_id
) {
continue;
}
if (
'paypal' === $config['gateway']
&& isset( $_GET[ SectionsRenderer::KEY ] )
&& sanitize_text_field( wp_unslash( $_GET[ SectionsRenderer::KEY ] ) ) !== PayPalGateway::ID
&& PayPalGateway::ID !== $this->page_id
) {
continue;
}
@ -406,14 +451,7 @@ class SettingsListener {
* phpcs:disable WordPress.Security.NonceVerification.Missing
* phpcs:disable WordPress.Security.NonceVerification.Recommended
*/
if (
! isset( $_REQUEST['section'] )
|| ! in_array(
sanitize_text_field( wp_unslash( $_REQUEST['section'] ) ),
array( 'ppcp-gateway', 'ppcp-credit-card-gateway' ),
true
)
) {
if ( empty( $this->page_id ) ) {
return false;
}

View file

@ -15,6 +15,7 @@ use WooCommerce\PayPalCommerce\Button\Helper\MessagesApply;
use WooCommerce\PayPalCommerce\Onboarding\State;
use WooCommerce\PayPalCommerce\WcGateway\Gateway\CreditCardGateway;
use Psr\Container\ContainerInterface;
use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway;
use Woocommerce\PayPalCommerce\WcGateway\Helper\DccProductStatus;
use Woocommerce\PayPalCommerce\WcGateway\Helper\SettingsStatus;
@ -72,6 +73,13 @@ class SettingsRenderer {
*/
private $dcc_product_status;
/**
* ID of the current PPCP gateway settings page, or empty if it is not such page.
*
* @var string
*/
protected $page_id;
/**
* SettingsRenderer constructor.
*
@ -82,6 +90,7 @@ class SettingsRenderer {
* @param MessagesApply $messages_apply Whether messages can be shown.
* @param DccProductStatus $dcc_product_status The product status.
* @param SettingsStatus $settings_status The Settings status helper.
* @param string $page_id ID of the current PPCP gateway settings page, or empty if it is not such page.
*/
public function __construct(
ContainerInterface $settings,
@ -90,7 +99,8 @@ class SettingsRenderer {
DccApplies $dcc_applies,
MessagesApply $messages_apply,
DccProductStatus $dcc_product_status,
SettingsStatus $settings_status
SettingsStatus $settings_status,
string $page_id
) {
$this->settings = $settings;
@ -100,6 +110,7 @@ class SettingsRenderer {
$this->messages_apply = $messages_apply;
$this->dcc_product_status = $dcc_product_status;
$this->settings_status = $settings_status;
$this->page_id = $page_id;
}
/**
@ -166,21 +177,7 @@ class SettingsRenderer {
* @return bool Whether is PayPal checkout screen or not.
*/
private function is_paypal_checkout_screen(): bool {
$current_screen = get_current_screen();
//phpcs:disable WordPress.Security.NonceVerification.Recommended
//phpcs:disable WordPress.Security.NonceVerification.Missing
if ( isset( $current_screen->id ) && 'woocommerce_page_wc-settings' === $current_screen->id
&& isset( $_GET['section'] ) && 'ppcp-gateway' === $_GET['section'] ) {
if ( isset( $_GET['ppcp-tab'] ) && 'ppcp-gateway' !== $_GET['ppcp-tab'] ) {
return false;
}
return true;
}
//phpcs:enable
return false;
return PayPalGateway::ID === $this->page_id;
}
/**
@ -317,9 +314,7 @@ class SettingsRenderer {
*/
public function render() {
//phpcs:disable WordPress.Security.NonceVerification.Recommended
//phpcs:disable WordPress.Security.NonceVerification.Missing
$is_dcc = isset( $_GET[ SectionsRenderer::KEY ] ) && CreditCardGateway::ID === sanitize_text_field( wp_unslash( $_GET[ SectionsRenderer::KEY ] ) );
$is_dcc = CreditCardGateway::ID === $this->page_id;
//phpcs:enable WordPress.Security.NonceVerification.Recommended
//phpcs:enable WordPress.Security.NonceVerification.Missing
$nonce = wp_create_nonce( SettingsListener::NONCE );
@ -506,8 +501,8 @@ class SettingsRenderer {
return false;
}
return $this->is_paypal_checkout_screen() && $this->paypal_vaulting_is_enabled()
|| $this->is_paypal_checkout_screen() && $this->settings_status->pay_later_messaging_is_enabled();
return $this->is_paypal_checkout_screen()
&& ( $this->paypal_vaulting_is_enabled() || $this->settings_status->pay_later_messaging_is_enabled() );
}
}

View file

@ -24,6 +24,7 @@ use WooCommerce\PayPalCommerce\WcGateway\Endpoint\ReturnUrlEndpoint;
use WooCommerce\PayPalCommerce\WcGateway\Gateway\CreditCardGateway;
use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway;
use WooCommerce\PayPalCommerce\WcGateway\Notice\ConnectAdminNotice;
use WooCommerce\PayPalCommerce\WcGateway\Notice\DccWithoutPayPalAdminNotice;
use WooCommerce\PayPalCommerce\WcGateway\Settings\SectionsRenderer;
use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
use WooCommerce\PayPalCommerce\WcGateway\Settings\SettingsListener;
@ -58,7 +59,6 @@ class WcGatewayModule implements ModuleInterface {
$this->register_order_functionality( $container );
$this->register_columns( $container );
$this->register_checkout_paypal_address_preset( $container );
$this->ajax_gateway_enabler( $container );
add_action(
'woocommerce_sections_checkout',
@ -86,15 +86,19 @@ class WcGatewayModule implements ModuleInterface {
Repository::NOTICES_FILTER,
static function ( $notices ) use ( $container ): array {
$notice = $container->get( 'wcgateway.notice.connect' );
/**
* The Connect Admin Notice object.
*
* @var ConnectAdminNotice $notice
*/
assert( $notice instanceof ConnectAdminNotice );
$connect_message = $notice->connect_message();
if ( $connect_message ) {
$notices[] = $connect_message;
}
$dcc_without_paypal_notice = $container->get( 'wcgateway.notice.dcc-without-paypal' );
assert( $dcc_without_paypal_notice instanceof DccWithoutPayPalAdminNotice );
$dcc_without_paypal_message = $dcc_without_paypal_notice->message();
if ( $dcc_without_paypal_message ) {
$notices[] = $dcc_without_paypal_message;
}
$authorize_order_action = $container->get( 'wcgateway.notice.authorize-order-action' );
$authorized_message = $authorize_order_action->message();
if ( $authorized_message ) {
@ -102,11 +106,7 @@ class WcGatewayModule implements ModuleInterface {
}
$settings_renderer = $container->get( 'wcgateway.settings.render' );
/**
* The settings renderer.
*
* @var SettingsRenderer $settings_renderer
*/
assert( $settings_renderer instanceof SettingsRenderer );
$messages = $settings_renderer->messages();
$notices = array_merge( $notices, $messages );
@ -149,50 +149,6 @@ class WcGatewayModule implements ModuleInterface {
);
}
/**
* Adds the functionality to listen to the ajax enable gateway switch.
*
* @param ContainerInterface $container The container.
*/
private function ajax_gateway_enabler( ContainerInterface $container ) {
add_action(
'wp_ajax_woocommerce_toggle_gateway_enabled',
static function () use ( $container ) {
if (
! current_user_can( 'manage_woocommerce' )
|| ! check_ajax_referer(
'woocommerce-toggle-payment-gateway-enabled',
'security'
)
|| ! isset( $_POST['gateway_id'] )
) {
return;
}
/**
* The settings.
*
* @var Settings $settings
*/
$settings = $container->get( 'wcgateway.settings' );
$key = PayPalGateway::ID === $_POST['gateway_id'] ? 'enabled' : '';
if ( CreditCardGateway::ID === $_POST['gateway_id'] ) {
$key = 'dcc_enabled';
}
if ( ! $key ) {
return;
}
$enabled = $settings->has( $key ) ? $settings->get( $key ) : false;
if ( ! $enabled ) {
return;
}
$settings->set( $key, false );
$settings->persist();
},
9
);
}
/**
* Registers the payment gateways.
*
@ -206,16 +162,12 @@ class WcGatewayModule implements ModuleInterface {
$methods[] = $container->get( 'wcgateway.paypal-gateway' );
$dcc_applies = $container->get( 'api.helpers.dccapplies' );
$screen = ! function_exists( 'get_current_screen' ) ? (object) array( 'id' => 'front' ) : get_current_screen();
if ( ! $screen ) {
$screen = (object) array( 'id' => 'front' );
}
/**
* The DCC Applies object.
*
* @var DccApplies $dcc_applies
*/
if ( 'woocommerce_page_wc-settings' !== $screen->id && $dcc_applies->for_country_currency() ) {
if ( $dcc_applies->for_country_currency() ) {
$methods[] = $container->get( 'wcgateway.credit-card-gateway' );
}
return (array) $methods;

View file

@ -22,10 +22,12 @@ return array(
$factory = $container->get( 'api.factory.webhook' );
$endpoint = $container->get( 'api.endpoint.webhook' );
$rest_endpoint = $container->get( 'webhook.endpoint.controller' );
$logger = $container->get( 'woocommerce.logger.woocommerce' );
return new WebhookRegistrar(
$factory,
$endpoint,
$rest_endpoint
$rest_endpoint,
$logger
);
},
'webhook.endpoint.controller' => function( $container ) : IncomingWebhookEndpoint {

View file

@ -9,6 +9,7 @@ declare(strict_types=1);
namespace WooCommerce\PayPalCommerce\Webhooks;
use Psr\Log\LoggerInterface;
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\WebhookEndpoint;
use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
use WooCommerce\PayPalCommerce\ApiClient\Factory\WebhookFactory;
@ -43,22 +44,32 @@ class WebhookRegistrar {
*/
private $rest_endpoint;
/**
* The logger.
*
* @var LoggerInterface
*/
private $logger;
/**
* WebhookRegistrar constructor.
*
* @param WebhookFactory $webhook_factory The Webhook factory.
* @param WebhookEndpoint $endpoint The Webhook endpoint.
* @param IncomingWebhookEndpoint $rest_endpoint The WordPress Rest API endpoint.
* @param LoggerInterface $logger The logger.
*/
public function __construct(
WebhookFactory $webhook_factory,
WebhookEndpoint $endpoint,
IncomingWebhookEndpoint $rest_endpoint
IncomingWebhookEndpoint $rest_endpoint,
LoggerInterface $logger
) {
$this->webhook_factory = $webhook_factory;
$this->endpoint = $endpoint;
$this->rest_endpoint = $rest_endpoint;
$this->logger = $logger;
}
/**
@ -81,8 +92,10 @@ class WebhookRegistrar {
self::KEY,
$created->to_array()
);
$this->logger->info( 'Webhooks registered.' );
return true;
} catch ( RuntimeException $error ) {
$this->logger->error( 'Failed to register webhooks: ' . $error->getMessage() );
return false;
}
}
@ -101,11 +114,13 @@ class WebhookRegistrar {
$webhook = $this->webhook_factory->from_array( $data );
$success = $this->endpoint->delete( $webhook );
} catch ( RuntimeException $error ) {
$this->logger->error( 'Failed to delete webhooks: ' . $error->getMessage() );
return false;
}
if ( $success ) {
delete_option( self::KEY );
$this->logger->info( 'Webhooks deleted.' );
}
return $success;
}