Merge pull request #205 from woocommerce/PT-51-plugin-information---support

Add PayPal onboarding information to WooCommerce system status
This commit is contained in:
Emili Castells 2021-08-10 11:33:20 +02:00 committed by GitHub
commit 8924fb884e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 331 additions and 24 deletions

View file

@ -14,6 +14,7 @@ use WooCommerce\PayPalCommerce\ApiClient\Entity\Token;
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,13 +75,15 @@ 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;
@ -81,6 +91,7 @@ class PayPalBearer implements Bearer {
$this->key = $key;
$this->secret = $secret;
$this->logger = $logger;
$this->settings = $settings;
}
/**
@ -105,12 +116,15 @@ class PayPalBearer implements Bearer {
* @throws RuntimeException When request fails.
*/
private function newBearer(): Token {
$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 @@ class PayPalBearer implements Bearer {
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',

View file

@ -51,7 +51,7 @@ return array(
*
* @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' );

View file

@ -103,15 +103,16 @@ return array(
$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 {

View file

@ -0,0 +1,12 @@
<?php
/**
* The status report module extensions.
*
* @package WooCommerce\PayPalCommerce\StatusReport
*/
declare(strict_types=1);
namespace WooCommerce\PayPalCommerce\StatusReport;
return array();

View file

@ -0,0 +1,16 @@
<?php
/**
* The status report module.
*
* @package WooCommerce\PayPalCommerce\StatusReport
*/
declare(strict_types=1);
namespace WooCommerce\PayPalCommerce\StatusReport;
use Dhii\Modular\Module\ModuleInterface;
return static function (): ModuleInterface {
return new StatusReportModule();
};

View file

@ -0,0 +1,16 @@
<?php
/**
* The status report module services.
*
* @package WooCommerce\PayPalCommerce\StatusReport
*/
declare(strict_types=1);
namespace WooCommerce\PayPalCommerce\StatusReport;
return array(
'status-report.renderer' => static function ( $container ): Renderer {
return new Renderer();
},
);

View file

@ -0,0 +1,52 @@
<?php
/**
* The status report renderer.
*
* @package WooCommerce\PayPalCommerce\StatusReport
*/
declare(strict_types=1);
namespace WooCommerce\PayPalCommerce\StatusReport;
/**
* Class Renderer
*/
class Renderer {
/**
* It renders the status report content.
*
* @param string $title The title.
* @param array $items The items.
* @return false|string
*/
public function render( string $title, array $items ) {
ob_start();
?>
<table class="wc_status_table widefat" id="status">
<thead>
<tr>
<th colspan="3" data-export-label="<?php echo esc_attr( $title ); ?>">
<h2><?php echo esc_attr( $title ); ?></h2>
</th>
</tr>
</thead>
<tbody>
<?php
foreach ( $items as $item ) {
?>
<tr>
<td data-export-label="<?php echo esc_attr( $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>
</tr>
<?php
}
?>
</tbody>
</table>
<?php
return ob_get_clean();
}
}

View file

@ -0,0 +1,148 @@
<?php
/**
* The status report module.
*
* @package WooCommerce\PayPalCommerce\StatusReport
*/
declare(strict_types=1);
namespace WooCommerce\PayPalCommerce\StatusReport;
use Dhii\Container\ServiceProvider;
use Dhii\Modular\Module\ModuleInterface;
use Interop\Container\ServiceProviderInterface;
use Psr\Container\ContainerInterface;
use WooCommerce\PayPalCommerce\ApiClient\Authentication\Bearer;
use WooCommerce\PayPalCommerce\ApiClient\Authentication\PayPalBearer;
use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
use WooCommerce\PayPalCommerce\ApiClient\Helper\DccApplies;
use WooCommerce\PayPalCommerce\Button\Helper\MessagesApply;
use WooCommerce\PayPalCommerce\Onboarding\State;
/**
* Class StatusReportModule
*/
class StatusReportModule implements ModuleInterface {
/**
* {@inheritDoc}
*/
public function setup(): ServiceProviderInterface {
return new ServiceProvider(
require __DIR__ . '/../services.php',
require __DIR__ . '/../extensions.php'
);
}
/**
* {@inheritDoc}
*
* @param ContainerInterface $container A services container instance.
*/
public function run( ContainerInterface $container ): void {
add_action(
'woocommerce_system_status_report',
function () use ( $container ) {
/* @var State $state The state. */
$state = $container->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' );
}
}
}

View file

@ -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)
}
}

View file

@ -156,12 +156,16 @@ class SettingsListener {
return;
}
} catch ( RuntimeException $exception ) {
$this->settings->set( 'vault_enabled', false );
$this->settings->persist();
add_action(
'admin_notices',
function () use ( $exception ) {
printf(
'<div class="notice notice-error"><p>%s</p></div>',
esc_attr( $exception->getMessage() )
'<div class="notice notice-error"><p>%1$s</p><p>%2$s</p></div>',
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 <a href="https://docs.woocommerce.com/document/woocommerce-paypal-payments/" target="_blank">plugin documentation</a> for more information about the setup.', 'woocommerce-paypal-payments' ) )
);
}
);

View file

@ -8,6 +8,7 @@ use WooCommerce\PayPalCommerce\ApiClient\Helper\Cache;
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 @@ class PayPalBearerTest extends TestCase
$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 @@ class PayPalBearerTest extends TestCase
$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 @@ class PayPalBearerTest extends TestCase
$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 @@ class PayPalBearerTest extends TestCase
$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 @@ class PayPalBearerTest extends TestCase
$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)

View file

@ -0,0 +1,32 @@
<?php
declare(strict_types=1);
namespace WooCommerce\PayPalCommerce\StatusReport;
use WooCommerce\PayPalCommerce\TestCase;
use function Brain\Monkey\Functions\when;
class RendererTest extends TestCase
{
public function testRender()
{
$items = [
[
'label' => '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('<h2>Some title here</h2>', $result);
self::assertStringContainsString('<td data-export-label="Foo">Foo</td>', $result);
self::assertStringContainsString('<td class="help">Bar</td>', $result);
self::assertStringContainsString('<td>Baz</td>', $result);
}
}