diff --git a/modules/ppcp-api-client/src/Authentication/class-paypalbearer.php b/modules/ppcp-api-client/src/Authentication/class-paypalbearer.php index fb4cac9ac..25af18575 100644 --- a/modules/ppcp-api-client/src/Authentication/class-paypalbearer.php +++ b/modules/ppcp-api-client/src/Authentication/class-paypalbearer.php @@ -14,6 +14,7 @@ use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException; use WooCommerce\PayPalCommerce\ApiClient\Helper\Cache; use Psr\Log\LoggerInterface; +use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings; /** * Class PayPalBearer @@ -24,6 +25,13 @@ class PayPalBearer implements Bearer { const CACHE_KEY = 'ppcp-bearer'; + /** + * The settings. + * + * @var Settings + */ + protected $settings; + /** * The cache. * @@ -67,20 +75,23 @@ class PayPalBearer implements Bearer { * @param string $key The key. * @param string $secret The secret. * @param LoggerInterface $logger The logger. + * @param Settings $settings The settings. */ public function __construct( Cache $cache, string $host, string $key, string $secret, - LoggerInterface $logger + LoggerInterface $logger, + Settings $settings ) { - $this->cache = $cache; - $this->host = $host; - $this->key = $key; - $this->secret = $secret; - $this->logger = $logger; + $this->cache = $cache; + $this->host = $host; + $this->key = $key; + $this->secret = $secret; + $this->logger = $logger; + $this->settings = $settings; } /** @@ -105,12 +116,15 @@ public function bearer(): Token { * @throws RuntimeException When request fails. */ private function newBearer(): Token { - $url = trailingslashit( $this->host ) . 'v1/oauth2/token?grant_type=client_credentials'; + $key = $this->settings->has( 'client_id' ) && $this->settings->get( 'client_id' ) ? $this->settings->get( 'client_id' ) : $this->key; + $secret = $this->settings->has( 'client_secret' ) && $this->settings->get( 'client_secret' ) ? $this->settings->get( 'client_secret' ) : $this->secret; + $url = trailingslashit( $this->host ) . 'v1/oauth2/token?grant_type=client_credentials'; + $args = array( 'method' => 'POST', 'headers' => array( // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode - 'Authorization' => 'Basic ' . base64_encode( $this->key . ':' . $this->secret ), + 'Authorization' => 'Basic ' . base64_encode( $key . ':' . $secret ), ), ); $response = $this->request( @@ -120,11 +134,7 @@ private function newBearer(): Token { if ( is_wp_error( $response ) || wp_remote_retrieve_response_code( $response ) !== 200 ) { $error = new RuntimeException( - sprintf( - // translators: %s is the error description. - __( 'Could not create token. %s', 'woocommerce-paypal-payments' ), - isset( json_decode( $response['body'] )->error_description ) ? json_decode( $response['body'] )->error_description : '' - ) + __( 'Could not create token.', 'woocommerce-paypal-payments' ) ); $this->logger->log( 'warning', diff --git a/modules/ppcp-button/services.php b/modules/ppcp-button/services.php index 6d2809d8f..9ff036bbf 100644 --- a/modules/ppcp-button/services.php +++ b/modules/ppcp-button/services.php @@ -51,7 +51,7 @@ * * @var State $state */ - if ( $state->current_state() < State::STATE_PROGRESSIVE ) { + if ( $state->current_state() <= State::STATE_PROGRESSIVE ) { return new DisabledSmartButton(); } $settings = $container->get( 'wcgateway.settings' ); diff --git a/modules/ppcp-onboarding/services.php b/modules/ppcp-onboarding/services.php index 3c9577510..2e07665b8 100644 --- a/modules/ppcp-onboarding/services.php +++ b/modules/ppcp-onboarding/services.php @@ -103,15 +103,16 @@ $cache = new Cache( 'ppcp-paypal-bearer' ); $key = $container->get( 'api.key' ); $secret = $container->get( 'api.secret' ); - $host = $container->get( 'api.host' ); $logger = $container->get( 'woocommerce.logger.woocommerce' ); + $settings = $container->get( 'wcgateway.settings' ); return new PayPalBearer( $cache, $host, $key, $secret, - $logger + $logger, + $settings ); }, 'onboarding.state' => function( $container ) : State { diff --git a/modules/ppcp-status-report/extensions.php b/modules/ppcp-status-report/extensions.php new file mode 100644 index 000000000..0935c0cc1 --- /dev/null +++ b/modules/ppcp-status-report/extensions.php @@ -0,0 +1,12 @@ + static function ( $container ): Renderer { + return new Renderer(); + }, +); diff --git a/modules/ppcp-status-report/src/class-renderer.php b/modules/ppcp-status-report/src/class-renderer.php new file mode 100644 index 000000000..680006bcd --- /dev/null +++ b/modules/ppcp-status-report/src/class-renderer.php @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + +
+

+
+ get( 'onboarding.state' ); + + /* @var Bearer $bearer The bearer. */ + $bearer = $container->get( 'api.bearer' ); + + /* @var DccApplies $dcc_applies The ddc applies. */ + $dcc_applies = $container->get( 'api.helpers.dccapplies' ); + + /* @var MessagesApply $messages_apply The messages apply. */ + $messages_apply = $container->get( 'button.helper.messages-apply' ); + + /* @var Renderer $renderer The renderer. */ + $renderer = $container->get( 'status-report.renderer' ); + + $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 ), + ), + 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'], + ), + 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' ), + ), + 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' ), + ), + 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 ), + ), + ); + + echo wp_kses_post( + $renderer->render( + esc_html__( 'WooCommerce PayPal Payments', 'woocommerce-paypal-payments' ), + $items + ) + ); + } + ); + } + + /** + * {@inheritDoc} + */ + public function getKey() { } + + /** + * It returns the current onboarding status. + * + * @param Bearer $bearer The bearer. + * @param State $state The state. + * @return string + */ + private function onboarded( $bearer, $state ): string { + try { + $token = $bearer->bearer(); + } catch ( RuntimeException $exception ) { + return esc_html__( 'No', 'woocommerce-paypal-payments' ); + } + + $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' ); + } + + /** + * It returns whether vaulting is enabled or not. + * + * @param Bearer $bearer The bearer. + * @return string + */ + private function vault_enabled( $bearer ) { + try { + $token = $bearer->bearer(); + return $token->vaulting_available() + ? esc_html__( 'Yes', 'woocommerce-paypal-payments' ) + : esc_html__( 'No', 'woocommerce-paypal-payments' ); + } catch ( RuntimeException $exception ) { + return esc_html__( 'No', 'woocommerce-paypal-payments' ); + } + } +} diff --git a/modules/ppcp-wc-gateway/resources/js/gateway-settings.js b/modules/ppcp-wc-gateway/resources/js/gateway-settings.js index ee061057b..69ae208aa 100644 --- a/modules/ppcp-wc-gateway/resources/js/gateway-settings.js +++ b/modules/ppcp-wc-gateway/resources/js/gateway-settings.js @@ -25,7 +25,7 @@ atLeastOneChecked(payLaterMessagingCheckboxes) ? disableAll(vaultingCheckboxes) : enableAll(vaultingCheckboxes) atLeastOneChecked(vaultingCheckboxes) ? disableAll(payLaterMessagingCheckboxes) : enableAll(payLaterMessagingCheckboxes) - if(PayPalCommerceGatewaySettings.vaulting_features_available !== '1' ) { + if(typeof PayPalCommerceGatewaySettings === 'undefined' || PayPalCommerceGatewaySettings.vaulting_features_available !== '1' ) { disableAll(vaultingCheckboxes) } } diff --git a/modules/ppcp-wc-gateway/src/Settings/class-settingslistener.php b/modules/ppcp-wc-gateway/src/Settings/class-settingslistener.php index e7a559355..6c0f9463f 100644 --- a/modules/ppcp-wc-gateway/src/Settings/class-settingslistener.php +++ b/modules/ppcp-wc-gateway/src/Settings/class-settingslistener.php @@ -156,12 +156,16 @@ public function listen_for_vaulting_enabled() { return; } } catch ( RuntimeException $exception ) { + $this->settings->set( 'vault_enabled', false ); + $this->settings->persist(); + add_action( 'admin_notices', function () use ( $exception ) { printf( - '

%s

', - esc_attr( $exception->getMessage() ) + '

%1$s

%2$s

', + esc_html__( 'Authentication with PayPal failed: ', 'woocommerce-paypal-payments' ) . esc_attr( $exception->getMessage() ), + wp_kses_post( __( 'Please verify your API Credentials and try again to connect your PayPal business account. Visit the plugin documentation for more information about the setup.', 'woocommerce-paypal-payments' ) ) ); } ); diff --git a/tests/PHPUnit/ApiClient/Authentication/PayPalBearerTest.php b/tests/PHPUnit/ApiClient/Authentication/PayPalBearerTest.php index c7349c420..469c337d5 100644 --- a/tests/PHPUnit/ApiClient/Authentication/PayPalBearerTest.php +++ b/tests/PHPUnit/ApiClient/Authentication/PayPalBearerTest.php @@ -8,6 +8,7 @@ use WooCommerce\PayPalCommerce\ApiClient\TestCase; use Psr\Log\LoggerInterface; use Mockery; +use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings; use function Brain\Monkey\Functions\expect; class PayPalBearerTest extends TestCase @@ -28,8 +29,11 @@ public function testDefault() $secret = 'secret'; $logger = Mockery::mock(LoggerInterface::class); $logger->shouldNotReceive('log'); + $settings = Mockery::mock(Settings::class); + $settings->shouldReceive('has')->andReturn(true); + $settings->shouldReceive('get')->andReturn(''); - $bearer = new PayPalBearer($cache, $host, $key, $secret, $logger); + $bearer = new PayPalBearer($cache, $host, $key, $secret, $logger, $settings); expect('trailingslashit') ->with($host) @@ -77,8 +81,11 @@ public function testNoTokenCached() $secret = 'secret'; $logger = Mockery::mock(LoggerInterface::class); $logger->shouldNotReceive('log'); + $settings = Mockery::mock(Settings::class); + $settings->shouldReceive('has')->andReturn(true); + $settings->shouldReceive('get')->andReturn(''); - $bearer = new PayPalBearer($cache, $host, $key, $secret, $logger); + $bearer = new PayPalBearer($cache, $host, $key, $secret, $logger, $settings); expect('trailingslashit') ->with($host) @@ -123,8 +130,11 @@ public function testCachedTokenIsStillValid() $secret = 'secret'; $logger = Mockery::mock(LoggerInterface::class); $logger->shouldNotReceive('log'); + $settings = Mockery::mock(Settings::class); + $settings->shouldReceive('has')->andReturn(true); + $settings->shouldReceive('get')->andReturn(''); - $bearer = new PayPalBearer($cache, $host, $key, $secret, $logger); + $bearer = new PayPalBearer($cache, $host, $key, $secret, $logger, $settings); $token = $bearer->bearer(); $this->assertEquals("abc", $token->token()); @@ -143,8 +153,11 @@ public function testExceptionThrownOnError() $secret = 'secret'; $logger = Mockery::mock(LoggerInterface::class); $logger->shouldReceive('log'); + $settings = Mockery::mock(Settings::class); + $settings->shouldReceive('has')->andReturn(true); + $settings->shouldReceive('get')->andReturn(''); - $bearer = new PayPalBearer($cache, $host, $key, $secret, $logger); + $bearer = new PayPalBearer($cache, $host, $key, $secret, $logger, $settings); expect('trailingslashit') ->with($host) @@ -186,8 +199,11 @@ public function testExceptionThrownBecauseOfHttpStatusCode() $secret = 'secret'; $logger = Mockery::mock(LoggerInterface::class); $logger->shouldReceive('log'); + $settings = Mockery::mock(Settings::class); + $settings->shouldReceive('has')->andReturn(true); + $settings->shouldReceive('get')->andReturn(''); - $bearer = new PayPalBearer($cache, $host, $key, $secret, $logger); + $bearer = new PayPalBearer($cache, $host, $key, $secret, $logger, $settings); expect('trailingslashit') ->with($host) diff --git a/tests/PHPUnit/StatusReport/RendererTest.php b/tests/PHPUnit/StatusReport/RendererTest.php new file mode 100644 index 000000000..0b83d86ff --- /dev/null +++ b/tests/PHPUnit/StatusReport/RendererTest.php @@ -0,0 +1,32 @@ + 'Foo', + 'description' => 'Bar', + 'value' => 'Baz' + ], + ]; + + when('esc_attr')->returnArg(); + when('wc_help_tip')->returnArg(); + + $testee = new Renderer(); + $result = $testee->render('Some title here', $items); + + self::assertStringContainsString('

Some title here

', $result); + self::assertStringContainsString('Foo', $result); + self::assertStringContainsString('Bar', $result); + self::assertStringContainsString('Baz', $result); + } +}