mirror of
https://github.com/woocommerce/woocommerce-paypal-payments.git
synced 2025-09-06 10:55:00 +08:00
Merge branch 'trunk' of github.com:woocommerce/woocommerce-paypal-payments into PCP-3965-update-the-settings-design-in-accordance-with-the-latest-figma-files
This commit is contained in:
commit
cc8482c340
144 changed files with 5286 additions and 2141 deletions
|
@ -19,7 +19,7 @@ hooks:
|
||||||
pre-start:
|
pre-start:
|
||||||
- exec-host: "mkdir -p .ddev/wordpress/wp-content/plugins/${DDEV_PROJECT}"
|
- exec-host: "mkdir -p .ddev/wordpress/wp-content/plugins/${DDEV_PROJECT}"
|
||||||
web_environment:
|
web_environment:
|
||||||
- WP_VERSION=6.3.3
|
- WP_VERSION=6.7.1
|
||||||
- WP_LOCALE=en_US
|
- WP_LOCALE=en_US
|
||||||
- WP_TITLE=WooCommerce PayPal Payments
|
- WP_TITLE=WooCommerce PayPal Payments
|
||||||
- WP_MULTISITE=true
|
- WP_MULTISITE=true
|
||||||
|
|
117
.psalm/stubs.php
117
.psalm/stubs.php
|
@ -1,71 +1,116 @@
|
||||||
<?php
|
<?php
|
||||||
if (!defined('PAYPAL_INTEGRATION_DATE')) {
|
/**
|
||||||
define('PAYPAL_INTEGRATION_DATE', '2023-06-02');
|
* Stubs to help psalm correctly annotate problems in the plugin.
|
||||||
|
*
|
||||||
|
* @package WooCommerce
|
||||||
|
*/
|
||||||
|
|
||||||
|
if ( ! defined( 'PAYPAL_INTEGRATION_DATE' ) ) {
|
||||||
|
define( 'PAYPAL_INTEGRATION_DATE', '2023-06-02' );
|
||||||
}
|
}
|
||||||
if (!defined('PAYPAL_URL')) {
|
if ( ! defined( 'PAYPAL_URL' ) ) {
|
||||||
define( 'PAYPAL_URL', 'https://www.paypal.com' );
|
define( 'PAYPAL_URL', 'https://www.paypal.com' );
|
||||||
}
|
}
|
||||||
if (!defined('PAYPAL_SANDBOX_URL')) {
|
if ( ! defined( 'PAYPAL_SANDBOX_URL' ) ) {
|
||||||
define( 'PAYPAL_SANDBOX_URL', 'https://www.sandbox.paypal.com' );
|
define( 'PAYPAL_SANDBOX_URL', 'https://www.sandbox.paypal.com' );
|
||||||
}
|
}
|
||||||
if (!defined('EP_PAGES')) {
|
if ( ! defined( 'EP_PAGES' ) ) {
|
||||||
define('EP_PAGES', 4096);
|
define( 'EP_PAGES', 4096 );
|
||||||
}
|
}
|
||||||
if (!defined('MONTH_IN_SECONDS')) {
|
if ( ! defined( 'MONTH_IN_SECONDS' ) ) {
|
||||||
define('MONTH_IN_SECONDS', 30 * DAY_IN_SECONDS);
|
define( 'MONTH_IN_SECONDS', 30 * DAY_IN_SECONDS );
|
||||||
}
|
}
|
||||||
if (!defined('HOUR_IN_SECONDS')) {
|
if ( ! defined( 'HOUR_IN_SECONDS' ) ) {
|
||||||
define('HOUR_IN_SECONDS', 60 * MINUTE_IN_SECONDS);
|
define( 'HOUR_IN_SECONDS', 60 * MINUTE_IN_SECONDS );
|
||||||
}
|
}
|
||||||
if (!defined('MINUTE_IN_SECONDS')) {
|
if ( ! defined( 'MINUTE_IN_SECONDS' ) ) {
|
||||||
define( 'MINUTE_IN_SECONDS', 60 );
|
define( 'MINUTE_IN_SECONDS', 60 );
|
||||||
}
|
}
|
||||||
|
if ( ! defined( 'ABSPATH' ) ) {
|
||||||
if (!defined('ABSPATH')) {
|
define( 'ABSPATH', '' );
|
||||||
define('ABSPATH', '');
|
|
||||||
}
|
}
|
||||||
|
if ( ! defined( 'PAYPAL_API_URL' ) ) {
|
||||||
if (!defined('PPCP_PAYPAL_BN_CODE')) {
|
define( 'PAYPAL_API_URL', 'https://api-m.paypal.com' );
|
||||||
define('PPCP_PAYPAL_BN_CODE', 'Woo_PPCP');
|
}
|
||||||
|
if ( ! defined( 'PAYPAL_SANDBOX_API_URL' ) ) {
|
||||||
|
define( 'PAYPAL_SANDBOX_API_URL', 'https://api-m.sandbox.paypal.com' );
|
||||||
|
}
|
||||||
|
if ( ! defined( 'PPCP_PAYPAL_BN_CODE' ) ) {
|
||||||
|
define( 'PPCP_PAYPAL_BN_CODE', 'Woo_PPCP' );
|
||||||
|
}
|
||||||
|
if ( ! defined( 'CONNECT_WOO_CLIENT_ID' ) ) {
|
||||||
|
define( 'CONNECT_WOO_CLIENT_ID', 'AcCAsWta_JTL__OfpjspNyH7c1GGHH332fLwonA5CwX4Y10mhybRZmHLA0GdRbwKwjQIhpDQy0pluX_P' );
|
||||||
|
}
|
||||||
|
if ( ! defined( 'CONNECT_WOO_SANDBOX_CLIENT_ID' ) ) {
|
||||||
|
define( 'CONNECT_WOO_SANDBOX_CLIENT_ID', 'AYmOHbt1VHg-OZ_oihPdzKEVbU3qg0qXonBcAztuzniQRaKE0w1Hr762cSFwd4n8wxOl-TCWohEa0XM_' );
|
||||||
|
}
|
||||||
|
if ( ! defined( 'CONNECT_WOO_MERCHANT_ID' ) ) {
|
||||||
|
define( 'CONNECT_WOO_MERCHANT_ID', 'K8SKZ36LQBWXJ' );
|
||||||
|
}
|
||||||
|
if ( ! defined( 'CONNECT_WOO_SANDBOX_MERCHANT_ID' ) ) {
|
||||||
|
define( 'CONNECT_WOO_SANDBOX_MERCHANT_ID', 'MPMFHQTVMBZ6G' );
|
||||||
|
}
|
||||||
|
if ( ! defined( 'CONNECT_WOO_URL' ) ) {
|
||||||
|
define( 'CONNECT_WOO_URL', 'https://api.woocommerce.com/integrations/ppc' );
|
||||||
|
}
|
||||||
|
if ( ! defined( 'CONNECT_WOO_SANDBOX_URL' ) ) {
|
||||||
|
define( 'CONNECT_WOO_SANDBOX_URL', 'https://api.woocommerce.com/integrations/ppcsandbox' );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cancel the next occurrence of a scheduled action.
|
* Cancel the next occurrence of a scheduled action.
|
||||||
*
|
*
|
||||||
* While only the next instance of a recurring or cron action is unscheduled by this method, that will also prevent
|
* While only the next instance of a recurring or cron action is unscheduled by this method, that
|
||||||
* all future instances of that recurring or cron action from being run. Recurring and cron actions are scheduled in
|
* will also prevent all future instances of that recurring or cron action from being run.
|
||||||
* a sequence instead of all being scheduled at once. Each successive occurrence of a recurring action is scheduled
|
* Recurring and cron actions are scheduled in a sequence instead of all being scheduled at once.
|
||||||
* only after the former action is run. If the next instance is never run, because it's unscheduled by this function,
|
* Each successive occurrence of a recurring action is scheduled only after the former action is
|
||||||
* then the following instance will never be scheduled (or exist), which is effectively the same as being unscheduled
|
* run. If the next instance is never run, because it's unscheduled by this function, then the
|
||||||
* by this method also.
|
* following instance will never be scheduled (or exist), which is effectively the same as being
|
||||||
|
* unscheduled by this method also.
|
||||||
*
|
*
|
||||||
* @param string $hook The hook that the job will trigger.
|
* @param string $hook The hook that the job will trigger.
|
||||||
* @param array $args Args that would have been passed to the job.
|
* @param array $args Args that would have been passed to the job.
|
||||||
* @param string $group The group the job is assigned to.
|
* @param string $group The group the job is assigned to.
|
||||||
*
|
*
|
||||||
* @return string|null The scheduled action ID if a scheduled action was found, or null if no matching action found.
|
* @return string|null The scheduled action ID if a scheduled action was found, or null if no
|
||||||
|
* matching action found.
|
||||||
*/
|
*/
|
||||||
function as_unschedule_action($hook, $args = array(), $group = '') {}
|
function as_unschedule_action( $hook, $args = array(), $group = '' ) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Schedule an action to run one time
|
* Schedule an action to run one time
|
||||||
*
|
*
|
||||||
* @param int $timestamp When the job will run.
|
* @param int $timestamp When the job will run.
|
||||||
* @param string $hook The hook to trigger.
|
* @param string $hook The hook to trigger.
|
||||||
* @param array $args Arguments to pass when the hook triggers.
|
* @param array $args Arguments to pass when the hook triggers.
|
||||||
* @param string $group The group to assign this job to.
|
* @param string $group The group to assign this job to.
|
||||||
* @param bool $unique Whether the action should be unique.
|
* @param bool $unique Whether the action should be unique.
|
||||||
*
|
*
|
||||||
* @return int The action ID.
|
* @return int The action ID.
|
||||||
*/
|
*/
|
||||||
function as_schedule_single_action( $timestamp, $hook, $args = array(), $group = '', $unique = false ) {}
|
function as_schedule_single_action( $timestamp, $hook, $args = array(), $group = '', $unique = false ) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* HTML API: WP_HTML_Tag_Processor class
|
* HTML API: WP_HTML_Tag_Processor class
|
||||||
*/
|
*/
|
||||||
|
// phpcs:disable
|
||||||
class WP_HTML_Tag_Processor {
|
class WP_HTML_Tag_Processor {
|
||||||
public function __construct( $html ) {}
|
public function __construct( $html ) {
|
||||||
public function next_tag( $query = null ) {}
|
}
|
||||||
public function set_attribute( $name, $value ) {}
|
|
||||||
public function get_updated_html() {}
|
public function next_tag( $query = null ) : bool {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function set_attribute( $name, $value ) : bool {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function get_updated_html() : string {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,23 @@
|
||||||
*** Changelog ***
|
*** Changelog ***
|
||||||
|
|
||||||
|
= 2.9.5 - xxxx-xx-xx =
|
||||||
|
Fix - Early translation loading triggers `Function _load_textdomain_just_in_time was called incorrectly.` notice #2816
|
||||||
|
Fix - ACDC card fields not loading and payment not successful when Classic Checkout Smart Button Location disabled #2852
|
||||||
|
Fix - ACDC gateway does not appear for guests when is Fastlane enabled and a subscription product is in the cart #2745
|
||||||
|
Fix - "Voide authorization" button does not appear for Apple Pay/Google Pay orders when payment buttons are separated #2752
|
||||||
|
Fix - Additional payment tokens saved with new customer_id #2820
|
||||||
|
Fix - Vaulted payment method may not be displayed in PayPal button for return buyer #2809
|
||||||
|
Fix - Conflict with EasyShip plugin due to shipping methods loading too early #2845
|
||||||
|
Fix - Restore accidentally removed ACDC currencies #2838
|
||||||
|
Enhancement - Native gateway icon for PayPal & Pay upon Invoice gateways #2712
|
||||||
|
Enhancement - Allow disabling specific card types for Fastlane #2704
|
||||||
|
Enhancement - Fastlane Insights SDK implementation for block Checkout #2737
|
||||||
|
Enhancement - Hide split local APMs in Payments settings tab when PayPal is not enabled #2703
|
||||||
|
Enhancement - Do not load split local APMs on Checkout when PayPal is not enabled #2792
|
||||||
|
Enhancement - Add support for Button Options in the Block Checkout for Apple Pay & Google Pay buttons #2797 #2772
|
||||||
|
Enhancement - Disable “Add payment method” button while saving ACDC payment #2794
|
||||||
|
Enhancement - Sanitize soft_descriptor field #2846 #2854
|
||||||
|
|
||||||
= 2.9.4 - 2024-11-11 =
|
= 2.9.4 - 2024-11-11 =
|
||||||
* Fix - Apple Pay button preview missing in Standard payment and Advanced Processing tabs #2755
|
* Fix - Apple Pay button preview missing in Standard payment and Advanced Processing tabs #2755
|
||||||
* Fix - Set "Sold individually" only for subscription connected to PayPal #2710
|
* Fix - Set "Sold individually" only for subscription connected to PayPal #2710
|
||||||
|
|
|
@ -15,7 +15,6 @@ use WooCommerce\PayPalCommerce\ApiClient\Authentication\UserIdToken;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\Orders;
|
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\Orders;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PaymentMethodTokensEndpoint;
|
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PaymentMethodTokensEndpoint;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PaymentTokensEndpoint;
|
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PaymentTokensEndpoint;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\CardAuthenticationResult;
|
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Factory\CardAuthenticationResultFactory;
|
use WooCommerce\PayPalCommerce\ApiClient\Factory\CardAuthenticationResultFactory;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Helper\CurrencyGetter;
|
use WooCommerce\PayPalCommerce\ApiClient\Helper\CurrencyGetter;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Helper\FailureRegistry;
|
use WooCommerce\PayPalCommerce\ApiClient\Helper\FailureRegistry;
|
||||||
|
@ -79,6 +78,7 @@ use WooCommerce\PayPalCommerce\ApiClient\Repository\OrderRepository;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Repository\PartnerReferralsData;
|
use WooCommerce\PayPalCommerce\ApiClient\Repository\PartnerReferralsData;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Repository\PayeeRepository;
|
use WooCommerce\PayPalCommerce\ApiClient\Repository\PayeeRepository;
|
||||||
use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
|
use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
|
||||||
|
use WooCommerce\PayPalCommerce\ApiClient\Authentication\ConnectBearer;
|
||||||
|
|
||||||
return array(
|
return array(
|
||||||
'api.host' => function( ContainerInterface $container ) : string {
|
'api.host' => function( ContainerInterface $container ) : string {
|
||||||
|
@ -179,6 +179,22 @@ return array(
|
||||||
$container->get( 'woocommerce.logger.woocommerce' )
|
$container->get( 'woocommerce.logger.woocommerce' )
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
'api.endpoint.partner-referrals-sandbox' => static function ( ContainerInterface $container ) : PartnerReferrals {
|
||||||
|
|
||||||
|
return new PartnerReferrals(
|
||||||
|
CONNECT_WOO_SANDBOX_URL,
|
||||||
|
new ConnectBearer(),
|
||||||
|
$container->get( 'woocommerce.logger.woocommerce' )
|
||||||
|
);
|
||||||
|
},
|
||||||
|
'api.endpoint.partner-referrals-production' => static function ( ContainerInterface $container ) : PartnerReferrals {
|
||||||
|
|
||||||
|
return new PartnerReferrals(
|
||||||
|
CONNECT_WOO_URL,
|
||||||
|
new ConnectBearer(),
|
||||||
|
$container->get( 'woocommerce.logger.woocommerce' )
|
||||||
|
);
|
||||||
|
},
|
||||||
'api.endpoint.identity-token' => static function ( ContainerInterface $container ) : IdentityToken {
|
'api.endpoint.identity-token' => static function ( ContainerInterface $container ) : IdentityToken {
|
||||||
$logger = $container->get( 'woocommerce.logger.woocommerce' );
|
$logger = $container->get( 'woocommerce.logger.woocommerce' );
|
||||||
$settings = $container->get( 'wcgateway.settings' );
|
$settings = $container->get( 'wcgateway.settings' );
|
||||||
|
@ -572,6 +588,7 @@ return array(
|
||||||
'CZK',
|
'CZK',
|
||||||
'DKK',
|
'DKK',
|
||||||
'EUR',
|
'EUR',
|
||||||
|
'HKD',
|
||||||
'HUF',
|
'HUF',
|
||||||
'ILS',
|
'ILS',
|
||||||
'JPY',
|
'JPY',
|
||||||
|
@ -584,6 +601,7 @@ return array(
|
||||||
'PLN',
|
'PLN',
|
||||||
'GBP',
|
'GBP',
|
||||||
'RUB',
|
'RUB',
|
||||||
|
'SGD',
|
||||||
'SEK',
|
'SEK',
|
||||||
'CHF',
|
'CHF',
|
||||||
'THB',
|
'THB',
|
||||||
|
@ -595,27 +613,32 @@ return array(
|
||||||
* The matrix which countries and currency combinations can be used for DCC.
|
* The matrix which countries and currency combinations can be used for DCC.
|
||||||
*/
|
*/
|
||||||
'api.dcc-supported-country-currency-matrix' => static function ( ContainerInterface $container ) : array {
|
'api.dcc-supported-country-currency-matrix' => static function ( ContainerInterface $container ) : array {
|
||||||
$default_currencies = array(
|
$default_currencies = apply_filters(
|
||||||
'AUD',
|
'woocommerce_paypal_payments_supported_currencies',
|
||||||
'BRL',
|
array(
|
||||||
'CAD',
|
'AUD',
|
||||||
'CHF',
|
'BRL',
|
||||||
'CZK',
|
'CAD',
|
||||||
'DKK',
|
'CHF',
|
||||||
'EUR',
|
'CZK',
|
||||||
'GBP',
|
'DKK',
|
||||||
'HUF',
|
'EUR',
|
||||||
'ILS',
|
'HKD',
|
||||||
'JPY',
|
'GBP',
|
||||||
'MXN',
|
'HUF',
|
||||||
'NOK',
|
'ILS',
|
||||||
'NZD',
|
'JPY',
|
||||||
'PHP',
|
'MXN',
|
||||||
'PLN',
|
'NOK',
|
||||||
'SEK',
|
'NZD',
|
||||||
'THB',
|
'PHP',
|
||||||
'TWD',
|
'PLN',
|
||||||
'USD',
|
'SGD',
|
||||||
|
'SEK',
|
||||||
|
'THB',
|
||||||
|
'TWD',
|
||||||
|
'USD',
|
||||||
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -659,14 +682,7 @@ return array(
|
||||||
'ES' => $default_currencies,
|
'ES' => $default_currencies,
|
||||||
'SE' => $default_currencies,
|
'SE' => $default_currencies,
|
||||||
'GB' => $default_currencies,
|
'GB' => $default_currencies,
|
||||||
'US' => array(
|
'US' => $default_currencies,
|
||||||
'AUD',
|
|
||||||
'CAD',
|
|
||||||
'EUR',
|
|
||||||
'GBP',
|
|
||||||
'JPY',
|
|
||||||
'USD',
|
|
||||||
),
|
|
||||||
'NO' => $default_currencies,
|
'NO' => $default_currencies,
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
@ -845,4 +861,22 @@ return array(
|
||||||
$container->get( 'api.client-credentials-cache' )
|
$container->get( 'api.client-credentials-cache' )
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
'api.paypal-host-production' => static function( ContainerInterface $container ) : string {
|
||||||
|
return PAYPAL_API_URL;
|
||||||
|
},
|
||||||
|
'api.paypal-host-sandbox' => static function( ContainerInterface $container ) : string {
|
||||||
|
return PAYPAL_SANDBOX_API_URL;
|
||||||
|
},
|
||||||
|
'api.paypal-website-url-production' => static function( ContainerInterface $container ) : string {
|
||||||
|
return PAYPAL_URL;
|
||||||
|
},
|
||||||
|
'api.paypal-website-url-sandbox' => static function( ContainerInterface $container ) : string {
|
||||||
|
return PAYPAL_SANDBOX_URL;
|
||||||
|
},
|
||||||
|
'api.partner_merchant_id-production' => static function( ContainerInterface $container ) : string {
|
||||||
|
return CONNECT_WOO_MERCHANT_ID;
|
||||||
|
},
|
||||||
|
'api.partner_merchant_id-sandbox' => static function( ContainerInterface $container ) : string {
|
||||||
|
return CONNECT_WOO_SANDBOX_MERCHANT_ID;
|
||||||
|
},
|
||||||
);
|
);
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
* @package WooCommerce\PayPalCommerce\ApiClient\Authentication
|
* @package WooCommerce\PayPalCommerce\ApiClient\Authentication
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare( strict_types = 1 );
|
||||||
|
|
||||||
namespace WooCommerce\PayPalCommerce\ApiClient\Authentication;
|
namespace WooCommerce\PayPalCommerce\ApiClient\Authentication;
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ class PayPalBearer implements Bearer {
|
||||||
/**
|
/**
|
||||||
* The settings.
|
* The settings.
|
||||||
*
|
*
|
||||||
* @var ContainerInterface
|
* @var ?ContainerInterface
|
||||||
*/
|
*/
|
||||||
protected $settings;
|
protected $settings;
|
||||||
|
|
||||||
|
@ -70,12 +70,12 @@ class PayPalBearer implements Bearer {
|
||||||
/**
|
/**
|
||||||
* PayPalBearer constructor.
|
* PayPalBearer constructor.
|
||||||
*
|
*
|
||||||
* @param Cache $cache The cache.
|
* @param Cache $cache The cache.
|
||||||
* @param string $host The host.
|
* @param string $host The host.
|
||||||
* @param string $key The key.
|
* @param string $key The key.
|
||||||
* @param string $secret The secret.
|
* @param string $secret The secret.
|
||||||
* @param LoggerInterface $logger The logger.
|
* @param LoggerInterface $logger The logger.
|
||||||
* @param ContainerInterface $settings The settings.
|
* @param ?ContainerInterface $settings The settings.
|
||||||
*/
|
*/
|
||||||
public function __construct(
|
public function __construct(
|
||||||
Cache $cache,
|
Cache $cache,
|
||||||
|
@ -83,7 +83,7 @@ class PayPalBearer implements Bearer {
|
||||||
string $key,
|
string $key,
|
||||||
string $secret,
|
string $secret,
|
||||||
LoggerInterface $logger,
|
LoggerInterface $logger,
|
||||||
ContainerInterface $settings
|
?ContainerInterface $settings
|
||||||
) {
|
) {
|
||||||
|
|
||||||
$this->cache = $cache;
|
$this->cache = $cache;
|
||||||
|
@ -97,27 +97,62 @@ class PayPalBearer implements Bearer {
|
||||||
/**
|
/**
|
||||||
* Returns a bearer token.
|
* Returns a bearer token.
|
||||||
*
|
*
|
||||||
* @return Token
|
|
||||||
* @throws RuntimeException When request fails.
|
* @throws RuntimeException When request fails.
|
||||||
|
* @return Token
|
||||||
*/
|
*/
|
||||||
public function bearer(): Token {
|
public function bearer() : Token {
|
||||||
try {
|
try {
|
||||||
$bearer = Token::from_json( (string) $this->cache->get( self::CACHE_KEY ) );
|
$bearer = Token::from_json( (string) $this->cache->get( self::CACHE_KEY ) );
|
||||||
|
|
||||||
return ( $bearer->is_valid() ) ? $bearer : $this->newBearer();
|
return ( $bearer->is_valid() ) ? $bearer : $this->newBearer();
|
||||||
} catch ( RuntimeException $error ) {
|
} catch ( RuntimeException $error ) {
|
||||||
return $this->newBearer();
|
return $this->newBearer();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the client key for authentication.
|
||||||
|
*
|
||||||
|
* @return string The client ID from settings, or the key defined via constructor.
|
||||||
|
*/
|
||||||
|
private function get_key() : string {
|
||||||
|
if (
|
||||||
|
$this->settings
|
||||||
|
&& $this->settings->has( 'client_id' )
|
||||||
|
&& $this->settings->get( 'client_id' )
|
||||||
|
) {
|
||||||
|
return $this->settings->get( 'client_id' );
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->key;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the client secret for authentication.
|
||||||
|
*
|
||||||
|
* @return string The client secret from settings, or the value defined via constructor.
|
||||||
|
*/
|
||||||
|
private function get_secret() : string {
|
||||||
|
if (
|
||||||
|
$this->settings
|
||||||
|
&& $this->settings->has( 'client_secret' )
|
||||||
|
&& $this->settings->get( 'client_secret' )
|
||||||
|
) {
|
||||||
|
return $this->settings->get( 'client_secret' );
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->secret;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new bearer token.
|
* Creates a new bearer token.
|
||||||
*
|
*
|
||||||
* @return Token
|
|
||||||
* @throws RuntimeException When request fails.
|
* @throws RuntimeException When request fails.
|
||||||
|
* @return Token
|
||||||
*/
|
*/
|
||||||
private function newBearer(): Token {
|
private function newBearer() : Token {
|
||||||
$key = $this->settings->has( 'client_id' ) && $this->settings->get( 'client_id' ) ? $this->settings->get( 'client_id' ) : $this->key;
|
$key = $this->get_key();
|
||||||
$secret = $this->settings->has( 'client_secret' ) && $this->settings->get( 'client_secret' ) ? $this->settings->get( 'client_secret' ) : $this->secret;
|
$secret = $this->get_secret();
|
||||||
$url = trailingslashit( $this->host ) . 'v1/oauth2/token?grant_type=client_credentials';
|
$url = trailingslashit( $this->host ) . 'v1/oauth2/token?grant_type=client_credentials';
|
||||||
|
|
||||||
$args = array(
|
$args = array(
|
||||||
|
@ -127,10 +162,7 @@ class PayPalBearer implements Bearer {
|
||||||
'Authorization' => 'Basic ' . base64_encode( $key . ':' . $secret ),
|
'Authorization' => 'Basic ' . base64_encode( $key . ':' . $secret ),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
$response = $this->request(
|
$response = $this->request( $url, $args );
|
||||||
$url,
|
|
||||||
$args
|
|
||||||
);
|
|
||||||
|
|
||||||
if ( is_wp_error( $response ) || wp_remote_retrieve_response_code( $response ) !== 200 ) {
|
if ( is_wp_error( $response ) || wp_remote_retrieve_response_code( $response ) !== 200 ) {
|
||||||
$error = new RuntimeException(
|
$error = new RuntimeException(
|
||||||
|
@ -148,6 +180,7 @@ class PayPalBearer implements Bearer {
|
||||||
|
|
||||||
$token = Token::from_json( $response['body'] );
|
$token = Token::from_json( $response['body'] );
|
||||||
$this->cache->set( self::CACHE_KEY, $token->as_json() );
|
$this->cache->set( self::CACHE_KEY, $token->as_json() );
|
||||||
|
|
||||||
return $token;
|
return $token;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,8 +85,7 @@ class PartnerReferrals {
|
||||||
$error = new RuntimeException(
|
$error = new RuntimeException(
|
||||||
__( 'Could not create referral.', 'woocommerce-paypal-payments' )
|
__( 'Could not create referral.', 'woocommerce-paypal-payments' )
|
||||||
);
|
);
|
||||||
$this->logger->log(
|
$this->logger->warning(
|
||||||
'warning',
|
|
||||||
$error->getMessage(),
|
$error->getMessage(),
|
||||||
array(
|
array(
|
||||||
'args' => $args,
|
'args' => $args,
|
||||||
|
@ -95,6 +94,7 @@ class PartnerReferrals {
|
||||||
);
|
);
|
||||||
throw $error;
|
throw $error;
|
||||||
}
|
}
|
||||||
|
|
||||||
$json = json_decode( $response['body'] );
|
$json = json_decode( $response['body'] );
|
||||||
$status_code = (int) wp_remote_retrieve_response_code( $response );
|
$status_code = (int) wp_remote_retrieve_response_code( $response );
|
||||||
if ( 201 !== $status_code ) {
|
if ( 201 !== $status_code ) {
|
||||||
|
@ -102,8 +102,7 @@ class PartnerReferrals {
|
||||||
$json,
|
$json,
|
||||||
$status_code
|
$status_code
|
||||||
);
|
);
|
||||||
$this->logger->log(
|
$this->logger->warning(
|
||||||
'warning',
|
|
||||||
$error->getMessage(),
|
$error->getMessage(),
|
||||||
array(
|
array(
|
||||||
'args' => $args,
|
'args' => $args,
|
||||||
|
@ -122,8 +121,7 @@ class PartnerReferrals {
|
||||||
$error = new RuntimeException(
|
$error = new RuntimeException(
|
||||||
__( 'Action URL not found.', 'woocommerce-paypal-payments' )
|
__( 'Action URL not found.', 'woocommerce-paypal-payments' )
|
||||||
);
|
);
|
||||||
$this->logger->log(
|
$this->logger->warning(
|
||||||
'warning',
|
|
||||||
$error->getMessage(),
|
$error->getMessage(),
|
||||||
array(
|
array(
|
||||||
'args' => $args,
|
'args' => $args,
|
||||||
|
|
|
@ -61,19 +61,24 @@ class PaymentMethodTokensEndpoint {
|
||||||
* Creates a setup token.
|
* Creates a setup token.
|
||||||
*
|
*
|
||||||
* @param PaymentSource $payment_source The payment source.
|
* @param PaymentSource $payment_source The payment source.
|
||||||
|
* @param string $customer_id PayPal customer ID.
|
||||||
*
|
*
|
||||||
* @return stdClass
|
* @return stdClass
|
||||||
*
|
*
|
||||||
* @throws RuntimeException When something when wrong with the request.
|
* @throws RuntimeException When something when wrong with the request.
|
||||||
* @throws PayPalApiException When something when wrong setting up the token.
|
* @throws PayPalApiException When something when wrong setting up the token.
|
||||||
*/
|
*/
|
||||||
public function setup_tokens( PaymentSource $payment_source ): stdClass {
|
public function setup_tokens( PaymentSource $payment_source, string $customer_id = '' ): stdClass {
|
||||||
$data = array(
|
$data = array(
|
||||||
'payment_source' => array(
|
'payment_source' => array(
|
||||||
$payment_source->name() => $payment_source->properties(),
|
$payment_source->name() => $payment_source->properties(),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if ( $customer_id ) {
|
||||||
|
$data['customer']['id'] = $customer_id;
|
||||||
|
}
|
||||||
|
|
||||||
$bearer = $this->bearer->bearer();
|
$bearer = $this->bearer->bearer();
|
||||||
$url = trailingslashit( $this->host ) . 'v3/vault/setup-tokens';
|
$url = trailingslashit( $this->host ) . 'v3/vault/setup-tokens';
|
||||||
|
|
||||||
|
@ -109,19 +114,24 @@ class PaymentMethodTokensEndpoint {
|
||||||
* Creates a payment token for the given payment source.
|
* Creates a payment token for the given payment source.
|
||||||
*
|
*
|
||||||
* @param PaymentSource $payment_source The payment source.
|
* @param PaymentSource $payment_source The payment source.
|
||||||
|
* @param string $customer_id PayPal customer ID.
|
||||||
*
|
*
|
||||||
* @return stdClass
|
* @return stdClass
|
||||||
*
|
*
|
||||||
* @throws RuntimeException When something when wrong with the request.
|
* @throws RuntimeException When something when wrong with the request.
|
||||||
* @throws PayPalApiException When something when wrong setting up the token.
|
* @throws PayPalApiException When something when wrong setting up the token.
|
||||||
*/
|
*/
|
||||||
public function create_payment_token( PaymentSource $payment_source ): stdClass {
|
public function create_payment_token( PaymentSource $payment_source, string $customer_id = '' ): stdClass {
|
||||||
$data = array(
|
$data = array(
|
||||||
'payment_source' => array(
|
'payment_source' => array(
|
||||||
$payment_source->name() => $payment_source->properties(),
|
$payment_source->name() => $payment_source->properties(),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if ( $customer_id ) {
|
||||||
|
$data['customer']['id'] = $customer_id;
|
||||||
|
}
|
||||||
|
|
||||||
$bearer = $this->bearer->bearer();
|
$bearer = $this->bearer->bearer();
|
||||||
$url = trailingslashit( $this->host ) . 'v3/vault/payment-tokens';
|
$url = trailingslashit( $this->host ) . 'v3/vault/payment-tokens';
|
||||||
|
|
||||||
|
|
|
@ -127,7 +127,7 @@ class PurchaseUnitFactory {
|
||||||
$description = '';
|
$description = '';
|
||||||
$custom_id = (string) $order->get_id();
|
$custom_id = (string) $order->get_id();
|
||||||
$invoice_id = $this->prefix . $order->get_order_number();
|
$invoice_id = $this->prefix . $order->get_order_number();
|
||||||
$soft_descriptor = $this->soft_descriptor;
|
$soft_descriptor = $this->sanitize_soft_descriptor( $this->soft_descriptor );
|
||||||
|
|
||||||
$purchase_unit = new PurchaseUnit(
|
$purchase_unit = new PurchaseUnit(
|
||||||
$amount,
|
$amount,
|
||||||
|
@ -197,7 +197,7 @@ class PurchaseUnitFactory {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$invoice_id = '';
|
$invoice_id = '';
|
||||||
$soft_descriptor = $this->soft_descriptor;
|
$soft_descriptor = $this->sanitize_soft_descriptor( $this->soft_descriptor );
|
||||||
$purchase_unit = new PurchaseUnit(
|
$purchase_unit = new PurchaseUnit(
|
||||||
$amount,
|
$amount,
|
||||||
$items,
|
$items,
|
||||||
|
@ -233,7 +233,7 @@ class PurchaseUnitFactory {
|
||||||
$description = ( isset( $data->description ) ) ? $data->description : '';
|
$description = ( isset( $data->description ) ) ? $data->description : '';
|
||||||
$custom_id = ( isset( $data->custom_id ) ) ? $data->custom_id : '';
|
$custom_id = ( isset( $data->custom_id ) ) ? $data->custom_id : '';
|
||||||
$invoice_id = ( isset( $data->invoice_id ) ) ? $data->invoice_id : '';
|
$invoice_id = ( isset( $data->invoice_id ) ) ? $data->invoice_id : '';
|
||||||
$soft_descriptor = ( isset( $data->soft_descriptor ) ) ? $data->soft_descriptor : $this->soft_descriptor;
|
$soft_descriptor = $this->sanitize_soft_descriptor( $data->soft_descriptor ?? $this->soft_descriptor );
|
||||||
$items = array();
|
$items = array();
|
||||||
if ( isset( $data->items ) && is_array( $data->items ) ) {
|
if ( isset( $data->items ) && is_array( $data->items ) ) {
|
||||||
$items = array_map(
|
$items = array_map(
|
||||||
|
@ -316,4 +316,22 @@ class PurchaseUnitFactory {
|
||||||
$purchase_unit->set_sanitizer( $this->sanitizer );
|
$purchase_unit->set_sanitizer( $this->sanitizer );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sanitizes a soft descriptor, ensuring it is limited to 22 chars.
|
||||||
|
*
|
||||||
|
* The soft descriptor in the DB is escaped using `wp_kses_post()` which
|
||||||
|
* escapes certain characters via `wp_kses_normalize_entities()`. This
|
||||||
|
* helper method reverts those normalized entities back to UTF characters.
|
||||||
|
*
|
||||||
|
* @param string $soft_descriptor Soft descriptor to sanitize.
|
||||||
|
*
|
||||||
|
* @return string The sanitized soft descriptor.
|
||||||
|
*/
|
||||||
|
private function sanitize_soft_descriptor( string $soft_descriptor ) : string {
|
||||||
|
$decoded = html_entity_decode( $soft_descriptor, ENT_QUOTES, 'UTF-8' );
|
||||||
|
$sanitized = preg_replace( '/[^a-zA-Z0-9 *\-.]/', '', $decoded ) ?: '';
|
||||||
|
|
||||||
|
return substr( $sanitized, 0, 22 ) ?: '';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import { registerPlugin } from '@wordpress/plugins';
|
import { registerPlugin } from '@wordpress/plugins';
|
||||||
import { useEffect, useCallback, useState, useRef } from '@wordpress/element';
|
import { useEffect, useCallback, useState, useRef } from '@wordpress/element';
|
||||||
import { useSelect } from '@wordpress/data';
|
import { useSelect } from '@wordpress/data';
|
||||||
import { PAYMENT_STORE_KEY } from '@woocommerce/block-data';
|
|
||||||
import PayPalInsights from '../../../../ppcp-axo/resources/js/Insights/PayPalInsights';
|
import PayPalInsights from '../../../../ppcp-axo/resources/js/Insights/PayPalInsights';
|
||||||
import { STORE_NAME } from '../stores/axoStore';
|
import { STORE_NAME } from '../stores/axoStore';
|
||||||
import usePayPalCommerceGateway from '../hooks/usePayPalCommerceGateway';
|
import usePayPalCommerceGateway from '../hooks/usePayPalCommerceGateway';
|
||||||
|
@ -149,6 +148,7 @@ const usePaymentMethodTracking = ( axoConfig, eventTracking ) => {
|
||||||
const isInitialMount = useRef( true );
|
const isInitialMount = useRef( true );
|
||||||
|
|
||||||
const activePaymentMethod = useSelect( ( select ) => {
|
const activePaymentMethod = useSelect( ( select ) => {
|
||||||
|
const { PAYMENT_STORE_KEY } = window.wc.wcBlocksData;
|
||||||
return select( PAYMENT_STORE_KEY )?.getActivePaymentMethod();
|
return select( PAYMENT_STORE_KEY )?.getActivePaymentMethod();
|
||||||
}, [] );
|
}, [] );
|
||||||
|
|
||||||
|
|
|
@ -39,8 +39,7 @@ return array(
|
||||||
$container->get( 'onboarding.environment' ),
|
$container->get( 'onboarding.environment' ),
|
||||||
$container->get( 'wcgateway.url' ),
|
$container->get( 'wcgateway.url' ),
|
||||||
$container->get( 'axo.payment_method_selected_map' ),
|
$container->get( 'axo.payment_method_selected_map' ),
|
||||||
$container->get( 'axo.supported-country-card-type-matrix' ),
|
$container->get( 'axo.supported-country-card-type-matrix' )
|
||||||
$container->get( 'axo.shipping-wc-enabled-locations' )
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
|
@ -22,6 +22,7 @@ use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ExtendingModule;
|
||||||
use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ModuleClassNameIdTrait;
|
use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ModuleClassNameIdTrait;
|
||||||
use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ServiceModule;
|
use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ServiceModule;
|
||||||
use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface;
|
use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface;
|
||||||
|
use WooCommerce\PayPalCommerce\WcGateway\Helper\DCCGatewayConfiguration;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class AxoBlockModule
|
* Class AxoBlockModule
|
||||||
|
@ -134,7 +135,6 @@ class AxoBlockModule implements ServiceModule, ExtendingModule, ExecutableModule
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
// Enqueue the PayPal Insights script.
|
|
||||||
add_action(
|
add_action(
|
||||||
'wp_enqueue_scripts',
|
'wp_enqueue_scripts',
|
||||||
function () use ( $c ) {
|
function () use ( $c ) {
|
||||||
|
@ -187,6 +187,11 @@ class AxoBlockModule implements ServiceModule, ExtendingModule, ExecutableModule
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$dcc_configuration = $c->get( 'wcgateway.configuration.dcc' );
|
||||||
|
if ( ! $dcc_configuration->use_fastlane() ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
$module_url = $c->get( 'axoblock.url' );
|
$module_url = $c->get( 'axoblock.url' );
|
||||||
$asset_version = $c->get( 'ppcp.asset-version' );
|
$asset_version = $c->get( 'ppcp.asset-version' );
|
||||||
|
|
||||||
|
|
|
@ -93,13 +93,6 @@ class AxoBlockPaymentMethod extends AbstractPaymentMethodType {
|
||||||
*/
|
*/
|
||||||
private $supported_country_card_type_matrix;
|
private $supported_country_card_type_matrix;
|
||||||
|
|
||||||
/**
|
|
||||||
* The list of WooCommerce enabled shipping locations.
|
|
||||||
*
|
|
||||||
* @var array
|
|
||||||
*/
|
|
||||||
private array $enabled_shipping_locations;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AdvancedCardPaymentMethod constructor.
|
* AdvancedCardPaymentMethod constructor.
|
||||||
*
|
*
|
||||||
|
@ -113,7 +106,6 @@ class AxoBlockPaymentMethod extends AbstractPaymentMethodType {
|
||||||
* @param string $wcgateway_module_url The WcGateway module URL.
|
* @param string $wcgateway_module_url The WcGateway module URL.
|
||||||
* @param array $payment_method_selected_map Mapping of payment methods to the PayPal Insights 'payment_method_selected' types.
|
* @param array $payment_method_selected_map Mapping of payment methods to the PayPal Insights 'payment_method_selected' types.
|
||||||
* @param array $supported_country_card_type_matrix The supported country card type matrix for Axo.
|
* @param array $supported_country_card_type_matrix The supported country card type matrix for Axo.
|
||||||
* @param array $enabled_shipping_locations The list of WooCommerce enabled shipping locations.
|
|
||||||
*/
|
*/
|
||||||
public function __construct(
|
public function __construct(
|
||||||
string $module_url,
|
string $module_url,
|
||||||
|
@ -125,8 +117,7 @@ class AxoBlockPaymentMethod extends AbstractPaymentMethodType {
|
||||||
Environment $environment,
|
Environment $environment,
|
||||||
string $wcgateway_module_url,
|
string $wcgateway_module_url,
|
||||||
array $payment_method_selected_map,
|
array $payment_method_selected_map,
|
||||||
array $supported_country_card_type_matrix,
|
array $supported_country_card_type_matrix
|
||||||
array $enabled_shipping_locations
|
|
||||||
) {
|
) {
|
||||||
$this->name = AxoGateway::ID;
|
$this->name = AxoGateway::ID;
|
||||||
$this->module_url = $module_url;
|
$this->module_url = $module_url;
|
||||||
|
@ -139,7 +130,6 @@ class AxoBlockPaymentMethod extends AbstractPaymentMethodType {
|
||||||
$this->wcgateway_module_url = $wcgateway_module_url;
|
$this->wcgateway_module_url = $wcgateway_module_url;
|
||||||
$this->payment_method_selected_map = $payment_method_selected_map;
|
$this->payment_method_selected_map = $payment_method_selected_map;
|
||||||
$this->supported_country_card_type_matrix = $supported_country_card_type_matrix;
|
$this->supported_country_card_type_matrix = $supported_country_card_type_matrix;
|
||||||
$this->enabled_shipping_locations = $enabled_shipping_locations;
|
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
|
@ -237,7 +227,7 @@ class AxoBlockPaymentMethod extends AbstractPaymentMethodType {
|
||||||
),
|
),
|
||||||
'allowed_cards' => $this->supported_country_card_type_matrix,
|
'allowed_cards' => $this->supported_country_card_type_matrix,
|
||||||
'disable_cards' => $this->settings->has( 'disable_cards' ) ? (array) $this->settings->get( 'disable_cards' ) : array(),
|
'disable_cards' => $this->settings->has( 'disable_cards' ) ? (array) $this->settings->get( 'disable_cards' ) : array(),
|
||||||
'enabled_shipping_locations' => $this->enabled_shipping_locations,
|
'enabled_shipping_locations' => apply_filters( 'woocommerce_paypal_payments_axo_shipping_wc_enabled_locations', array() ),
|
||||||
'style_options' => array(
|
'style_options' => array(
|
||||||
'root' => array(
|
'root' => array(
|
||||||
'backgroundColor' => $this->settings->has( 'axo_style_root_bg_color' ) ? $this->settings->get( 'axo_style_root_bg_color' ) : '',
|
'backgroundColor' => $this->settings->has( 'axo_style_root_bg_color' ) ? $this->settings->get( 'axo_style_root_bg_color' ) : '',
|
||||||
|
|
|
@ -70,8 +70,7 @@ return array(
|
||||||
$container->get( 'api.shop.currency.getter' ),
|
$container->get( 'api.shop.currency.getter' ),
|
||||||
$container->get( 'woocommerce.logger.woocommerce' ),
|
$container->get( 'woocommerce.logger.woocommerce' ),
|
||||||
$container->get( 'wcgateway.url' ),
|
$container->get( 'wcgateway.url' ),
|
||||||
$container->get( 'axo.supported-country-card-type-matrix' ),
|
$container->get( 'axo.supported-country-card-type-matrix' )
|
||||||
$container->get( 'axo.shipping-wc-enabled-locations' )
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -329,33 +328,23 @@ return array(
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
'axo.shipping-wc-enabled-locations' => static function ( ContainerInterface $container ): array {
|
'axo.shipping-wc-enabled-locations' => static function ( ContainerInterface $container ) {
|
||||||
$default_zone = new \WC_Shipping_Zone( 0 );
|
$default_zone = new \WC_Shipping_Zone( 0 );
|
||||||
|
|
||||||
$is_method_enabled = fn( \WC_Shipping_Method $method): bool => $method->enabled === 'yes';
|
if ( ! empty( $default_zone->get_shipping_methods( true ) ) ) {
|
||||||
|
|
||||||
$is_default_zone_enabled = ! empty(
|
|
||||||
array_filter(
|
|
||||||
$default_zone->get_shipping_methods(),
|
|
||||||
$is_method_enabled
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
if ( $is_default_zone_enabled ) {
|
|
||||||
return array();
|
return array();
|
||||||
}
|
}
|
||||||
|
|
||||||
$shipping_zones = \WC_Shipping_Zones::get_zones();
|
$shipping_zones = \WC_Shipping_Zones::get_zones();
|
||||||
|
|
||||||
$get_zone_locations = fn( \WC_Shipping_Zone $zone): array =>
|
$get_zone_locations = fn( \WC_Shipping_Zone $zone): array =>
|
||||||
! empty( array_filter( $zone->get_shipping_methods(), $is_method_enabled ) )
|
! empty( $zone->get_shipping_methods( true ) )
|
||||||
? array_map(
|
? array_map(
|
||||||
fn( object $location): string => $location->code,
|
fn( object $location): string => $location->code,
|
||||||
$zone->get_zone_locations()
|
$zone->get_zone_locations()
|
||||||
)
|
)
|
||||||
: array();
|
: array();
|
||||||
|
|
||||||
$enabled_locations = array_unique(
|
return array_unique(
|
||||||
array_merge(
|
array_merge(
|
||||||
...array_map(
|
...array_map(
|
||||||
$get_zone_locations,
|
$get_zone_locations,
|
||||||
|
@ -367,7 +356,5 @@ return array(
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
return $enabled_locations;
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
|
@ -99,12 +99,6 @@ class AxoManager {
|
||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
private array $supported_country_card_type_matrix;
|
private array $supported_country_card_type_matrix;
|
||||||
/**
|
|
||||||
* The list of WooCommerce enabled shipping locations.
|
|
||||||
*
|
|
||||||
* @var array
|
|
||||||
*/
|
|
||||||
private array $enabled_shipping_locations;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AxoManager constructor.
|
* AxoManager constructor.
|
||||||
|
@ -120,7 +114,6 @@ class AxoManager {
|
||||||
* @param LoggerInterface $logger The logger.
|
* @param LoggerInterface $logger The logger.
|
||||||
* @param string $wcgateway_module_url The WcGateway module URL.
|
* @param string $wcgateway_module_url The WcGateway module URL.
|
||||||
* @param array $supported_country_card_type_matrix The supported country card type matrix for Axo.
|
* @param array $supported_country_card_type_matrix The supported country card type matrix for Axo.
|
||||||
* @param array $enabled_shipping_locations The list of WooCommerce enabled shipping locations.
|
|
||||||
*/
|
*/
|
||||||
public function __construct(
|
public function __construct(
|
||||||
string $module_url,
|
string $module_url,
|
||||||
|
@ -133,8 +126,7 @@ class AxoManager {
|
||||||
CurrencyGetter $currency,
|
CurrencyGetter $currency,
|
||||||
LoggerInterface $logger,
|
LoggerInterface $logger,
|
||||||
string $wcgateway_module_url,
|
string $wcgateway_module_url,
|
||||||
array $supported_country_card_type_matrix,
|
array $supported_country_card_type_matrix
|
||||||
array $enabled_shipping_locations
|
|
||||||
) {
|
) {
|
||||||
|
|
||||||
$this->module_url = $module_url;
|
$this->module_url = $module_url;
|
||||||
|
@ -147,7 +139,6 @@ class AxoManager {
|
||||||
$this->currency = $currency;
|
$this->currency = $currency;
|
||||||
$this->logger = $logger;
|
$this->logger = $logger;
|
||||||
$this->wcgateway_module_url = $wcgateway_module_url;
|
$this->wcgateway_module_url = $wcgateway_module_url;
|
||||||
$this->enabled_shipping_locations = $enabled_shipping_locations;
|
|
||||||
$this->supported_country_card_type_matrix = $supported_country_card_type_matrix;
|
$this->supported_country_card_type_matrix = $supported_country_card_type_matrix;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -203,7 +194,7 @@ class AxoManager {
|
||||||
return $data; } )( $this->insights_data ),
|
return $data; } )( $this->insights_data ),
|
||||||
'allowed_cards' => $this->supported_country_card_type_matrix,
|
'allowed_cards' => $this->supported_country_card_type_matrix,
|
||||||
'disable_cards' => $this->settings->has( 'disable_cards' ) ? (array) $this->settings->get( 'disable_cards' ) : array(),
|
'disable_cards' => $this->settings->has( 'disable_cards' ) ? (array) $this->settings->get( 'disable_cards' ) : array(),
|
||||||
'enabled_shipping_locations' => $this->enabled_shipping_locations,
|
'enabled_shipping_locations' => apply_filters( 'woocommerce_paypal_payments_axo_shipping_wc_enabled_locations', array() ),
|
||||||
'style_options' => array(
|
'style_options' => array(
|
||||||
'root' => array(
|
'root' => array(
|
||||||
'backgroundColor' => $this->settings->has( 'axo_style_root_bg_color' ) ? $this->settings->get( 'axo_style_root_bg_color' ) : '',
|
'backgroundColor' => $this->settings->has( 'axo_style_root_bg_color' ) ? $this->settings->get( 'axo_style_root_bg_color' ) : '',
|
||||||
|
|
|
@ -229,6 +229,16 @@ class AxoModule implements ServiceModule, ExtendingModule, ExecutableModule {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Late loading locations because of trouble with some shipping plugins
|
||||||
|
*/
|
||||||
|
add_filter(
|
||||||
|
'woocommerce_paypal_payments_axo_shipping_wc_enabled_locations',
|
||||||
|
function ( array $locations ) use ( $c ): array {
|
||||||
|
return array_merge( $locations, $c->get( 'axo.shipping-wc-enabled-locations' ) );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Param types removed to avoid third-party issues.
|
* Param types removed to avoid third-party issues.
|
||||||
*
|
*
|
||||||
|
|
|
@ -143,10 +143,15 @@ class BlocksModule implements ServiceModule, ExtendingModule, ExecutableModule {
|
||||||
|
|
||||||
add_filter(
|
add_filter(
|
||||||
'woocommerce_paypal_payments_sdk_components_hook',
|
'woocommerce_paypal_payments_sdk_components_hook',
|
||||||
function( array $components ) {
|
function( array $components, string $context ) {
|
||||||
$components[] = 'buttons';
|
if ( str_ends_with( $context, '-block' ) ) {
|
||||||
|
$components[] = 'buttons';
|
||||||
|
}
|
||||||
|
|
||||||
return $components;
|
return $components;
|
||||||
}
|
},
|
||||||
|
10,
|
||||||
|
2
|
||||||
);
|
);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -324,6 +324,10 @@ const bootstrap = () => {
|
||||||
messagesBootstrap.init();
|
messagesBootstrap.init();
|
||||||
|
|
||||||
apmButtonsInit( PayPalCommerceGateway );
|
apmButtonsInit( PayPalCommerceGateway );
|
||||||
|
|
||||||
|
if ( ! renderer.useSmartButtons ) {
|
||||||
|
buttonsSpinner.unblock();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
document.addEventListener( 'DOMContentLoaded', () => {
|
document.addEventListener( 'DOMContentLoaded', () => {
|
||||||
|
|
|
@ -211,6 +211,7 @@ class CheckoutBootstap {
|
||||||
const isFreeTrial = PayPalCommerceGateway.is_free_trial_cart;
|
const isFreeTrial = PayPalCommerceGateway.is_free_trial_cart;
|
||||||
const hasVaultedPaypal =
|
const hasVaultedPaypal =
|
||||||
PayPalCommerceGateway.vaulted_paypal_email !== '';
|
PayPalCommerceGateway.vaulted_paypal_email !== '';
|
||||||
|
const useSmartButtons = this.renderer.useSmartButtons ?? true;
|
||||||
|
|
||||||
const paypalButtonWrappers = {
|
const paypalButtonWrappers = {
|
||||||
...Object.entries( PayPalCommerceGateway.separate_buttons ).reduce(
|
...Object.entries( PayPalCommerceGateway.separate_buttons ).reduce(
|
||||||
|
@ -225,7 +226,8 @@ class CheckoutBootstap {
|
||||||
this.standardOrderButtonSelector,
|
this.standardOrderButtonSelector,
|
||||||
( isPaypal && isFreeTrial && hasVaultedPaypal ) ||
|
( isPaypal && isFreeTrial && hasVaultedPaypal ) ||
|
||||||
isNotOurGateway ||
|
isNotOurGateway ||
|
||||||
isSavedCard,
|
isSavedCard ||
|
||||||
|
( isPaypal && ! useSmartButtons ),
|
||||||
'ppcp-hidden'
|
'ppcp-hidden'
|
||||||
);
|
);
|
||||||
setVisible( '.ppcp-vaulted-paypal-details', isPaypal );
|
setVisible( '.ppcp-vaulted-paypal-details', isPaypal );
|
||||||
|
|
|
@ -6,16 +6,16 @@ const processAxoConfig = ( config ) => {
|
||||||
const scriptOptions = {};
|
const scriptOptions = {};
|
||||||
const sdkClientToken = config?.axo?.sdk_client_token;
|
const sdkClientToken = config?.axo?.sdk_client_token;
|
||||||
const uuid = uuidv4().replace( /-/g, '' );
|
const uuid = uuidv4().replace( /-/g, '' );
|
||||||
if ( sdkClientToken ) {
|
if ( sdkClientToken && config?.user?.is_logged !== true ) {
|
||||||
scriptOptions[ 'data-sdk-client-token' ] = sdkClientToken;
|
scriptOptions[ 'data-sdk-client-token' ] = sdkClientToken;
|
||||||
scriptOptions[ 'data-client-metadata-id' ] = uuid;
|
scriptOptions[ 'data-client-metadata-id' ] = uuid;
|
||||||
}
|
}
|
||||||
return scriptOptions;
|
return scriptOptions;
|
||||||
};
|
};
|
||||||
|
|
||||||
const processUserIdToken = ( config, sdkClientToken ) => {
|
const processUserIdToken = ( config ) => {
|
||||||
const userIdToken = config?.save_payment_methods?.id_token;
|
const userIdToken = config?.save_payment_methods?.id_token;
|
||||||
return userIdToken && ! sdkClientToken
|
return userIdToken && config?.user?.is_logged === true
|
||||||
? { 'data-user-id-token': userIdToken }
|
? { 'data-user-id-token': userIdToken }
|
||||||
: {};
|
: {};
|
||||||
};
|
};
|
||||||
|
@ -26,9 +26,6 @@ export const processConfig = ( config ) => {
|
||||||
scriptOptions = merge( scriptOptions, config.script_attributes );
|
scriptOptions = merge( scriptOptions, config.script_attributes );
|
||||||
}
|
}
|
||||||
const axoOptions = processAxoConfig( config );
|
const axoOptions = processAxoConfig( config );
|
||||||
const userIdTokenOptions = processUserIdToken(
|
const userIdTokenOptions = processUserIdToken( config );
|
||||||
config,
|
|
||||||
axoOptions[ 'data-sdk-client-token' ]
|
|
||||||
);
|
|
||||||
return merge.all( [ scriptOptions, axoOptions, userIdTokenOptions ] );
|
return merge.all( [ scriptOptions, axoOptions, userIdTokenOptions ] );
|
||||||
};
|
};
|
||||||
|
|
|
@ -9,7 +9,7 @@ const scriptPromises = new Map();
|
||||||
const handleDataClientIdAttribute = async ( scriptOptions, config ) => {
|
const handleDataClientIdAttribute = async ( scriptOptions, config ) => {
|
||||||
if (
|
if (
|
||||||
config.data_client_id?.set_attribute &&
|
config.data_client_id?.set_attribute &&
|
||||||
config.vault_v3_enabled !== '1'
|
config.vault_v3_enabled !== true
|
||||||
) {
|
) {
|
||||||
return new Promise( ( resolve, reject ) => {
|
return new Promise( ( resolve, reject ) => {
|
||||||
dataClientIdAttributeHandler(
|
dataClientIdAttributeHandler(
|
||||||
|
|
|
@ -75,7 +75,7 @@ export const loadPaypalScript = ( config, onLoaded, onError = null ) => {
|
||||||
// Axo SDK options
|
// Axo SDK options
|
||||||
const sdkClientToken = config?.axo?.sdk_client_token;
|
const sdkClientToken = config?.axo?.sdk_client_token;
|
||||||
const uuid = uuidv4().replace( /-/g, '' );
|
const uuid = uuidv4().replace( /-/g, '' );
|
||||||
if ( sdkClientToken ) {
|
if ( sdkClientToken && config?.user?.is_logged !== true ) {
|
||||||
scriptOptions[ 'data-sdk-client-token' ] = sdkClientToken;
|
scriptOptions[ 'data-sdk-client-token' ] = sdkClientToken;
|
||||||
scriptOptions[ 'data-client-metadata-id' ] = uuid;
|
scriptOptions[ 'data-client-metadata-id' ] = uuid;
|
||||||
}
|
}
|
||||||
|
@ -96,7 +96,7 @@ export const loadPaypalScript = ( config, onLoaded, onError = null ) => {
|
||||||
|
|
||||||
// Adds data-user-id-token to script options.
|
// Adds data-user-id-token to script options.
|
||||||
const userIdToken = config?.save_payment_methods?.id_token;
|
const userIdToken = config?.save_payment_methods?.id_token;
|
||||||
if ( userIdToken && ! sdkClientToken ) {
|
if ( userIdToken && config?.user?.is_logged === true ) {
|
||||||
scriptOptions[ 'data-user-id-token' ] = userIdToken;
|
scriptOptions[ 'data-user-id-token' ] = userIdToken;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ import {
|
||||||
handleShippingOptionsChange,
|
handleShippingOptionsChange,
|
||||||
handleShippingAddressChange,
|
handleShippingAddressChange,
|
||||||
} from '../Helper/ShippingHandler.js';
|
} from '../Helper/ShippingHandler.js';
|
||||||
|
import { PaymentContext } from '../Helper/CheckoutMethodState';
|
||||||
|
|
||||||
class Renderer {
|
class Renderer {
|
||||||
constructor(
|
constructor(
|
||||||
|
@ -28,6 +29,22 @@ class Renderer {
|
||||||
this.reloadEventName = 'ppcp-reload-buttons';
|
this.reloadEventName = 'ppcp-reload-buttons';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine is PayPal smart buttons are used by inspecting the existing plugin configuration:
|
||||||
|
* If the url-param "components" contains a "buttons" element, smart buttons are enabled.
|
||||||
|
*
|
||||||
|
* @return {boolean} True, if smart buttons are present on the page.
|
||||||
|
*/
|
||||||
|
get useSmartButtons() {
|
||||||
|
if ( PaymentContext.Preview === this.defaultSettings?.context ) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const components = this.defaultSettings?.url_params?.components || '';
|
||||||
|
|
||||||
|
return components.split( ',' ).includes( 'buttons' );
|
||||||
|
}
|
||||||
|
|
||||||
render(
|
render(
|
||||||
contextConfig,
|
contextConfig,
|
||||||
settingsOverride = {},
|
settingsOverride = {},
|
||||||
|
@ -44,12 +61,14 @@ class Renderer {
|
||||||
Object.keys( enabledSeparateGateways ).length !== 0;
|
Object.keys( enabledSeparateGateways ).length !== 0;
|
||||||
|
|
||||||
if ( ! hasEnabledSeparateGateways ) {
|
if ( ! hasEnabledSeparateGateways ) {
|
||||||
this.renderButtons(
|
if ( this.useSmartButtons ) {
|
||||||
settings.button.wrapper,
|
this.renderButtons(
|
||||||
settings.button.style,
|
settings.button.wrapper,
|
||||||
contextConfig,
|
settings.button.style,
|
||||||
hasEnabledSeparateGateways
|
contextConfig,
|
||||||
);
|
hasEnabledSeparateGateways
|
||||||
|
);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// render each button separately
|
// render each button separately
|
||||||
for ( const fundingSource of paypal
|
for ( const fundingSource of paypal
|
||||||
|
@ -141,7 +160,7 @@ class Renderer {
|
||||||
// Check the condition and add the handler if needed
|
// Check the condition and add the handler if needed
|
||||||
if ( this.shouldEnableShippingCallback() ) {
|
if ( this.shouldEnableShippingCallback() ) {
|
||||||
options.onShippingOptionsChange = ( data, actions ) => {
|
options.onShippingOptionsChange = ( data, actions ) => {
|
||||||
let shippingOptionsChange =
|
const shippingOptionsChange =
|
||||||
! this.isVenmoButtonClickedWhenVaultingIsEnabled(
|
! this.isVenmoButtonClickedWhenVaultingIsEnabled(
|
||||||
venmoButtonClicked
|
venmoButtonClicked
|
||||||
)
|
)
|
||||||
|
@ -152,10 +171,10 @@ class Renderer {
|
||||||
)
|
)
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
return shippingOptionsChange
|
return shippingOptionsChange;
|
||||||
};
|
};
|
||||||
options.onShippingAddressChange = ( data, actions ) => {
|
options.onShippingAddressChange = ( data, actions ) => {
|
||||||
let shippingAddressChange =
|
const shippingAddressChange =
|
||||||
! this.isVenmoButtonClickedWhenVaultingIsEnabled(
|
! this.isVenmoButtonClickedWhenVaultingIsEnabled(
|
||||||
venmoButtonClicked
|
venmoButtonClicked
|
||||||
)
|
)
|
||||||
|
@ -166,7 +185,7 @@ class Renderer {
|
||||||
)
|
)
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
return shippingAddressChange
|
return shippingAddressChange;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -228,8 +247,13 @@ class Renderer {
|
||||||
};
|
};
|
||||||
|
|
||||||
shouldEnableShippingCallback = () => {
|
shouldEnableShippingCallback = () => {
|
||||||
let needShipping = this.defaultSettings.needShipping || this.defaultSettings.context === 'product'
|
const needShipping =
|
||||||
return this.defaultSettings.should_handle_shipping_in_paypal && needShipping
|
this.defaultSettings.needShipping ||
|
||||||
|
this.defaultSettings.context === 'product';
|
||||||
|
return (
|
||||||
|
this.defaultSettings.should_handle_shipping_in_paypal &&
|
||||||
|
needShipping
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
isAlreadyRendered( wrapper, fundingSource ) {
|
isAlreadyRendered( wrapper, fundingSource ) {
|
||||||
|
|
|
@ -38,6 +38,7 @@ use WooCommerce\PayPalCommerce\Button\Helper\ThreeDSecure;
|
||||||
use WooCommerce\PayPalCommerce\Onboarding\Environment;
|
use WooCommerce\PayPalCommerce\Onboarding\Environment;
|
||||||
use WooCommerce\PayPalCommerce\Onboarding\State;
|
use WooCommerce\PayPalCommerce\Onboarding\State;
|
||||||
use WooCommerce\PayPalCommerce\WcGateway\Helper\SettingsStatus;
|
use WooCommerce\PayPalCommerce\WcGateway\Helper\SettingsStatus;
|
||||||
|
use WooCommerce\PayPalCommerce\WcGateway\Helper\DCCGatewayConfiguration;
|
||||||
|
|
||||||
return array(
|
return array(
|
||||||
'button.client_id' => static function ( ContainerInterface $container ): string {
|
'button.client_id' => static function ( ContainerInterface $container ): string {
|
||||||
|
@ -108,9 +109,18 @@ return array(
|
||||||
assert( $settings_status instanceof SettingsStatus );
|
assert( $settings_status instanceof SettingsStatus );
|
||||||
|
|
||||||
if ( in_array( $context, array( 'checkout', 'pay-now' ), true ) ) {
|
if ( in_array( $context, array( 'checkout', 'pay-now' ), true ) ) {
|
||||||
if ( $container->get( 'wcgateway.use-place-order-button' )
|
$redirect_to_pay = $container->get( 'wcgateway.use-place-order-button' );
|
||||||
|| ! $settings_status->is_smart_button_enabled_for_location( $context )
|
if ( $redirect_to_pay ) {
|
||||||
) {
|
// No smart buttons, redirect the current page to PayPal for payment.
|
||||||
|
return new DisabledSmartButton();
|
||||||
|
}
|
||||||
|
|
||||||
|
$no_smart_buttons = ! $settings_status->is_smart_button_enabled_for_location( $context );
|
||||||
|
$dcc_configuration = $container->get( 'wcgateway.configuration.dcc' );
|
||||||
|
assert( $dcc_configuration instanceof DCCGatewayConfiguration );
|
||||||
|
|
||||||
|
if ( $no_smart_buttons && ! $dcc_configuration->is_enabled() ) {
|
||||||
|
// Smart buttons disabled, and also not using advanced card payments.
|
||||||
return new DisabledSmartButton();
|
return new DisabledSmartButton();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1594,9 +1594,16 @@ document.querySelector("#payment").before(document.querySelector(".ppcp-messages
|
||||||
*
|
*
|
||||||
* @internal Matches filter name in APM extension.
|
* @internal Matches filter name in APM extension.
|
||||||
*
|
*
|
||||||
* @param array $components The array of components already registered.
|
* @param array $components The array of components already registered.
|
||||||
|
* @param string $context The SmartButton context.
|
||||||
*/
|
*/
|
||||||
return apply_filters( 'woocommerce_paypal_payments_sdk_components_hook', $components );
|
return array_unique(
|
||||||
|
(array) apply_filters(
|
||||||
|
'woocommerce_paypal_payments_sdk_components_hook',
|
||||||
|
$components,
|
||||||
|
$this->context()
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -46,12 +46,6 @@ class CardFieldsModule implements ServiceModule, ExtendingModule, ExecutableModu
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
$dcc_configuration = $c->get( 'wcgateway.configuration.dcc' );
|
|
||||||
assert( $dcc_configuration instanceof DCCGatewayConfiguration );
|
|
||||||
if ( ! $dcc_configuration->is_enabled() ) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Param types removed to avoid third-party issues.
|
* Param types removed to avoid third-party issues.
|
||||||
*
|
*
|
||||||
|
@ -59,7 +53,10 @@ class CardFieldsModule implements ServiceModule, ExtendingModule, ExecutableModu
|
||||||
*/
|
*/
|
||||||
add_filter(
|
add_filter(
|
||||||
'woocommerce_paypal_payments_sdk_components_hook',
|
'woocommerce_paypal_payments_sdk_components_hook',
|
||||||
function( $components ) {
|
function( $components ) use ( $c ) {
|
||||||
|
if ( ! $c->get( 'wcgateway.configuration.dcc' )->is_enabled() ) {
|
||||||
|
return $components;
|
||||||
|
}
|
||||||
if ( in_array( 'hosted-fields', $components, true ) ) {
|
if ( in_array( 'hosted-fields', $components, true ) ) {
|
||||||
$key = array_search( 'hosted-fields', $components, true );
|
$key = array_search( 'hosted-fields', $components, true );
|
||||||
if ( $key !== false ) {
|
if ( $key !== false ) {
|
||||||
|
@ -80,7 +77,10 @@ class CardFieldsModule implements ServiceModule, ExtendingModule, ExecutableModu
|
||||||
* @psalm-suppress MissingClosureReturnType
|
* @psalm-suppress MissingClosureReturnType
|
||||||
* @psalm-suppress MissingClosureParamType
|
* @psalm-suppress MissingClosureParamType
|
||||||
*/
|
*/
|
||||||
function( $default_fields, $id ) {
|
function( $default_fields, $id ) use ( $c ) {
|
||||||
|
if ( ! $c->get( 'wcgateway.configuration.dcc' )->is_enabled() ) {
|
||||||
|
return $default_fields;
|
||||||
|
}
|
||||||
if ( CreditCardGateway::ID === $id && apply_filters( 'woocommerce_paypal_payments_enable_cardholder_name_field', false ) ) {
|
if ( CreditCardGateway::ID === $id && apply_filters( 'woocommerce_paypal_payments_enable_cardholder_name_field', false ) ) {
|
||||||
$default_fields['card-name-field'] = '<p class="form-row form-row-wide">
|
$default_fields['card-name-field'] = '<p class="form-row form-row-wide">
|
||||||
<label for="ppcp-credit-card-gateway-card-name">' . esc_attr__( 'Cardholder Name', 'woocommerce-paypal-payments' ) . '</label>
|
<label for="ppcp-credit-card-gateway-card-name">' . esc_attr__( 'Cardholder Name', 'woocommerce-paypal-payments' ) . '</label>
|
||||||
|
@ -113,6 +113,9 @@ class CardFieldsModule implements ServiceModule, ExtendingModule, ExecutableModu
|
||||||
add_filter(
|
add_filter(
|
||||||
'ppcp_create_order_request_body_data',
|
'ppcp_create_order_request_body_data',
|
||||||
function( array $data, string $payment_method ) use ( $c ): array {
|
function( array $data, string $payment_method ) use ( $c ): array {
|
||||||
|
if ( ! $c->get( 'wcgateway.configuration.dcc' )->is_enabled() ) {
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
// phpcs:ignore WordPress.Security.NonceVerification.Missing
|
// phpcs:ignore WordPress.Security.NonceVerification.Missing
|
||||||
if ( $payment_method !== CreditCardGateway::ID ) {
|
if ( $payment_method !== CreditCardGateway::ID ) {
|
||||||
return $data;
|
return $data;
|
||||||
|
|
|
@ -115,4 +115,43 @@ return array(
|
||||||
$container->get( 'api.bearer' )
|
$container->get( 'api.bearer' )
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configuration for the new/old settings map.
|
||||||
|
*
|
||||||
|
* @returns SettingsMap[]
|
||||||
|
*/
|
||||||
|
'compat.setting.new-to-old-map' => function( ContainerInterface $container ) : array {
|
||||||
|
$are_new_settings_enabled = $container->get( 'wcgateway.settings.admin-settings-enabled' );
|
||||||
|
if ( ! $are_new_settings_enabled ) {
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
|
||||||
|
return array(
|
||||||
|
new SettingsMap(
|
||||||
|
$container->get( 'settings.data.common' ),
|
||||||
|
array(
|
||||||
|
'client_id' => 'client_id',
|
||||||
|
'client_secret' => 'client_secret',
|
||||||
|
)
|
||||||
|
),
|
||||||
|
new SettingsMap(
|
||||||
|
$container->get( 'settings.data.general' ),
|
||||||
|
array(
|
||||||
|
'is_sandbox' => 'sandbox_on',
|
||||||
|
'live_client_id' => 'client_id_production',
|
||||||
|
'live_client_secret' => 'client_secret_production',
|
||||||
|
'live_merchant_id' => 'merchant_id_production',
|
||||||
|
'live_merchant_email' => 'merchant_email_production',
|
||||||
|
'sandbox_client_id' => 'client_id_sandbox',
|
||||||
|
'sandbox_client_secret' => 'client_secret_sandbox',
|
||||||
|
'sandbox_merchant_id' => 'merchant_id_sandbox',
|
||||||
|
'sandbox_merchant_email' => 'merchant_email_sandbox',
|
||||||
|
)
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
'compat.settings.settings_map_helper' => static function( ContainerInterface $container ) : SettingsMapHelper {
|
||||||
|
return new SettingsMapHelper( $container->get( 'compat.setting.new-to-old-map' ) );
|
||||||
|
},
|
||||||
);
|
);
|
||||||
|
|
|
@ -51,14 +51,24 @@ class CompatModule implements ServiceModule, ExtendingModule, ExecutableModule {
|
||||||
*/
|
*/
|
||||||
public function run( ContainerInterface $c ): bool {
|
public function run( ContainerInterface $c ): bool {
|
||||||
|
|
||||||
$this->initialize_ppec_compat_layer( $c );
|
add_action(
|
||||||
$this->initialize_tracking_compat_layer( $c );
|
'woocommerce_init',
|
||||||
|
function() use ( $c ) {
|
||||||
|
$this->initialize_ppec_compat_layer( $c );
|
||||||
|
$this->initialize_tracking_compat_layer( $c );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
$asset_loader = $c->get( 'compat.assets' );
|
add_action(
|
||||||
assert( $asset_loader instanceof CompatAssets );
|
'init',
|
||||||
|
function() use ( $c ) {
|
||||||
|
$asset_loader = $c->get( 'compat.assets' );
|
||||||
|
assert( $asset_loader instanceof CompatAssets );
|
||||||
|
|
||||||
add_action( 'init', array( $asset_loader, 'register' ) );
|
$asset_loader->register();
|
||||||
add_action( 'admin_enqueue_scripts', array( $asset_loader, 'enqueue' ) );
|
add_action( 'admin_enqueue_scripts', array( $asset_loader, 'enqueue' ) );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
$this->migrate_pay_later_settings( $c );
|
$this->migrate_pay_later_settings( $c );
|
||||||
$this->migrate_smart_button_settings( $c );
|
$this->migrate_smart_button_settings( $c );
|
||||||
|
@ -72,11 +82,9 @@ class CompatModule implements ServiceModule, ExtendingModule, ExecutableModule {
|
||||||
$this->initialize_nyp_compat_layer();
|
$this->initialize_nyp_compat_layer();
|
||||||
}
|
}
|
||||||
|
|
||||||
$logger = $c->get( 'woocommerce.logger.woocommerce' );
|
|
||||||
|
|
||||||
$is_wc_bookings_active = $c->get( 'compat.wc_bookings.is_supported_plugin_version_active' );
|
$is_wc_bookings_active = $c->get( 'compat.wc_bookings.is_supported_plugin_version_active' );
|
||||||
if ( $is_wc_bookings_active ) {
|
if ( $is_wc_bookings_active ) {
|
||||||
$this->initialize_wc_bookings_compat_layer( $logger );
|
$this->initialize_wc_bookings_compat_layer( $c );
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -427,13 +435,13 @@ class CompatModule implements ServiceModule, ExtendingModule, ExecutableModule {
|
||||||
/**
|
/**
|
||||||
* Sets up the compatibility layer for WooCommerce Bookings plugin.
|
* Sets up the compatibility layer for WooCommerce Bookings plugin.
|
||||||
*
|
*
|
||||||
* @param LoggerInterface $logger The logger.
|
* @param ContainerInterface $container The logger.
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
protected function initialize_wc_bookings_compat_layer( LoggerInterface $logger ): void {
|
protected function initialize_wc_bookings_compat_layer( ContainerInterface $container ): void {
|
||||||
add_action(
|
add_action(
|
||||||
'woocommerce_paypal_payments_shipping_callback_woocommerce_order_created',
|
'woocommerce_paypal_payments_shipping_callback_woocommerce_order_created',
|
||||||
static function ( WC_Order $wc_order, WC_Cart $wc_cart ) use ( $logger ): void {
|
static function ( WC_Order $wc_order, WC_Cart $wc_cart ) use ( $container ): void {
|
||||||
try {
|
try {
|
||||||
$cart_contents = $wc_cart->get_cart();
|
$cart_contents = $wc_cart->get_cart();
|
||||||
foreach ( $cart_contents as $cart_item ) {
|
foreach ( $cart_contents as $cart_item ) {
|
||||||
|
@ -474,7 +482,7 @@ class CompatModule implements ServiceModule, ExtendingModule, ExecutableModule {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch ( Exception $exception ) {
|
} catch ( Exception $exception ) {
|
||||||
$logger->warning( 'Failed to create booking for WooCommerce Bookings plugin: ' . $exception->getMessage() );
|
$container->get( 'woocommerce.logger.woocommerce' )->warning( 'Failed to create booking for WooCommerce Bookings plugin: ' . $exception->getMessage() );
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
10,
|
10,
|
||||||
|
|
63
modules/ppcp-compat/src/SettingsMap.php
Normal file
63
modules/ppcp-compat/src/SettingsMap.php
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* A map of new to old settings.
|
||||||
|
*
|
||||||
|
* @package WooCommerce\PayPalCommerce\Compat
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace WooCommerce\PayPalCommerce\Compat;
|
||||||
|
|
||||||
|
use WooCommerce\PayPalCommerce\Settings\Data\AbstractDataModel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A map of new to old settings.
|
||||||
|
*
|
||||||
|
* @psalm-type newSettingsKey = string
|
||||||
|
* @psalm-type oldSettingsKey = string
|
||||||
|
*/
|
||||||
|
class SettingsMap {
|
||||||
|
/**
|
||||||
|
* The new settings model.
|
||||||
|
*
|
||||||
|
* @var AbstractDataModel
|
||||||
|
*/
|
||||||
|
private AbstractDataModel $model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The map of the new setting key to the old setting keys.
|
||||||
|
*
|
||||||
|
* @var array<newSettingsKey, oldSettingsKey>
|
||||||
|
*/
|
||||||
|
private array $map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The constructor.
|
||||||
|
*
|
||||||
|
* @param AbstractDataModel $model The new settings model.
|
||||||
|
* @param array<newSettingsKey, oldSettingsKey> $map The map of the new setting key to the old setting keys.
|
||||||
|
*/
|
||||||
|
public function __construct( AbstractDataModel $model, array $map ) {
|
||||||
|
$this->model = $model;
|
||||||
|
$this->map = $map;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The model.
|
||||||
|
*
|
||||||
|
* @return AbstractDataModel
|
||||||
|
*/
|
||||||
|
public function get_model(): AbstractDataModel {
|
||||||
|
return $this->model;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The map of the new setting key to the old setting keys.
|
||||||
|
*
|
||||||
|
* @return array<newSettingsKey, oldSettingsKey>
|
||||||
|
*/
|
||||||
|
public function get_map(): array {
|
||||||
|
return $this->map;
|
||||||
|
}
|
||||||
|
}
|
70
modules/ppcp-compat/src/SettingsMapHelper.php
Normal file
70
modules/ppcp-compat/src/SettingsMapHelper.php
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* A helper for mapping the new/old settings.
|
||||||
|
*
|
||||||
|
* @package WooCommerce\PayPalCommerce\Compat
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace WooCommerce\PayPalCommerce\Compat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A helper for mapping the new/old settings.
|
||||||
|
*/
|
||||||
|
class SettingsMapHelper {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A list of mapped settings.
|
||||||
|
*
|
||||||
|
* @var SettingsMap[]
|
||||||
|
*/
|
||||||
|
protected array $settings_map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*
|
||||||
|
* @param SettingsMap[] $settings_map A list of mapped settings.
|
||||||
|
*/
|
||||||
|
public function __construct( array $settings_map ) {
|
||||||
|
$this->settings_map = $settings_map;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the mapped value from the new settings.
|
||||||
|
*
|
||||||
|
* @param string $key The key.
|
||||||
|
* @return ?mixed the mapped value or Null if it doesn't exist.
|
||||||
|
*/
|
||||||
|
public function mapped_value( string $key ) {
|
||||||
|
if ( ! $this->has_mapped_key( $key ) ) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ( $this->settings_map as $settings_map ) {
|
||||||
|
$mapped_key = array_search( $key, $settings_map->get_map(), true );
|
||||||
|
$new_settings = $settings_map->get_model()->to_array();
|
||||||
|
if ( ! empty( $new_settings[ $mapped_key ] ) ) {
|
||||||
|
return $new_settings[ $mapped_key ];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the given key exists in the new settings.
|
||||||
|
*
|
||||||
|
* @param string $key The key.
|
||||||
|
* @return bool true if the given key exists in the new settings, otherwise false.
|
||||||
|
*/
|
||||||
|
public function has_mapped_key( string $key ) : bool {
|
||||||
|
foreach ( $this->settings_map as $settings_map ) {
|
||||||
|
if ( in_array( $key, $settings_map->get_map(), true ) ) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
|
@ -44,12 +44,6 @@ class LocalAlternativePaymentMethodsModule implements ServiceModule, ExtendingMo
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
public function run( ContainerInterface $c ): bool {
|
public function run( ContainerInterface $c ): bool {
|
||||||
$settings = $c->get( 'wcgateway.settings' );
|
|
||||||
assert( $settings instanceof Settings );
|
|
||||||
|
|
||||||
if ( ! self::should_add_local_apm_gateways( $settings ) ) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
add_filter(
|
add_filter(
|
||||||
'woocommerce_payment_gateways',
|
'woocommerce_payment_gateways',
|
||||||
|
@ -59,6 +53,9 @@ class LocalAlternativePaymentMethodsModule implements ServiceModule, ExtendingMo
|
||||||
* @psalm-suppress MissingClosureParamType
|
* @psalm-suppress MissingClosureParamType
|
||||||
*/
|
*/
|
||||||
function ( $methods ) use ( $c ) {
|
function ( $methods ) use ( $c ) {
|
||||||
|
if ( ! self::should_add_local_apm_gateways( $c ) ) {
|
||||||
|
return $methods;
|
||||||
|
}
|
||||||
$onboarding_state = $c->get( 'onboarding.state' );
|
$onboarding_state = $c->get( 'onboarding.state' );
|
||||||
if ( $onboarding_state->current_state() === State::STATE_START ) {
|
if ( $onboarding_state->current_state() === State::STATE_START ) {
|
||||||
return $methods;
|
return $methods;
|
||||||
|
@ -85,6 +82,9 @@ class LocalAlternativePaymentMethodsModule implements ServiceModule, ExtendingMo
|
||||||
* @psalm-suppress MissingClosureParamType
|
* @psalm-suppress MissingClosureParamType
|
||||||
*/
|
*/
|
||||||
function ( $methods ) use ( $c ) {
|
function ( $methods ) use ( $c ) {
|
||||||
|
if ( ! self::should_add_local_apm_gateways( $c ) ) {
|
||||||
|
return $methods;
|
||||||
|
}
|
||||||
if ( ! is_array( $methods ) ) {
|
if ( ! is_array( $methods ) ) {
|
||||||
return $methods;
|
return $methods;
|
||||||
}
|
}
|
||||||
|
@ -115,6 +115,9 @@ class LocalAlternativePaymentMethodsModule implements ServiceModule, ExtendingMo
|
||||||
add_action(
|
add_action(
|
||||||
'woocommerce_blocks_payment_method_type_registration',
|
'woocommerce_blocks_payment_method_type_registration',
|
||||||
function( PaymentMethodRegistry $payment_method_registry ) use ( $c ): void {
|
function( PaymentMethodRegistry $payment_method_registry ) use ( $c ): void {
|
||||||
|
if ( ! self::should_add_local_apm_gateways( $c ) ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
$payment_methods = $c->get( 'ppcp-local-apms.payment-methods' );
|
$payment_methods = $c->get( 'ppcp-local-apms.payment-methods' );
|
||||||
foreach ( $payment_methods as $key => $value ) {
|
foreach ( $payment_methods as $key => $value ) {
|
||||||
$payment_method_registry->register( $c->get( 'ppcp-local-apms.' . $key . '.payment-method' ) );
|
$payment_method_registry->register( $c->get( 'ppcp-local-apms.' . $key . '.payment-method' ) );
|
||||||
|
@ -125,6 +128,9 @@ class LocalAlternativePaymentMethodsModule implements ServiceModule, ExtendingMo
|
||||||
add_filter(
|
add_filter(
|
||||||
'woocommerce_paypal_payments_localized_script_data',
|
'woocommerce_paypal_payments_localized_script_data',
|
||||||
function ( array $data ) use ( $c ) {
|
function ( array $data ) use ( $c ) {
|
||||||
|
if ( ! self::should_add_local_apm_gateways( $c ) ) {
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
$payment_methods = $c->get( 'ppcp-local-apms.payment-methods' );
|
$payment_methods = $c->get( 'ppcp-local-apms.payment-methods' );
|
||||||
|
|
||||||
$default_disable_funding = $data['url_params']['disable-funding'] ?? '';
|
$default_disable_funding = $data['url_params']['disable-funding'] ?? '';
|
||||||
|
@ -143,6 +149,9 @@ class LocalAlternativePaymentMethodsModule implements ServiceModule, ExtendingMo
|
||||||
* @psalm-suppress MissingClosureParamType
|
* @psalm-suppress MissingClosureParamType
|
||||||
*/
|
*/
|
||||||
function( $order_id ) use ( $c ) {
|
function( $order_id ) use ( $c ) {
|
||||||
|
if ( ! self::should_add_local_apm_gateways( $c ) ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
$order = wc_get_order( $order_id );
|
$order = wc_get_order( $order_id );
|
||||||
if ( ! $order instanceof WC_Order ) {
|
if ( ! $order instanceof WC_Order ) {
|
||||||
return;
|
return;
|
||||||
|
@ -175,6 +184,9 @@ class LocalAlternativePaymentMethodsModule implements ServiceModule, ExtendingMo
|
||||||
add_action(
|
add_action(
|
||||||
'woocommerce_paypal_payments_payment_capture_completed_webhook_handler',
|
'woocommerce_paypal_payments_payment_capture_completed_webhook_handler',
|
||||||
function( WC_Order $wc_order, string $order_id ) use ( $c ) {
|
function( WC_Order $wc_order, string $order_id ) use ( $c ) {
|
||||||
|
if ( ! self::should_add_local_apm_gateways( $c ) ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
$payment_methods = $c->get( 'ppcp-local-apms.payment-methods' );
|
$payment_methods = $c->get( 'ppcp-local-apms.payment-methods' );
|
||||||
if (
|
if (
|
||||||
! $this->is_local_apm( $wc_order->get_payment_method(), $payment_methods )
|
! $this->is_local_apm( $wc_order->get_payment_method(), $payment_methods )
|
||||||
|
@ -214,10 +226,12 @@ class LocalAlternativePaymentMethodsModule implements ServiceModule, ExtendingMo
|
||||||
/**
|
/**
|
||||||
* Check if the local APMs should be added to the available payment gateways.
|
* Check if the local APMs should be added to the available payment gateways.
|
||||||
*
|
*
|
||||||
* @param Settings $settings PayPal gateway settings.
|
* @param ContainerInterface $container Container.
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
private function should_add_local_apm_gateways( Settings $settings ): bool {
|
private function should_add_local_apm_gateways( ContainerInterface $container ): bool {
|
||||||
|
$settings = $container->get( 'wcgateway.settings' );
|
||||||
|
assert( $settings instanceof Settings );
|
||||||
return $settings->has( 'enabled' )
|
return $settings->has( 'enabled' )
|
||||||
&& $settings->get( 'enabled' ) === true
|
&& $settings->get( 'enabled' ) === true
|
||||||
&& $settings->has( 'allow_local_apm_gateways' )
|
&& $settings->has( 'allow_local_apm_gateways' )
|
||||||
|
|
|
@ -15,7 +15,6 @@ use WooCommerce\PayPalCommerce\ApiClient\Authentication\Bearer;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Authentication\ConnectBearer;
|
use WooCommerce\PayPalCommerce\ApiClient\Authentication\ConnectBearer;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Authentication\PayPalBearer;
|
use WooCommerce\PayPalCommerce\ApiClient\Authentication\PayPalBearer;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\LoginSeller;
|
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\LoginSeller;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PartnerReferrals;
|
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Helper\Cache;
|
use WooCommerce\PayPalCommerce\ApiClient\Helper\Cache;
|
||||||
use WooCommerce\PayPalCommerce\Onboarding\Assets\OnboardingAssets;
|
use WooCommerce\PayPalCommerce\Onboarding\Assets\OnboardingAssets;
|
||||||
use WooCommerce\PayPalCommerce\Onboarding\Endpoint\LoginSellerEndpoint;
|
use WooCommerce\PayPalCommerce\Onboarding\Endpoint\LoginSellerEndpoint;
|
||||||
|
@ -25,7 +24,7 @@ use WooCommerce\PayPalCommerce\Onboarding\Render\OnboardingRenderer;
|
||||||
use WooCommerce\PayPalCommerce\Onboarding\OnboardingRESTController;
|
use WooCommerce\PayPalCommerce\Onboarding\OnboardingRESTController;
|
||||||
|
|
||||||
return array(
|
return array(
|
||||||
'api.sandbox-host' => static function ( ContainerInterface $container ): string {
|
'api.sandbox-host' => static function ( ContainerInterface $container ): string {
|
||||||
|
|
||||||
$state = $container->get( 'onboarding.state' );
|
$state = $container->get( 'onboarding.state' );
|
||||||
|
|
||||||
|
@ -39,7 +38,7 @@ return array(
|
||||||
}
|
}
|
||||||
return CONNECT_WOO_SANDBOX_URL;
|
return CONNECT_WOO_SANDBOX_URL;
|
||||||
},
|
},
|
||||||
'api.production-host' => static function ( ContainerInterface $container ): string {
|
'api.production-host' => static function ( ContainerInterface $container ): string {
|
||||||
|
|
||||||
$state = $container->get( 'onboarding.state' );
|
$state = $container->get( 'onboarding.state' );
|
||||||
|
|
||||||
|
@ -54,7 +53,7 @@ return array(
|
||||||
}
|
}
|
||||||
return CONNECT_WOO_URL;
|
return CONNECT_WOO_URL;
|
||||||
},
|
},
|
||||||
'api.host' => static function ( ContainerInterface $container ): string {
|
'api.host' => static function ( ContainerInterface $container ): string {
|
||||||
$environment = $container->get( 'onboarding.environment' );
|
$environment = $container->get( 'onboarding.environment' );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -66,25 +65,7 @@ return array(
|
||||||
? (string) $container->get( 'api.sandbox-host' ) : (string) $container->get( 'api.production-host' );
|
? (string) $container->get( 'api.sandbox-host' ) : (string) $container->get( 'api.production-host' );
|
||||||
|
|
||||||
},
|
},
|
||||||
'api.paypal-host-production' => static function( ContainerInterface $container ) : string {
|
'api.paypal-host' => function( ContainerInterface $container ) : string {
|
||||||
return PAYPAL_API_URL;
|
|
||||||
},
|
|
||||||
'api.paypal-host-sandbox' => static function( ContainerInterface $container ) : string {
|
|
||||||
return PAYPAL_SANDBOX_API_URL;
|
|
||||||
},
|
|
||||||
'api.paypal-website-url-production' => static function( ContainerInterface $container ) : string {
|
|
||||||
return PAYPAL_URL;
|
|
||||||
},
|
|
||||||
'api.paypal-website-url-sandbox' => static function( ContainerInterface $container ) : string {
|
|
||||||
return PAYPAL_SANDBOX_URL;
|
|
||||||
},
|
|
||||||
'api.partner_merchant_id-production' => static function( ContainerInterface $container ) : string {
|
|
||||||
return CONNECT_WOO_MERCHANT_ID;
|
|
||||||
},
|
|
||||||
'api.partner_merchant_id-sandbox' => static function( ContainerInterface $container ) : string {
|
|
||||||
return CONNECT_WOO_SANDBOX_MERCHANT_ID;
|
|
||||||
},
|
|
||||||
'api.paypal-host' => function( ContainerInterface $container ) : string {
|
|
||||||
$environment = $container->get( 'onboarding.environment' );
|
$environment = $container->get( 'onboarding.environment' );
|
||||||
/**
|
/**
|
||||||
* The current environment.
|
* The current environment.
|
||||||
|
@ -97,7 +78,7 @@ return array(
|
||||||
return $container->get( 'api.paypal-host-production' );
|
return $container->get( 'api.paypal-host-production' );
|
||||||
|
|
||||||
},
|
},
|
||||||
'api.paypal-website-url' => function( ContainerInterface $container ) : string {
|
'api.paypal-website-url' => function( ContainerInterface $container ) : string {
|
||||||
$environment = $container->get( 'onboarding.environment' );
|
$environment = $container->get( 'onboarding.environment' );
|
||||||
assert( $environment instanceof Environment );
|
assert( $environment instanceof Environment );
|
||||||
if ( $environment->current_environment_is( Environment::SANDBOX ) ) {
|
if ( $environment->current_environment_is( Environment::SANDBOX ) ) {
|
||||||
|
@ -107,7 +88,7 @@ return array(
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
'api.bearer' => static function ( ContainerInterface $container ): Bearer {
|
'api.bearer' => static function ( ContainerInterface $container ): Bearer {
|
||||||
|
|
||||||
$state = $container->get( 'onboarding.state' );
|
$state = $container->get( 'onboarding.state' );
|
||||||
|
|
||||||
|
@ -134,16 +115,16 @@ return array(
|
||||||
$settings
|
$settings
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
'onboarding.state' => function( ContainerInterface $container ) : State {
|
'onboarding.state' => function( ContainerInterface $container ) : State {
|
||||||
$settings = $container->get( 'wcgateway.settings' );
|
$settings = $container->get( 'wcgateway.settings' );
|
||||||
return new State( $settings );
|
return new State( $settings );
|
||||||
},
|
},
|
||||||
'onboarding.environment' => function( ContainerInterface $container ) : Environment {
|
'onboarding.environment' => function( ContainerInterface $container ) : Environment {
|
||||||
$settings = $container->get( 'wcgateway.settings' );
|
$settings = $container->get( 'wcgateway.settings' );
|
||||||
return new Environment( $settings );
|
return new Environment( $settings );
|
||||||
},
|
},
|
||||||
|
|
||||||
'onboarding.assets' => function( ContainerInterface $container ) : OnboardingAssets {
|
'onboarding.assets' => function( ContainerInterface $container ) : OnboardingAssets {
|
||||||
$state = $container->get( 'onboarding.state' );
|
$state = $container->get( 'onboarding.state' );
|
||||||
$login_seller_endpoint = $container->get( 'onboarding.endpoint.login-seller' );
|
$login_seller_endpoint = $container->get( 'onboarding.endpoint.login-seller' );
|
||||||
return new OnboardingAssets(
|
return new OnboardingAssets(
|
||||||
|
@ -156,14 +137,14 @@ return array(
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
'onboarding.url' => static function ( ContainerInterface $container ): string {
|
'onboarding.url' => static function ( ContainerInterface $container ): string {
|
||||||
return plugins_url(
|
return plugins_url(
|
||||||
'/modules/ppcp-onboarding/',
|
'/modules/ppcp-onboarding/',
|
||||||
dirname( realpath( __FILE__ ), 3 ) . '/woocommerce-paypal-payments.php'
|
dirname( realpath( __FILE__ ), 3 ) . '/woocommerce-paypal-payments.php'
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
'api.endpoint.login-seller-production' => static function ( ContainerInterface $container ) : LoginSeller {
|
'api.endpoint.login-seller-production' => static function ( ContainerInterface $container ) : LoginSeller {
|
||||||
|
|
||||||
$logger = $container->get( 'woocommerce.logger.woocommerce' );
|
$logger = $container->get( 'woocommerce.logger.woocommerce' );
|
||||||
return new LoginSeller(
|
return new LoginSeller(
|
||||||
|
@ -173,7 +154,7 @@ return array(
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
'api.endpoint.login-seller-sandbox' => static function ( ContainerInterface $container ) : LoginSeller {
|
'api.endpoint.login-seller-sandbox' => static function ( ContainerInterface $container ) : LoginSeller {
|
||||||
|
|
||||||
$logger = $container->get( 'woocommerce.logger.woocommerce' );
|
$logger = $container->get( 'woocommerce.logger.woocommerce' );
|
||||||
return new LoginSeller(
|
return new LoginSeller(
|
||||||
|
@ -183,7 +164,7 @@ return array(
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
'onboarding.endpoint.login-seller' => static function ( ContainerInterface $container ) : LoginSellerEndpoint {
|
'onboarding.endpoint.login-seller' => static function ( ContainerInterface $container ) : LoginSellerEndpoint {
|
||||||
|
|
||||||
$request_data = $container->get( 'button.request-data' );
|
$request_data = $container->get( 'button.request-data' );
|
||||||
$login_seller_production = $container->get( 'api.endpoint.login-seller-production' );
|
$login_seller_production = $container->get( 'api.endpoint.login-seller-production' );
|
||||||
|
@ -203,7 +184,7 @@ return array(
|
||||||
new Cache( 'ppcp-client-credentials-cache' )
|
new Cache( 'ppcp-client-credentials-cache' )
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
'onboarding.endpoint.pui' => static function( ContainerInterface $container ) : UpdateSignupLinksEndpoint {
|
'onboarding.endpoint.pui' => static function( ContainerInterface $container ) : UpdateSignupLinksEndpoint {
|
||||||
return new UpdateSignupLinksEndpoint(
|
return new UpdateSignupLinksEndpoint(
|
||||||
$container->get( 'wcgateway.settings' ),
|
$container->get( 'wcgateway.settings' ),
|
||||||
$container->get( 'button.request-data' ),
|
$container->get( 'button.request-data' ),
|
||||||
|
@ -213,26 +194,10 @@ return array(
|
||||||
$container->get( 'woocommerce.logger.woocommerce' )
|
$container->get( 'woocommerce.logger.woocommerce' )
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
'api.endpoint.partner-referrals-sandbox' => static function ( ContainerInterface $container ) : PartnerReferrals {
|
'onboarding.signup-link-cache' => static function( ContainerInterface $container ): Cache {
|
||||||
|
|
||||||
return new PartnerReferrals(
|
|
||||||
CONNECT_WOO_SANDBOX_URL,
|
|
||||||
new ConnectBearer(),
|
|
||||||
$container->get( 'woocommerce.logger.woocommerce' )
|
|
||||||
);
|
|
||||||
},
|
|
||||||
'api.endpoint.partner-referrals-production' => static function ( ContainerInterface $container ) : PartnerReferrals {
|
|
||||||
|
|
||||||
return new PartnerReferrals(
|
|
||||||
CONNECT_WOO_URL,
|
|
||||||
new ConnectBearer(),
|
|
||||||
$container->get( 'woocommerce.logger.woocommerce' )
|
|
||||||
);
|
|
||||||
},
|
|
||||||
'onboarding.signup-link-cache' => static function( ContainerInterface $container ): Cache {
|
|
||||||
return new Cache( 'ppcp-paypal-signup-link' );
|
return new Cache( 'ppcp-paypal-signup-link' );
|
||||||
},
|
},
|
||||||
'onboarding.signup-link-ids' => static function ( ContainerInterface $container ): array {
|
'onboarding.signup-link-ids' => static function ( ContainerInterface $container ): array {
|
||||||
return array(
|
return array(
|
||||||
'production-ppcp',
|
'production-ppcp',
|
||||||
'production-express_checkout',
|
'production-express_checkout',
|
||||||
|
@ -240,12 +205,12 @@ return array(
|
||||||
'sandbox-express_checkout',
|
'sandbox-express_checkout',
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
'onboarding.render-send-only-notice' => static function( ContainerInterface $container ) {
|
'onboarding.render-send-only-notice' => static function( ContainerInterface $container ) {
|
||||||
return new OnboardingSendOnlyNoticeRenderer(
|
return new OnboardingSendOnlyNoticeRenderer(
|
||||||
$container->get( 'wcgateway.send-only-message' )
|
$container->get( 'wcgateway.send-only-message' )
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
'onboarding.render' => static function ( ContainerInterface $container ) : OnboardingRenderer {
|
'onboarding.render' => static function ( ContainerInterface $container ) : OnboardingRenderer {
|
||||||
$partner_referrals = $container->get( 'api.endpoint.partner-referrals-production' );
|
$partner_referrals = $container->get( 'api.endpoint.partner-referrals-production' );
|
||||||
$partner_referrals_sandbox = $container->get( 'api.endpoint.partner-referrals-sandbox' );
|
$partner_referrals_sandbox = $container->get( 'api.endpoint.partner-referrals-sandbox' );
|
||||||
$partner_referrals_data = $container->get( 'api.repository.partner-referrals-data' );
|
$partner_referrals_data = $container->get( 'api.repository.partner-referrals-data' );
|
||||||
|
@ -261,14 +226,14 @@ return array(
|
||||||
$logger
|
$logger
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
'onboarding.render-options' => static function ( ContainerInterface $container ) : OnboardingOptionsRenderer {
|
'onboarding.render-options' => static function ( ContainerInterface $container ) : OnboardingOptionsRenderer {
|
||||||
return new OnboardingOptionsRenderer(
|
return new OnboardingOptionsRenderer(
|
||||||
$container->get( 'onboarding.url' ),
|
$container->get( 'onboarding.url' ),
|
||||||
$container->get( 'api.shop.country' ),
|
$container->get( 'api.shop.country' ),
|
||||||
$container->get( 'wcgateway.settings' )
|
$container->get( 'wcgateway.settings' )
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
'onboarding.rest' => static function( $container ) : OnboardingRESTController {
|
'onboarding.rest' => static function( $container ) : OnboardingRESTController {
|
||||||
return new OnboardingRESTController( $container );
|
return new OnboardingRESTController( $container );
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
|
@ -13,6 +13,7 @@ use WooCommerce\PayPalCommerce\Onboarding\Endpoint\UpdateSignupLinksEndpoint;
|
||||||
use WooCommerce\PayPalCommerce\Onboarding\Assets\OnboardingAssets;
|
use WooCommerce\PayPalCommerce\Onboarding\Assets\OnboardingAssets;
|
||||||
use WooCommerce\PayPalCommerce\Onboarding\Endpoint\LoginSellerEndpoint;
|
use WooCommerce\PayPalCommerce\Onboarding\Endpoint\LoginSellerEndpoint;
|
||||||
use WooCommerce\PayPalCommerce\Onboarding\Render\OnboardingRenderer;
|
use WooCommerce\PayPalCommerce\Onboarding\Render\OnboardingRenderer;
|
||||||
|
use WooCommerce\PayPalCommerce\Settings\SettingsModule;
|
||||||
use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ExecutableModule;
|
use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ExecutableModule;
|
||||||
use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ExtendingModule;
|
use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ExtendingModule;
|
||||||
use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ModuleClassNameIdTrait;
|
use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ModuleClassNameIdTrait;
|
||||||
|
@ -44,33 +45,32 @@ class OnboardingModule implements ServiceModule, ExtendingModule, ExecutableModu
|
||||||
*/
|
*/
|
||||||
public function run( ContainerInterface $c ): bool {
|
public function run( ContainerInterface $c ): bool {
|
||||||
|
|
||||||
if ( ! apply_filters(
|
add_action(
|
||||||
// phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores
|
'admin_enqueue_scripts',
|
||||||
'woocommerce.feature-flags.woocommerce_paypal_payments.settings_enabled',
|
function() use ( $c ) {
|
||||||
getenv( 'PCP_SETTINGS_ENABLED' ) === '1'
|
if (
|
||||||
) ) {
|
apply_filters(
|
||||||
|
// phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores
|
||||||
|
'woocommerce.feature-flags.woocommerce_paypal_payments.settings_enabled',
|
||||||
|
getenv( 'PCP_SETTINGS_ENABLED' ) === '1'
|
||||||
|
) && ! SettingsModule::should_use_the_old_ui()
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
$asset_loader = $c->get( 'onboarding.assets' );
|
$asset_loader = $c->get( 'onboarding.assets' );
|
||||||
/**
|
assert( $asset_loader instanceof OnboardingAssets );
|
||||||
* The OnboardingAssets.
|
|
||||||
*
|
$asset_loader->register();
|
||||||
* @var OnboardingAssets $asset_loader
|
add_action(
|
||||||
*/
|
'woocommerce_settings_checkout',
|
||||||
add_action(
|
array(
|
||||||
'admin_enqueue_scripts',
|
$asset_loader,
|
||||||
array(
|
'enqueue',
|
||||||
$asset_loader,
|
)
|
||||||
'register',
|
);
|
||||||
)
|
}
|
||||||
);
|
);
|
||||||
add_action(
|
|
||||||
'woocommerce_settings_checkout',
|
|
||||||
array(
|
|
||||||
$asset_loader,
|
|
||||||
'enqueue',
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
add_filter(
|
add_filter(
|
||||||
'woocommerce_form_field',
|
'woocommerce_form_field',
|
||||||
|
|
|
@ -55,23 +55,21 @@ class OrderTrackingModule implements ServiceModule, ExtendingModule, ExecutableM
|
||||||
* @throws NotFoundException
|
* @throws NotFoundException
|
||||||
*/
|
*/
|
||||||
public function run( ContainerInterface $c ): bool {
|
public function run( ContainerInterface $c ): bool {
|
||||||
$endpoint = $c->get( 'order-tracking.endpoint.controller' );
|
|
||||||
assert( $endpoint instanceof OrderTrackingEndpoint );
|
|
||||||
|
|
||||||
add_action( 'wc_ajax_' . OrderTrackingEndpoint::ENDPOINT, array( $endpoint, 'handle_request' ) );
|
add_action(
|
||||||
|
'wc_ajax_' . OrderTrackingEndpoint::ENDPOINT,
|
||||||
|
function() use ( $c ) {
|
||||||
|
$c->get( 'order-tracking.endpoint.controller' )->handle_request();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
$asset_loader = $c->get( 'order-tracking.assets' );
|
$asset_loader = $c->get( 'order-tracking.assets' );
|
||||||
assert( $asset_loader instanceof OrderEditPageAssets );
|
assert( $asset_loader instanceof OrderEditPageAssets );
|
||||||
|
|
||||||
$logger = $c->get( 'woocommerce.logger.woocommerce' );
|
|
||||||
assert( $logger instanceof LoggerInterface );
|
|
||||||
|
|
||||||
$bearer = $c->get( 'api.bearer' );
|
|
||||||
|
|
||||||
add_action(
|
add_action(
|
||||||
'init',
|
'init',
|
||||||
function() use ( $asset_loader, $bearer ) {
|
function() use ( $asset_loader, $c ) {
|
||||||
if ( ! $this->is_tracking_enabled( $bearer ) ) {
|
if ( ! $this->is_tracking_enabled( $c->get( 'api.bearer' ) ) ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,8 +78,8 @@ class OrderTrackingModule implements ServiceModule, ExtendingModule, ExecutableM
|
||||||
);
|
);
|
||||||
add_action(
|
add_action(
|
||||||
'init',
|
'init',
|
||||||
function() use ( $asset_loader, $bearer ) {
|
function() use ( $asset_loader, $c ) {
|
||||||
if ( ! $this->is_tracking_enabled( $bearer ) ) {
|
if ( ! $this->is_tracking_enabled( $c->get( 'api.bearer' ) ) ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,9 +87,6 @@ class OrderTrackingModule implements ServiceModule, ExtendingModule, ExecutableM
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
$meta_box_renderer = $c->get( 'order-tracking.meta-box.renderer' );
|
|
||||||
assert( $meta_box_renderer instanceof MetaBoxRenderer );
|
|
||||||
|
|
||||||
add_action(
|
add_action(
|
||||||
'add_meta_boxes',
|
'add_meta_boxes',
|
||||||
/**
|
/**
|
||||||
|
@ -103,8 +98,8 @@ class OrderTrackingModule implements ServiceModule, ExtendingModule, ExecutableM
|
||||||
*
|
*
|
||||||
* @psalm-suppress MissingClosureParamType
|
* @psalm-suppress MissingClosureParamType
|
||||||
*/
|
*/
|
||||||
function( string $post_type, $post_or_order_object ) use ( $meta_box_renderer, $bearer ) {
|
function( string $post_type, $post_or_order_object ) use ( $c ) {
|
||||||
if ( ! $this->is_tracking_enabled( $bearer ) ) {
|
if ( ! $this->is_tracking_enabled( $c->get( 'api.bearer' ) ) ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,6 +130,9 @@ class OrderTrackingModule implements ServiceModule, ExtendingModule, ExecutableM
|
||||||
? wc_get_page_screen_id( 'shop-order' )
|
? wc_get_page_screen_id( 'shop-order' )
|
||||||
: 'shop_order';
|
: 'shop_order';
|
||||||
|
|
||||||
|
$meta_box_renderer = $c->get( 'order-tracking.meta-box.renderer' );
|
||||||
|
assert( $meta_box_renderer instanceof MetaBoxRenderer );
|
||||||
|
|
||||||
add_meta_box(
|
add_meta_box(
|
||||||
'ppcp_order-tracking',
|
'ppcp_order-tracking',
|
||||||
__( 'PayPal Package Tracking', 'woocommerce-paypal-payments' ),
|
__( 'PayPal Package Tracking', 'woocommerce-paypal-payments' ),
|
||||||
|
|
|
@ -71,12 +71,12 @@ class PayLaterBlockModule implements ServiceModule, ExtendingModule, ExecutableM
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
$settings = $c->get( 'wcgateway.settings' );
|
|
||||||
assert( $settings instanceof Settings );
|
|
||||||
|
|
||||||
add_action(
|
add_action(
|
||||||
'init',
|
'init',
|
||||||
function () use ( $c, $settings ): void {
|
function () use ( $c ): void {
|
||||||
|
$settings = $c->get( 'wcgateway.settings' );
|
||||||
|
assert( $settings instanceof Settings );
|
||||||
|
|
||||||
$script_handle = 'ppcp-paylater-block';
|
$script_handle = 'ppcp-paylater-block';
|
||||||
wp_register_script(
|
wp_register_script(
|
||||||
$script_handle,
|
$script_handle,
|
||||||
|
|
|
@ -56,46 +56,46 @@ class PayLaterConfiguratorModule implements ServiceModule, ExtendingModule, Exec
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
public function run( ContainerInterface $c ) : bool {
|
public function run( ContainerInterface $c ) : bool {
|
||||||
$is_available = $c->get( 'paylater-configurator.is-available' );
|
|
||||||
|
|
||||||
if ( ! $is_available ) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
$current_page_id = $c->get( 'wcgateway.current-ppcp-settings-page-id' );
|
|
||||||
$is_wc_settings_page = $c->get( 'wcgateway.is-wc-settings-page' );
|
|
||||||
$messaging_locations = $c->get( 'paylater-configurator.messaging-locations' );
|
|
||||||
|
|
||||||
$this->add_paylater_update_notice( $messaging_locations, $is_wc_settings_page, $current_page_id );
|
|
||||||
|
|
||||||
$settings = $c->get( 'wcgateway.settings' );
|
|
||||||
assert( $settings instanceof Settings );
|
|
||||||
|
|
||||||
add_action(
|
|
||||||
'wc_ajax_' . SaveConfig::ENDPOINT,
|
|
||||||
static function () use ( $c ) {
|
|
||||||
$endpoint = $c->get( 'paylater-configurator.endpoint.save-config' );
|
|
||||||
assert( $endpoint instanceof SaveConfig );
|
|
||||||
$endpoint->handle_request();
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
add_action(
|
|
||||||
'wc_ajax_' . GetConfig::ENDPOINT,
|
|
||||||
static function () use ( $c ) {
|
|
||||||
$endpoint = $c->get( 'paylater-configurator.endpoint.get-config' );
|
|
||||||
assert( $endpoint instanceof GetConfig );
|
|
||||||
$endpoint->handle_request();
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
if ( $current_page_id !== Settings::PAY_LATER_TAB_ID ) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
add_action(
|
add_action(
|
||||||
'init',
|
'init',
|
||||||
static function () use ( $c, $settings ) {
|
static function () use ( $c ) {
|
||||||
|
$is_available = $c->get( 'paylater-configurator.is-available' );
|
||||||
|
if ( ! $is_available ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$current_page_id = $c->get( 'wcgateway.current-ppcp-settings-page-id' );
|
||||||
|
$is_wc_settings_page = $c->get( 'wcgateway.is-wc-settings-page' );
|
||||||
|
$messaging_locations = $c->get( 'paylater-configurator.messaging-locations' );
|
||||||
|
|
||||||
|
self::add_paylater_update_notice( $messaging_locations, $is_wc_settings_page, $current_page_id );
|
||||||
|
|
||||||
|
$settings = $c->get( 'wcgateway.settings' );
|
||||||
|
assert( $settings instanceof Settings );
|
||||||
|
|
||||||
|
add_action(
|
||||||
|
'wc_ajax_' . SaveConfig::ENDPOINT,
|
||||||
|
static function () use ( $c ) {
|
||||||
|
$endpoint = $c->get( 'paylater-configurator.endpoint.save-config' );
|
||||||
|
assert( $endpoint instanceof SaveConfig );
|
||||||
|
$endpoint->handle_request();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
add_action(
|
||||||
|
'wc_ajax_' . GetConfig::ENDPOINT,
|
||||||
|
static function () use ( $c ) {
|
||||||
|
$endpoint = $c->get( 'paylater-configurator.endpoint.get-config' );
|
||||||
|
assert( $endpoint instanceof GetConfig );
|
||||||
|
$endpoint->handle_request();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if ( $current_page_id !== Settings::PAY_LATER_TAB_ID ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
wp_enqueue_script(
|
wp_enqueue_script(
|
||||||
'ppcp-paylater-configurator-lib',
|
'ppcp-paylater-configurator-lib',
|
||||||
'https://www.paypalobjects.com/merchant-library/merchant-configurator.js',
|
'https://www.paypalobjects.com/merchant-library/merchant-configurator.js',
|
||||||
|
@ -165,7 +165,7 @@ class PayLaterConfiguratorModule implements ServiceModule, ExtendingModule, Exec
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
private function add_paylater_update_notice( array $message_locations, bool $is_settings_page, string $current_page_id ) : void {
|
private static function add_paylater_update_notice( array $message_locations, bool $is_settings_page, string $current_page_id ) : void {
|
||||||
// The message must be registered on any WC-Settings page, except for the Pay Later page.
|
// The message must be registered on any WC-Settings page, except for the Pay Later page.
|
||||||
if ( ! $is_settings_page || Settings::PAY_LATER_TAB_ID === $current_page_id ) {
|
if ( ! $is_settings_page || Settings::PAY_LATER_TAB_ID === $current_page_id ) {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -99,12 +99,11 @@ class PayLaterWCBlocksModule implements ServiceModule, ExtendingModule, Executab
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
$settings = $c->get( 'wcgateway.settings' );
|
|
||||||
assert( $settings instanceof Settings );
|
|
||||||
|
|
||||||
add_action(
|
add_action(
|
||||||
'init',
|
'init',
|
||||||
function () use ( $c, $settings ): void {
|
function () use ( $c ): void {
|
||||||
|
$settings = $c->get( 'wcgateway.settings' );
|
||||||
|
assert( $settings instanceof Settings );
|
||||||
$config_factory = $c->get( 'paylater-configurator.factory.config' );
|
$config_factory = $c->get( 'paylater-configurator.factory.config' );
|
||||||
assert( $config_factory instanceof ConfigFactory );
|
assert( $config_factory instanceof ConfigFactory );
|
||||||
|
|
||||||
|
@ -186,47 +185,52 @@ class PayLaterWCBlocksModule implements ServiceModule, ExtendingModule, Executab
|
||||||
2
|
2
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
add_action(
|
||||||
* Cannot return false for this path.
|
'init',
|
||||||
*
|
function () use ( $c ): void {
|
||||||
* @psalm-suppress PossiblyFalseArgument
|
if ( ! function_exists( 'register_block_type' ) ) {
|
||||||
*/
|
return;
|
||||||
if ( function_exists( 'register_block_type' ) ) {
|
}
|
||||||
register_block_type(
|
|
||||||
dirname( realpath( __FILE__ ), 2 ) . '/resources/js/CartPayLaterMessagesBlock',
|
|
||||||
array(
|
|
||||||
'render_callback' => function ( array $attributes ) use ( $c ) {
|
|
||||||
return PayLaterWCBlocksUtils::render_paylater_block(
|
|
||||||
$attributes['blockId'] ?? 'woocommerce-paypal-payments/cart-paylater-messages',
|
|
||||||
$attributes['ppcpId'] ?? 'ppcp-cart-paylater-messages',
|
|
||||||
'cart',
|
|
||||||
$c
|
|
||||||
);
|
|
||||||
},
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cannot return false for this path.
|
* Cannot return false for this path.
|
||||||
*
|
*
|
||||||
* @psalm-suppress PossiblyFalseArgument
|
* @psalm-suppress PossiblyFalseArgument
|
||||||
*/
|
*/
|
||||||
if ( function_exists( 'register_block_type' ) ) {
|
register_block_type(
|
||||||
register_block_type(
|
dirname( realpath( __FILE__ ), 2 ) . '/resources/js/CartPayLaterMessagesBlock',
|
||||||
dirname( realpath( __FILE__ ), 2 ) . '/resources/js/CheckoutPayLaterMessagesBlock',
|
array(
|
||||||
array(
|
'render_callback' => function ( array $attributes ) use ( $c ) {
|
||||||
'render_callback' => function ( array $attributes ) use ( $c ) {
|
return PayLaterWCBlocksUtils::render_paylater_block(
|
||||||
return PayLaterWCBlocksUtils::render_paylater_block(
|
$attributes['blockId'] ?? 'woocommerce-paypal-payments/cart-paylater-messages',
|
||||||
$attributes['blockId'] ?? 'woocommerce-paypal-payments/checkout-paylater-messages',
|
$attributes['ppcpId'] ?? 'ppcp-cart-paylater-messages',
|
||||||
$attributes['ppcpId'] ?? 'ppcp-checkout-paylater-messages',
|
'cart',
|
||||||
'checkout',
|
$c
|
||||||
$c
|
);
|
||||||
);
|
},
|
||||||
},
|
)
|
||||||
)
|
);
|
||||||
);
|
|
||||||
}
|
/**
|
||||||
|
* Cannot return false for this path.
|
||||||
|
*
|
||||||
|
* @psalm-suppress PossiblyFalseArgument
|
||||||
|
*/
|
||||||
|
register_block_type(
|
||||||
|
dirname( realpath( __FILE__ ), 2 ) . '/resources/js/CheckoutPayLaterMessagesBlock',
|
||||||
|
array(
|
||||||
|
'render_callback' => function ( array $attributes ) use ( $c ) {
|
||||||
|
return PayLaterWCBlocksUtils::render_paylater_block(
|
||||||
|
$attributes['blockId'] ?? 'woocommerce-paypal-payments/checkout-paylater-messages',
|
||||||
|
$attributes['ppcpId'] ?? 'ppcp-checkout-paylater-messages',
|
||||||
|
'checkout',
|
||||||
|
$c
|
||||||
|
);
|
||||||
|
},
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
// This is a fallback for the default Cart block that haven't been saved with the inserted Pay Later messaging block.
|
// This is a fallback for the default Cart block that haven't been saved with the inserted Pay Later messaging block.
|
||||||
add_filter(
|
add_filter(
|
||||||
|
@ -271,7 +275,7 @@ class PayLaterWCBlocksModule implements ServiceModule, ExtendingModule, Executab
|
||||||
if ( self::is_under_cart_totals_placement_enabled() ) {
|
if ( self::is_under_cart_totals_placement_enabled() ) {
|
||||||
add_action(
|
add_action(
|
||||||
'enqueue_block_editor_assets',
|
'enqueue_block_editor_assets',
|
||||||
function () use ( $c, $settings ): void {
|
function () use ( $c ): void {
|
||||||
$handle = 'ppcp-checkout-paylater-block-editor-inserter';
|
$handle = 'ppcp-checkout-paylater-block-editor-inserter';
|
||||||
$path = $c->get( 'paylater-wc-blocks.url' ) . 'assets/js/cart-paylater-block-inserter.js';
|
$path = $c->get( 'paylater-wc-blocks.url' ) . 'assets/js/cart-paylater-block-inserter.js';
|
||||||
|
|
||||||
|
|
|
@ -599,11 +599,11 @@ class PayPalSubscriptionsModule implements ServiceModule, ExtendingModule, Execu
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
$endpoint = $c->get( 'paypal-subscriptions.deactivate-plan-endpoint' );
|
|
||||||
assert( $endpoint instanceof DeactivatePlanEndpoint );
|
|
||||||
add_action(
|
add_action(
|
||||||
'wc_ajax_' . DeactivatePlanEndpoint::ENDPOINT,
|
'wc_ajax_' . DeactivatePlanEndpoint::ENDPOINT,
|
||||||
array( $endpoint, 'handle_request' )
|
function() use ( $c ) {
|
||||||
|
$c->get( 'paypal-subscriptions.deactivate-plan-endpoint' )->handle_request();
|
||||||
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
add_action(
|
add_action(
|
||||||
|
|
|
@ -94,7 +94,9 @@ class CreatePaymentToken implements EndpointInterface {
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
$result = $this->payment_method_tokens_endpoint->create_payment_token( $payment_source );
|
$customer_id = get_user_meta( get_current_user_id(), '_ppcp_target_customer_id', true );
|
||||||
|
|
||||||
|
$result = $this->payment_method_tokens_endpoint->create_payment_token( $payment_source, $customer_id );
|
||||||
|
|
||||||
if ( is_user_logged_in() && isset( $result->customer->id ) ) {
|
if ( is_user_logged_in() && isset( $result->customer->id ) ) {
|
||||||
$current_user_id = get_current_user_id();
|
$current_user_id = get_current_user_id();
|
||||||
|
|
|
@ -103,7 +103,9 @@ class CreateSetupToken implements EndpointInterface {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
$result = $this->payment_method_tokens_endpoint->setup_tokens( $payment_source );
|
$customer_id = get_user_meta( get_current_user_id(), '_ppcp_target_customer_id', true );
|
||||||
|
|
||||||
|
$result = $this->payment_method_tokens_endpoint->setup_tokens( $payment_source, $customer_id );
|
||||||
|
|
||||||
wp_send_json_success( $result );
|
wp_send_json_success( $result );
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -63,33 +63,26 @@ class SavePaymentMethodsModule implements ServiceModule, ExtendingModule, Execut
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
$settings = $c->get( 'wcgateway.settings' );
|
|
||||||
assert( $settings instanceof Settings );
|
|
||||||
|
|
||||||
$billing_agreements_endpoint = $c->get( 'api.endpoint.billing-agreements' );
|
|
||||||
assert( $billing_agreements_endpoint instanceof BillingAgreementsEndpoint );
|
|
||||||
|
|
||||||
add_action(
|
add_action(
|
||||||
'woocommerce_paypal_payments_gateway_migrate_on_update',
|
'woocommerce_paypal_payments_gateway_migrate_on_update',
|
||||||
function() use ( $settings, $billing_agreements_endpoint ) {
|
function() use ( $c ) {
|
||||||
|
$billing_agreements_endpoint = $c->get( 'api.endpoint.billing-agreements' );
|
||||||
|
assert( $billing_agreements_endpoint instanceof BillingAgreementsEndpoint );
|
||||||
|
|
||||||
$reference_transaction_enabled = $billing_agreements_endpoint->reference_transaction_enabled();
|
$reference_transaction_enabled = $billing_agreements_endpoint->reference_transaction_enabled();
|
||||||
if ( $reference_transaction_enabled !== true ) {
|
if ( $reference_transaction_enabled !== true ) {
|
||||||
$settings->set( 'vault_enabled', false );
|
$c->get( 'wcgateway.settings' )->set( 'vault_enabled', false );
|
||||||
$settings->persist();
|
$c->get( 'wcgateway.settings' )->persist();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
if (
|
|
||||||
( ! $settings->has( 'vault_enabled' ) || ! $settings->get( 'vault_enabled' ) )
|
|
||||||
&& ( ! $settings->has( 'vault_enabled_dcc' ) || ! $settings->get( 'vault_enabled_dcc' ) )
|
|
||||||
) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
add_filter(
|
add_filter(
|
||||||
'woocommerce_paypal_payments_localized_script_data',
|
'woocommerce_paypal_payments_localized_script_data',
|
||||||
function( array $localized_script_data ) use ( $c ) {
|
function( array $localized_script_data ) use ( $c ) {
|
||||||
|
if ( ! self::vault_enabled( $c ) ) {
|
||||||
|
return $localized_script_data;
|
||||||
|
}
|
||||||
$subscriptions_helper = $c->get( 'wc-subscriptions.helper' );
|
$subscriptions_helper = $c->get( 'wc-subscriptions.helper' );
|
||||||
assert( $subscriptions_helper instanceof SubscriptionHelper );
|
assert( $subscriptions_helper instanceof SubscriptionHelper );
|
||||||
if ( ! is_user_logged_in() && ! $subscriptions_helper->cart_contains_subscription() ) {
|
if ( ! is_user_logged_in() && ! $subscriptions_helper->cart_contains_subscription() ) {
|
||||||
|
@ -109,12 +102,11 @@ class SavePaymentMethodsModule implements ServiceModule, ExtendingModule, Execut
|
||||||
// Adds attributes needed to save payment method.
|
// Adds attributes needed to save payment method.
|
||||||
add_filter(
|
add_filter(
|
||||||
'ppcp_create_order_request_body_data',
|
'ppcp_create_order_request_body_data',
|
||||||
function( array $data, string $payment_method, array $request_data ) use ( $settings ): array {
|
function( array $data, string $payment_method, array $request_data ) use ( $c ): array {
|
||||||
|
if ( ! self::vault_enabled( $c ) ) {
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
if ( $payment_method === CreditCardGateway::ID ) {
|
if ( $payment_method === CreditCardGateway::ID ) {
|
||||||
if ( ! $settings->has( 'vault_enabled_dcc' ) || ! $settings->get( 'vault_enabled_dcc' ) ) {
|
|
||||||
return $data;
|
|
||||||
}
|
|
||||||
|
|
||||||
$save_payment_method = $request_data['save_payment_method'] ?? false;
|
$save_payment_method = $request_data['save_payment_method'] ?? false;
|
||||||
if ( $save_payment_method ) {
|
if ( $save_payment_method ) {
|
||||||
$data['payment_source'] = array(
|
$data['payment_source'] = array(
|
||||||
|
@ -141,10 +133,6 @@ class SavePaymentMethodsModule implements ServiceModule, ExtendingModule, Execut
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( $payment_method === PayPalGateway::ID ) {
|
if ( $payment_method === PayPalGateway::ID ) {
|
||||||
if ( ! $settings->has( 'vault_enabled' ) || ! $settings->get( 'vault_enabled' ) ) {
|
|
||||||
return $data;
|
|
||||||
}
|
|
||||||
|
|
||||||
$funding_source = $request_data['funding_source'] ?? null;
|
$funding_source = $request_data['funding_source'] ?? null;
|
||||||
|
|
||||||
if ( $funding_source && $funding_source === 'venmo' ) {
|
if ( $funding_source && $funding_source === 'venmo' ) {
|
||||||
|
@ -197,6 +185,9 @@ class SavePaymentMethodsModule implements ServiceModule, ExtendingModule, Execut
|
||||||
add_action(
|
add_action(
|
||||||
'woocommerce_paypal_payments_after_order_processor',
|
'woocommerce_paypal_payments_after_order_processor',
|
||||||
function( WC_Order $wc_order, Order $order ) use ( $c ) {
|
function( WC_Order $wc_order, Order $order ) use ( $c ) {
|
||||||
|
if ( ! self::vault_enabled( $c ) ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
$payment_source = $order->payment_source();
|
$payment_source = $order->payment_source();
|
||||||
assert( $payment_source instanceof PaymentSource );
|
assert( $payment_source instanceof PaymentSource );
|
||||||
|
|
||||||
|
@ -259,13 +250,30 @@ class SavePaymentMethodsModule implements ServiceModule, ExtendingModule, Execut
|
||||||
2
|
2
|
||||||
);
|
);
|
||||||
|
|
||||||
add_filter( 'woocommerce_paypal_payments_disable_add_payment_method', '__return_false' );
|
add_filter(
|
||||||
add_filter( 'woocommerce_paypal_payments_should_render_card_custom_fields', '__return_false' );
|
'woocommerce_paypal_payments_disable_add_payment_method',
|
||||||
|
function ( bool $value ) use ( $c ): bool {
|
||||||
|
if ( ! self::vault_enabled( $c ) ) {
|
||||||
|
return $value;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
add_filter(
|
||||||
|
'woocommerce_paypal_payments_should_render_card_custom_fields',
|
||||||
|
function ( bool $value ) use ( $c ): bool {
|
||||||
|
if ( ! self::vault_enabled( $c ) ) {
|
||||||
|
return $value;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
add_action(
|
add_action(
|
||||||
'wp_enqueue_scripts',
|
'wp_enqueue_scripts',
|
||||||
function() use ( $c ) {
|
function() use ( $c ) {
|
||||||
if ( ! is_user_logged_in() || ! ( $this->is_add_payment_method_page() || $this->is_subscription_change_payment_method_page() ) ) {
|
if ( ! is_user_logged_in() || ! ( $this->is_add_payment_method_page() || $this->is_subscription_change_payment_method_page() ) || ! self::vault_enabled( $c ) ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -355,8 +363,8 @@ class SavePaymentMethodsModule implements ServiceModule, ExtendingModule, Execut
|
||||||
|
|
||||||
add_action(
|
add_action(
|
||||||
'woocommerce_add_payment_method_form_bottom',
|
'woocommerce_add_payment_method_form_bottom',
|
||||||
function () {
|
function () use ( $c ) {
|
||||||
if ( ! is_user_logged_in() || ! is_add_payment_method_page() ) {
|
if ( ! is_user_logged_in() || ! is_add_payment_method_page() || ! self::vault_enabled( $c ) ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -367,6 +375,9 @@ class SavePaymentMethodsModule implements ServiceModule, ExtendingModule, Execut
|
||||||
add_action(
|
add_action(
|
||||||
'wc_ajax_' . CreateSetupToken::ENDPOINT,
|
'wc_ajax_' . CreateSetupToken::ENDPOINT,
|
||||||
static function () use ( $c ) {
|
static function () use ( $c ) {
|
||||||
|
if ( ! self::vault_enabled( $c ) ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
$endpoint = $c->get( 'save-payment-methods.endpoint.create-setup-token' );
|
$endpoint = $c->get( 'save-payment-methods.endpoint.create-setup-token' );
|
||||||
assert( $endpoint instanceof CreateSetupToken );
|
assert( $endpoint instanceof CreateSetupToken );
|
||||||
|
|
||||||
|
@ -377,6 +388,9 @@ class SavePaymentMethodsModule implements ServiceModule, ExtendingModule, Execut
|
||||||
add_action(
|
add_action(
|
||||||
'wc_ajax_' . CreatePaymentToken::ENDPOINT,
|
'wc_ajax_' . CreatePaymentToken::ENDPOINT,
|
||||||
static function () use ( $c ) {
|
static function () use ( $c ) {
|
||||||
|
if ( ! self::vault_enabled( $c ) ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
$endpoint = $c->get( 'save-payment-methods.endpoint.create-payment-token' );
|
$endpoint = $c->get( 'save-payment-methods.endpoint.create-payment-token' );
|
||||||
assert( $endpoint instanceof CreatePaymentToken );
|
assert( $endpoint instanceof CreatePaymentToken );
|
||||||
|
|
||||||
|
@ -387,6 +401,9 @@ class SavePaymentMethodsModule implements ServiceModule, ExtendingModule, Execut
|
||||||
add_action(
|
add_action(
|
||||||
'wc_ajax_' . CreatePaymentTokenForGuest::ENDPOINT,
|
'wc_ajax_' . CreatePaymentTokenForGuest::ENDPOINT,
|
||||||
static function () use ( $c ) {
|
static function () use ( $c ) {
|
||||||
|
if ( ! self::vault_enabled( $c ) ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
$endpoint = $c->get( 'save-payment-methods.endpoint.create-payment-token-for-guest' );
|
$endpoint = $c->get( 'save-payment-methods.endpoint.create-payment-token-for-guest' );
|
||||||
assert( $endpoint instanceof CreatePaymentTokenForGuest );
|
assert( $endpoint instanceof CreatePaymentTokenForGuest );
|
||||||
|
|
||||||
|
@ -397,6 +414,9 @@ class SavePaymentMethodsModule implements ServiceModule, ExtendingModule, Execut
|
||||||
add_action(
|
add_action(
|
||||||
'woocommerce_paypal_payments_before_delete_payment_token',
|
'woocommerce_paypal_payments_before_delete_payment_token',
|
||||||
function( string $token_id ) use ( $c ) {
|
function( string $token_id ) use ( $c ) {
|
||||||
|
if ( ! self::vault_enabled( $c ) ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
$endpoint = $c->get( 'api.endpoint.payment-tokens' );
|
$endpoint = $c->get( 'api.endpoint.payment-tokens' );
|
||||||
assert( $endpoint instanceof PaymentTokensEndpoint );
|
assert( $endpoint instanceof PaymentTokensEndpoint );
|
||||||
|
@ -419,13 +439,11 @@ class SavePaymentMethodsModule implements ServiceModule, ExtendingModule, Execut
|
||||||
add_filter(
|
add_filter(
|
||||||
'woocommerce_paypal_payments_credit_card_gateway_supports',
|
'woocommerce_paypal_payments_credit_card_gateway_supports',
|
||||||
function( array $supports ) use ( $c ): array {
|
function( array $supports ) use ( $c ): array {
|
||||||
$settings = $c->get( 'wcgateway.settings' );
|
if ( ! self::vault_enabled( $c ) ) {
|
||||||
assert( $settings instanceof ContainerInterface );
|
return $supports;
|
||||||
|
|
||||||
if ( $settings->has( 'vault_enabled_dcc' ) && $settings->get( 'vault_enabled_dcc' ) ) {
|
|
||||||
$supports[] = 'tokenization';
|
|
||||||
$supports[] = 'add_payment_method';
|
|
||||||
}
|
}
|
||||||
|
$supports[] = 'tokenization';
|
||||||
|
$supports[] = 'add_payment_method';
|
||||||
|
|
||||||
return $supports;
|
return $supports;
|
||||||
}
|
}
|
||||||
|
@ -433,7 +451,10 @@ class SavePaymentMethodsModule implements ServiceModule, ExtendingModule, Execut
|
||||||
|
|
||||||
add_filter(
|
add_filter(
|
||||||
'woocommerce_paypal_payments_save_payment_methods_eligible',
|
'woocommerce_paypal_payments_save_payment_methods_eligible',
|
||||||
function() {
|
function( bool $value ) use ( $c ): bool {
|
||||||
|
if ( ! self::vault_enabled( $c ) ) {
|
||||||
|
return $value;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -481,4 +502,24 @@ class SavePaymentMethodsModule implements ServiceModule, ExtendingModule, Execut
|
||||||
|
|
||||||
return $localized_script_data;
|
return $localized_script_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether the vault functionality is enabled based on configuration settings.
|
||||||
|
*
|
||||||
|
* @param ContainerInterface $container The dependency injection container from which settings can be retrieved.
|
||||||
|
*
|
||||||
|
* @return bool Returns true if either 'vault_enabled' or 'vault_enabled_dcc' settings are enabled; otherwise, false.
|
||||||
|
*/
|
||||||
|
private static function vault_enabled( ContainerInterface $container ): bool {
|
||||||
|
$settings = $container->get( 'wcgateway.settings' );
|
||||||
|
assert( $settings instanceof Settings );
|
||||||
|
|
||||||
|
if (
|
||||||
|
( ! $settings->has( 'vault_enabled' ) || ! $settings->get( 'vault_enabled' ) )
|
||||||
|
&& ( ! $settings->has( 'vault_enabled_dcc' ) || ! $settings->get( 'vault_enabled_dcc' ) )
|
||||||
|
) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
"@wordpress/scripts": "^30.3.0"
|
"@wordpress/scripts": "^30.3.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@paypal/react-paypal-js": "^8.7.0",
|
||||||
"@woocommerce/settings": "^1.0.0",
|
"@woocommerce/settings": "^1.0.0",
|
||||||
"react-select": "^5.8.3"
|
"react-select": "^5.8.3"
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,10 +58,6 @@ h1, h2, h3, h4 {
|
||||||
color: $color-black;
|
color: $color-black;
|
||||||
}
|
}
|
||||||
|
|
||||||
a:not(.button) {
|
|
||||||
color: $color-blueberry;
|
|
||||||
}
|
|
||||||
|
|
||||||
.components-form-toggle.is-checked > .components-form-toggle__track {
|
.components-form-toggle.is-checked > .components-form-toggle__track {
|
||||||
background-color: $color-blueberry;
|
background-color: $color-blueberry;
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&-image-badge {
|
.ppcp-r-badge-box__title-text:not(:empty) + .ppcp-r-badge-box__title-image-badge {
|
||||||
margin-left: 7px;
|
margin-left: 7px;
|
||||||
|
|
||||||
img {
|
img {
|
||||||
|
|
|
@ -5,16 +5,16 @@ button.components-button, a.components-button {
|
||||||
}
|
}
|
||||||
|
|
||||||
&:disabled {
|
&:disabled {
|
||||||
color: $color-white;
|
color: $color-gray-700;
|
||||||
}
|
}
|
||||||
|
|
||||||
border-radius: 2px;
|
border-radius: 50px;
|
||||||
padding: 14px 17px;
|
padding: 15px 32px;
|
||||||
height: auto;
|
height: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.is-primary {
|
&.is-primary {
|
||||||
@include font(13, 20, 400);
|
@include font(14, 18, 900);
|
||||||
|
|
||||||
&:not(:disabled) {
|
&:not(:disabled) {
|
||||||
background-color: $color-blueberry;
|
background-color: $color-blueberry;
|
||||||
|
|
|
@ -21,23 +21,25 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&__checkbox-value {
|
&__checkbox {
|
||||||
@include hide-input-field;
|
position: relative;
|
||||||
|
|
||||||
&:not(:checked) + .ppcp-r__checkbox-presentation img {
|
input {
|
||||||
display: none;
|
margin: 0;
|
||||||
|
border-color: $color-gray-600;
|
||||||
|
|
||||||
|
&:checked {
|
||||||
|
background-color: $color-blueberry;
|
||||||
|
border-color:$color-blueberry;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&:checked {
|
.components-checkbox-control__input-container {
|
||||||
+ .ppcp-r__checkbox-presentation {
|
margin: 0;
|
||||||
width: 20px;
|
}
|
||||||
height: 20px;
|
|
||||||
border: none;
|
|
||||||
|
|
||||||
img {
|
.components-base-control__field {
|
||||||
border-radius: 2px;
|
margin: 0;
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
|
|
||||||
&__content {
|
&__content {
|
||||||
margin-top: 60px;
|
margin-top: 60px;
|
||||||
padding:0 24px 28px 24px;
|
padding: 0 24px 28px 24px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,6 +96,36 @@
|
||||||
margin-top: 2px;
|
margin-top: 2px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.components-radio-control {
|
||||||
|
.components-flex {
|
||||||
|
gap: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
label {
|
||||||
|
@include font(14, 20, 400);
|
||||||
|
color: $color-black;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__option {
|
||||||
|
gap: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__input {
|
||||||
|
border-color: $color-gray-700;
|
||||||
|
margin-right: 0;
|
||||||
|
&:checked {
|
||||||
|
border: 1px solid $color-gray-700;
|
||||||
|
background-color: $color-white;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
transform: translate(3px, 3px);
|
||||||
|
border-width: 6px;
|
||||||
|
border-color: $color-blueberry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.ppcp-r-modal__field-row--save button.is-primary {
|
.ppcp-r-modal__field-row--save button.is-primary {
|
||||||
|
|
|
@ -2,13 +2,22 @@
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
||||||
|
&__space,
|
||||||
&__line {
|
&__line {
|
||||||
height: 1px;
|
margin: 0;
|
||||||
background-color: $color-gray-600;
|
|
||||||
display: block;
|
display: block;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&__line {
|
||||||
|
background-color: $color-gray-400;
|
||||||
|
height: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__space {
|
||||||
|
margin-bottom: 48px;
|
||||||
|
}
|
||||||
|
|
||||||
&__text {
|
&__text {
|
||||||
color: $color-gray;
|
color: $color-gray;
|
||||||
@include font(12, 24, 500, 0.8px);
|
@include font(12, 24, 500, 0.8px);
|
||||||
|
|
|
@ -4,17 +4,7 @@
|
||||||
&__title {
|
&__title {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
@include font(20, 28, 700);
|
@include font(20, 28, 700);
|
||||||
margin: 0 0 32px 0;
|
margin: 32px 0 32px 0;
|
||||||
}
|
|
||||||
|
|
||||||
&__description {
|
|
||||||
text-align: center;
|
|
||||||
@include font(14, 22, 400);
|
|
||||||
font-style: italic;
|
|
||||||
|
|
||||||
a {
|
|
||||||
color: $color-gray-700;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
&__wrapper {
|
&__wrapper {
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
body:has(.ppcp-r-container--onboarding) {
|
body:has(.ppcp-r-container--onboarding) {
|
||||||
background-color: #fff !important;
|
background-color: #fff !important;
|
||||||
|
|
||||||
.notice, .nav-tab-wrapper.woo-nav-tab-wrapper, .woocommerce-layout, .wrap.woocommerce form > h2, #screen-meta-links {
|
.notice, .nav-tab-wrapper.woo-nav-tab-wrapper, .woocommerce-layout__header, .wrap.woocommerce form > h2, #screen-meta-links {
|
||||||
display: none !important;
|
display: none !important;
|
||||||
|
visibility: hidden;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
@import './onboarding/step-welcome';
|
@import './onboarding/step-welcome';
|
||||||
@import './onboarding/step-business';
|
@import './onboarding/step-business';
|
||||||
@import './onboarding/step-products';
|
@import './onboarding/step-products';
|
||||||
|
@import './onboarding/step-payment-methods';
|
||||||
|
|
||||||
.ppcp-r-tabs.onboarding,
|
.ppcp-r-tabs.onboarding,
|
||||||
.ppcp-r-container--onboarding {
|
.ppcp-r-container--onboarding {
|
||||||
|
|
|
@ -49,6 +49,17 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ppcp-r__checkbox {
|
||||||
|
.components-flex {
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
label {
|
||||||
|
@include font(13, 20, 400);
|
||||||
|
color: $color-blueberry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
&__description {
|
&__description {
|
||||||
@include font(13, 20, 400);
|
@include font(13, 20, 400);
|
||||||
color: $color-blueberry;
|
color: $color-blueberry;
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
.ppcp-r-page-optional-payment-methods {
|
||||||
|
.ppcp-r-select-box:first-child {
|
||||||
|
.ppcp-r-select-box__title {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.ppcp-r-optional-payment-methods {
|
||||||
|
&__wrapper {
|
||||||
|
.ppcp-r-badge-box {
|
||||||
|
margin: 0 0 24px 0;
|
||||||
|
&:last-child {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.ppcp-r-badge-box__description {
|
||||||
|
margin: 12px 0 0 0;
|
||||||
|
@include font(14, 20, 400);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__description {
|
||||||
|
margin: 32px 0 0 0;
|
||||||
|
text-align: center;
|
||||||
|
@include font(14, 22, 400);
|
||||||
|
font-style: italic;
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: $color-gray-700;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__separator {
|
||||||
|
margin: 0 0 24px 0;
|
||||||
|
}
|
||||||
|
}
|
|
@ -16,27 +16,22 @@
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ppcp-r-page-welcome-or-separator {
|
|
||||||
margin: 0 0 16px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ppcp-r-page-welcome-mode-separator {
|
|
||||||
margin: 0 0 48px 0;
|
|
||||||
|
|
||||||
.ppcp-r-separator__line {
|
|
||||||
background-color: $color-gray-300;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.components-base-control__field {
|
.components-base-control__field {
|
||||||
margin: 0 0 24px 0;
|
margin: 0 0 24px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ppcp-r-toggle-block__toggled-content > button{
|
.ppcp-r-toggle-block__toggled-content > button{
|
||||||
@include small-button;
|
@include small-button;
|
||||||
color: $color-white;
|
color: $color-white;
|
||||||
border: none;
|
border: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.client-id-error {
|
||||||
|
color: #cc1818;
|
||||||
|
margin: -16px 0 24px;
|
||||||
|
@include font(11, 16, 450);
|
||||||
|
}
|
||||||
|
|
||||||
.onboarding-advanced-options {
|
.onboarding-advanced-options {
|
||||||
max-width: 800px;
|
max-width: 800px;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,121 @@
|
||||||
|
.ppcp-r-styling {
|
||||||
|
display: flex;
|
||||||
|
border: 1px solid $color-gray-200;
|
||||||
|
border-radius: 8px;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
&__section:not(:last-child) {
|
||||||
|
border-bottom: 1px solid black;
|
||||||
|
padding-bottom: 24px;
|
||||||
|
margin-bottom: 28px;
|
||||||
|
border-bottom: 1px solid $color-gray-600;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__main-title {
|
||||||
|
@include font(14, 20, 600);
|
||||||
|
color: $color-gray-800;
|
||||||
|
margin: 0 0 8px 0;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__description {
|
||||||
|
@include font(13, 20, 400);
|
||||||
|
color: $color-gray-800;
|
||||||
|
margin: 0 0 18px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__settings {
|
||||||
|
width: 422px;
|
||||||
|
background-color: $color-white;
|
||||||
|
padding: 48px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__preview {
|
||||||
|
width: calc(100% - 422px);
|
||||||
|
background-color: #FAF8F5;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
&-inner {
|
||||||
|
width: 100%;
|
||||||
|
padding: 24px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__section--rc {
|
||||||
|
.ppcp-r-styling__title {
|
||||||
|
@include font(13, 20, 600);
|
||||||
|
color: $color-black;
|
||||||
|
display: block;
|
||||||
|
margin: 0 0 18px 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__section--empty.ppcp-r-styling__section {
|
||||||
|
padding-bottom: 0;
|
||||||
|
margin-bottom: 0;
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__select {
|
||||||
|
label {
|
||||||
|
@include font(13, 16, 600);
|
||||||
|
color: $color-black;
|
||||||
|
margin: 0;
|
||||||
|
text-transform: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
select {
|
||||||
|
@include font(13, 20, 400);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.ppcp-r__checkbox {
|
||||||
|
.components-checkbox-control {
|
||||||
|
&__label {
|
||||||
|
@include font(13, 20, 400);
|
||||||
|
color: $color-black;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.components-flex {
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__payment-method-checkboxes {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 24px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.ppcp-r {
|
||||||
|
&__horizontal-control {
|
||||||
|
.components-flex {
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: flex-start;
|
||||||
|
gap: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.components-radio-control {
|
||||||
|
&__option {
|
||||||
|
gap: 12px;
|
||||||
|
|
||||||
|
input {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
label {
|
||||||
|
@include font(13, 20, 400);
|
||||||
|
color: $color-black;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
input {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -21,6 +21,7 @@
|
||||||
@import './components/reusable-components/welcome-docs';
|
@import './components/reusable-components/welcome-docs';
|
||||||
@import './components/screens/onboarding';
|
@import './components/screens/onboarding';
|
||||||
@import './components/screens/settings';
|
@import './components/screens/settings';
|
||||||
|
@import './components/screens/overview/tab-styling';
|
||||||
}
|
}
|
||||||
|
|
||||||
@import './components/reusable-components/payment-method-modal';
|
@import './components/reusable-components/payment-method-modal';
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { useEffect } from '@wordpress/element';
|
||||||
import { Icon } from '@wordpress/components';
|
import { Icon } from '@wordpress/components';
|
||||||
import { chevronDown, chevronUp } from '@wordpress/icons';
|
import { chevronDown, chevronUp } from '@wordpress/icons';
|
||||||
|
|
||||||
|
@ -5,11 +6,33 @@ import { useState } from 'react';
|
||||||
|
|
||||||
const Accordion = ( {
|
const Accordion = ( {
|
||||||
title,
|
title,
|
||||||
initiallyOpen = false,
|
initiallyOpen = null,
|
||||||
className = '',
|
className = '',
|
||||||
|
id = '',
|
||||||
children,
|
children,
|
||||||
} ) => {
|
} ) => {
|
||||||
const [ isOpen, setIsOpen ] = useState( initiallyOpen );
|
const determineInitialState = () => {
|
||||||
|
if ( id && initiallyOpen === null ) {
|
||||||
|
return window.location.hash === `#${ id }`;
|
||||||
|
}
|
||||||
|
return !! initiallyOpen;
|
||||||
|
};
|
||||||
|
|
||||||
|
const [ isOpen, setIsOpen ] = useState( determineInitialState );
|
||||||
|
|
||||||
|
useEffect( () => {
|
||||||
|
const handleHashChange = () => {
|
||||||
|
if ( id && window.location.hash === `#${ id }` ) {
|
||||||
|
setIsOpen( true );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
window.addEventListener( 'hashchange', handleHashChange );
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
window.removeEventListener( 'hashchange', handleHashChange );
|
||||||
|
};
|
||||||
|
}, [ id ] );
|
||||||
|
|
||||||
const toggleOpen = ( ev ) => {
|
const toggleOpen = ( ev ) => {
|
||||||
setIsOpen( ! isOpen );
|
setIsOpen( ! isOpen );
|
||||||
|
@ -26,7 +49,7 @@ const Accordion = ( {
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={ wrapperClasses.join( ' ' ) }>
|
<div className={ wrapperClasses.join( ' ' ) } id={ id }>
|
||||||
<button
|
<button
|
||||||
onClick={ toggleOpen }
|
onClick={ toggleOpen }
|
||||||
className="ppcp-r-accordion--title"
|
className="ppcp-r-accordion--title"
|
||||||
|
|
|
@ -1,39 +1,53 @@
|
||||||
import data from '../../utils/data';
|
import data from '../../utils/data';
|
||||||
import TitleBadge, { TITLE_BADGE_INFO } from "./TitleBadge";
|
import TitleBadge, { TITLE_BADGE_INFO } from './TitleBadge';
|
||||||
import { __ } from "@wordpress/i18n";
|
import { __ } from '@wordpress/i18n';
|
||||||
|
|
||||||
const BadgeBox = ( props ) => {
|
const BadgeBox = ( props ) => {
|
||||||
const titleSize = props.titleType && props.titleType === BADGE_BOX_TITLE_BIG ? BADGE_BOX_TITLE_BIG : BADGE_BOX_TITLE_SMALL
|
const titleSize =
|
||||||
|
props.titleType && props.titleType === BADGE_BOX_TITLE_BIG
|
||||||
|
? BADGE_BOX_TITLE_BIG
|
||||||
|
: BADGE_BOX_TITLE_SMALL;
|
||||||
|
|
||||||
const titleTextClassName = 'ppcp-r-badge-box__title-text ' + `ppcp-r-badge-box__title-text--${ titleSize }`;
|
const titleTextClassName =
|
||||||
|
'ppcp-r-badge-box__title-text ' +
|
||||||
|
`ppcp-r-badge-box__title-text--${ titleSize }`;
|
||||||
|
|
||||||
const titleBaseClassName = 'ppcp-r-badge-box__title';
|
const titleBaseClassName = 'ppcp-r-badge-box__title';
|
||||||
const titleClassName = props.imageBadge ? `${ titleBaseClassName } ppcp-r-badge-box__title--has-image-badge` : titleBaseClassName;
|
const titleClassName = props.imageBadge
|
||||||
|
? `${ titleBaseClassName } ppcp-r-badge-box__title--has-image-badge`
|
||||||
|
: titleBaseClassName;
|
||||||
return (
|
return (
|
||||||
<div className="ppcp-r-badge-box">
|
<div className="ppcp-r-badge-box">
|
||||||
<span className={ titleClassName }>
|
<span className={ titleClassName }>
|
||||||
<span className={ titleTextClassName }>{props.title}</span>
|
<span className={ titleTextClassName }>{ props.title }</span>
|
||||||
|
|
||||||
{ props.imageBadge && (
|
{ props.imageBadge && (
|
||||||
<span className="ppcp-r-badge-box__title-image-badge">
|
<span className="ppcp-r-badge-box__title-image-badge">
|
||||||
{ props.imageBadge.map( ( badge ) => data().getImage( badge ) ) }
|
{ props.imageBadge.map( ( badge ) =>
|
||||||
</span>
|
data().getImage( badge )
|
||||||
) }
|
) }
|
||||||
|
</span>
|
||||||
|
) }
|
||||||
|
|
||||||
{ props.textBadge && (
|
{ props.textBadge && (
|
||||||
<TitleBadge type={ TITLE_BADGE_INFO } text={ props.textBadge }/>
|
<TitleBadge
|
||||||
) }
|
type={ TITLE_BADGE_INFO }
|
||||||
</span>
|
text={ props.textBadge }
|
||||||
<div className="ppcp-r-badge-box__description">
|
/>
|
||||||
{ props?.description && (
|
) }
|
||||||
<p
|
</span>
|
||||||
className="ppcp-r-badge-box__description"
|
<div className="ppcp-r-badge-box__description">
|
||||||
dangerouslySetInnerHTML={ { __html: props.description, } }
|
{ props?.description && (
|
||||||
></p>
|
<p
|
||||||
) }
|
className="ppcp-r-badge-box__description"
|
||||||
</div>
|
dangerouslySetInnerHTML={ {
|
||||||
</div>
|
__html: props.description,
|
||||||
);
|
} }
|
||||||
|
></p>
|
||||||
|
) }
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const BADGE_BOX_TITLE_BIG = 'big';
|
export const BADGE_BOX_TITLE_BIG = 'big';
|
||||||
|
|
|
@ -1,25 +1,46 @@
|
||||||
import data from '../../utils/data';
|
import { CheckboxControl } from '@wordpress/components';
|
||||||
|
|
||||||
export const PayPalCheckbox = ( props ) => {
|
export const PayPalCheckbox = ( props ) => {
|
||||||
|
let isChecked = null;
|
||||||
|
|
||||||
|
if ( Array.isArray( props.currentValue ) ) {
|
||||||
|
isChecked = props.currentValue.includes( props.value );
|
||||||
|
} else {
|
||||||
|
isChecked = props.currentValue;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="ppcp-r__checkbox">
|
<div className="ppcp-r__checkbox">
|
||||||
<input
|
<CheckboxControl
|
||||||
className="ppcp-r__checkbox-value"
|
label={ props?.label ? props.label : '' }
|
||||||
type="checkbox"
|
|
||||||
checked={ props.currentValue.includes( props.value ) }
|
|
||||||
name={ props.name }
|
|
||||||
value={ props.value }
|
value={ props.value }
|
||||||
onChange={ ( e ) =>
|
checked={ isChecked }
|
||||||
props.handleCheckboxState( e.target.checked, props )
|
onChange={ ( checked ) =>
|
||||||
|
handleCheckboxState( checked, props )
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<span className="ppcp-r__checkbox-presentation">
|
|
||||||
{ data().getImage( 'icon-checkbox.svg' ) }
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const PayPalCheckboxGroup = ( props ) => {
|
||||||
|
const renderCheckboxGroup = () => {
|
||||||
|
return props.value.map( ( checkbox ) => {
|
||||||
|
return (
|
||||||
|
<PayPalCheckbox
|
||||||
|
label={ checkbox.label }
|
||||||
|
value={ checkbox.value }
|
||||||
|
key={ checkbox.value }
|
||||||
|
currentValue={ props.currentValue }
|
||||||
|
changeCallback={ props.changeCallback }
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
} );
|
||||||
|
};
|
||||||
|
|
||||||
|
return <>{ renderCheckboxGroup() }</>;
|
||||||
|
};
|
||||||
|
|
||||||
export const PayPalRdb = ( props ) => {
|
export const PayPalRdb = ( props ) => {
|
||||||
return (
|
return (
|
||||||
<div className="ppcp-r__radio">
|
<div className="ppcp-r__radio">
|
||||||
|
@ -73,9 +94,10 @@ export const PayPalRdbWithContent = ( props ) => {
|
||||||
|
|
||||||
export const handleCheckboxState = ( checked, props ) => {
|
export const handleCheckboxState = ( checked, props ) => {
|
||||||
let newValue = null;
|
let newValue = null;
|
||||||
if ( checked ) {
|
if ( ! Array.isArray( props.currentValue ) ) {
|
||||||
|
newValue = checked;
|
||||||
|
} else if ( checked ) {
|
||||||
newValue = [ ...props.currentValue, props.value ];
|
newValue = [ ...props.currentValue, props.value ];
|
||||||
props.changeCallback( newValue );
|
|
||||||
} else {
|
} else {
|
||||||
newValue = props.currentValue.filter(
|
newValue = props.currentValue.filter(
|
||||||
( value ) => value !== props.value
|
( value ) => value !== props.value
|
||||||
|
|
|
@ -0,0 +1,273 @@
|
||||||
|
import BadgeBox, { BADGE_BOX_TITLE_BIG } from '../BadgeBox';
|
||||||
|
import { __, sprintf } from '@wordpress/i18n';
|
||||||
|
import Separator from '../Separator';
|
||||||
|
import generatePriceText from '../../../utils/badgeBoxUtils';
|
||||||
|
import { countryPriceInfo } from '../../../utils/countryPriceInfo';
|
||||||
|
|
||||||
|
const AcdcOptionalPaymentMethods = ( {
|
||||||
|
isFastlane,
|
||||||
|
isPayLater,
|
||||||
|
storeCountry,
|
||||||
|
storeCurrency,
|
||||||
|
} ) => {
|
||||||
|
if ( isFastlane && isPayLater && storeCountry === 'us' ) {
|
||||||
|
return (
|
||||||
|
<div className="ppcp-r-optional-payment-methods__wrapper">
|
||||||
|
<BadgeBox
|
||||||
|
title={ __(
|
||||||
|
'Custom Card Fields',
|
||||||
|
'woocommerce-paypal-payments'
|
||||||
|
) }
|
||||||
|
imageBadge={ [
|
||||||
|
'icon-button-visa.svg',
|
||||||
|
'icon-button-mastercard.svg',
|
||||||
|
'icon-button-amex.svg',
|
||||||
|
'icon-button-discover.svg',
|
||||||
|
] }
|
||||||
|
textBadge={ generatePriceText(
|
||||||
|
'ccf',
|
||||||
|
countryPriceInfo[ storeCountry ],
|
||||||
|
storeCurrency
|
||||||
|
) }
|
||||||
|
description={ sprintf(
|
||||||
|
// translators: %s: Link to PayPal business fees guide
|
||||||
|
__(
|
||||||
|
'Style the credit card fields to match your own style. Includes advanced processing with risk management, 3D Secure, fraud protection options, and chargeback protection. <a target="_blank" href="%s">Learn more</a>',
|
||||||
|
'woocommerce-paypal-payments'
|
||||||
|
),
|
||||||
|
'https://www.paypal.com/us/business/paypal-business-fees'
|
||||||
|
) }
|
||||||
|
/>
|
||||||
|
<Separator className="ppcp-r-optional-payment-methods__separator" />
|
||||||
|
<BadgeBox
|
||||||
|
title={ __(
|
||||||
|
'Digital Wallets',
|
||||||
|
'woocommerce-paypal-payments'
|
||||||
|
) }
|
||||||
|
imageBadge={ [
|
||||||
|
'icon-button-apple-pay.svg',
|
||||||
|
'icon-button-google-pay.svg',
|
||||||
|
] }
|
||||||
|
textBadge={ generatePriceText(
|
||||||
|
'dw',
|
||||||
|
countryPriceInfo[ storeCountry ],
|
||||||
|
storeCurrency
|
||||||
|
) }
|
||||||
|
description={ sprintf(
|
||||||
|
// translators: %s: Link to PayPal business fees guide
|
||||||
|
__(
|
||||||
|
'Accept Apple Pay on eligible devices and Google Pay through mobile and web. <a target="_blank" href="%s">Learn more</a>',
|
||||||
|
'woocommerce-paypal-payments'
|
||||||
|
),
|
||||||
|
'https://www.paypal.com/us/business/paypal-business-fees'
|
||||||
|
) }
|
||||||
|
/>
|
||||||
|
<Separator className="ppcp-r-optional-payment-methods__separator" />
|
||||||
|
<BadgeBox
|
||||||
|
title={ __(
|
||||||
|
'Alternative Payment Methods',
|
||||||
|
'woocommerce-paypal-payments'
|
||||||
|
) }
|
||||||
|
imageBadge={ [
|
||||||
|
'icon-button-sepa.svg',
|
||||||
|
'icon-button-ideal.svg',
|
||||||
|
'icon-button-blik.svg',
|
||||||
|
'icon-button-bancontact.svg',
|
||||||
|
] }
|
||||||
|
textBadge={ generatePriceText(
|
||||||
|
'apm',
|
||||||
|
countryPriceInfo[ storeCountry ],
|
||||||
|
storeCurrency
|
||||||
|
) }
|
||||||
|
description={ sprintf(
|
||||||
|
// translators: %s: Link to PayPal business fees guide
|
||||||
|
__(
|
||||||
|
'Seamless payments for customers across the globe using their preferred payment methods. <a target="_blank" href="%s">Learn more</a>',
|
||||||
|
'woocommerce-paypal-payments'
|
||||||
|
),
|
||||||
|
'https://www.paypal.com/us/business/paypal-business-fees'
|
||||||
|
) }
|
||||||
|
/>
|
||||||
|
<Separator className="ppcp-r-optional-payment-methods__separator" />
|
||||||
|
<BadgeBox
|
||||||
|
title={ __( '', 'woocommerce-paypal-payments' ) }
|
||||||
|
imageBadge={ [ 'icon-payment-method-fastlane-small.svg' ] }
|
||||||
|
textBadge={ generatePriceText(
|
||||||
|
'fastlane',
|
||||||
|
countryPriceInfo[ storeCountry ],
|
||||||
|
storeCurrency
|
||||||
|
) }
|
||||||
|
description={ sprintf(
|
||||||
|
// translators: %s: Link to PayPal business fees guide
|
||||||
|
__(
|
||||||
|
'Speed up guest checkout with Fatslane. Link a customer\'s email address to their payment details. <a target="_blank" href="%s">Learn more</a>',
|
||||||
|
'woocommerce-paypal-payments'
|
||||||
|
),
|
||||||
|
'https://www.paypal.com/us/business/paypal-business-fees'
|
||||||
|
) }
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( isPayLater && storeCountry === 'uk' ) {
|
||||||
|
return (
|
||||||
|
<div className="ppcp-r-optional-payment-methods__wrapper">
|
||||||
|
<BadgeBox
|
||||||
|
title={ __(
|
||||||
|
'Custom Card Fields',
|
||||||
|
'woocommerce-paypal-payments'
|
||||||
|
) }
|
||||||
|
imageBadge={ [
|
||||||
|
'icon-button-visa.svg',
|
||||||
|
'icon-button-mastercard.svg',
|
||||||
|
'icon-button-amex.svg',
|
||||||
|
'icon-button-discover.svg',
|
||||||
|
] }
|
||||||
|
textBadge={ generatePriceText(
|
||||||
|
'ccf',
|
||||||
|
countryPriceInfo[ storeCountry ],
|
||||||
|
storeCurrency
|
||||||
|
) }
|
||||||
|
description={ sprintf(
|
||||||
|
// translators: %s: Link to PayPal business fees guide
|
||||||
|
__(
|
||||||
|
'Style the credit card fields to match your own style. Includes advanced processing with risk management, 3D Secure, fraud protection options, and chargeback protection. <a target="_blank" href="%s">Learn more</a>',
|
||||||
|
'woocommerce-paypal-payments'
|
||||||
|
),
|
||||||
|
'https://www.paypal.com/us/business/paypal-business-fees'
|
||||||
|
) }
|
||||||
|
/>
|
||||||
|
<Separator className="ppcp-r-optional-payment-methods__separator" />
|
||||||
|
<BadgeBox
|
||||||
|
title={ __(
|
||||||
|
'Digital Wallets',
|
||||||
|
'woocommerce-paypal-payments'
|
||||||
|
) }
|
||||||
|
imageBadge={ [
|
||||||
|
'icon-button-apple-pay.svg',
|
||||||
|
'icon-button-google-pay.svg',
|
||||||
|
] }
|
||||||
|
textBadge={ generatePriceText(
|
||||||
|
'dw',
|
||||||
|
countryPriceInfo[ storeCountry ],
|
||||||
|
storeCurrency
|
||||||
|
) }
|
||||||
|
description={ sprintf(
|
||||||
|
// translators: %s: Link to PayPal business fees guide
|
||||||
|
__(
|
||||||
|
'Accept Apple Pay on eligible devices and Google Pay through mobile and web. <a target="_blank" href="%s">Learn more</a>',
|
||||||
|
'woocommerce-paypal-payments'
|
||||||
|
),
|
||||||
|
'https://www.paypal.com/us/business/paypal-business-fees'
|
||||||
|
) }
|
||||||
|
/>
|
||||||
|
<Separator className="ppcp-r-optional-payment-methods__separator" />
|
||||||
|
<BadgeBox
|
||||||
|
title={ __(
|
||||||
|
'Alternative Payment Methods',
|
||||||
|
'woocommerce-paypal-payments'
|
||||||
|
) }
|
||||||
|
imageBadge={ [
|
||||||
|
'icon-button-sepa.svg',
|
||||||
|
'icon-button-ideal.svg',
|
||||||
|
'icon-button-blik.svg',
|
||||||
|
'icon-button-bancontact.svg',
|
||||||
|
] }
|
||||||
|
textBadge={ generatePriceText(
|
||||||
|
'apm',
|
||||||
|
countryPriceInfo[ storeCountry ],
|
||||||
|
storeCurrency
|
||||||
|
) }
|
||||||
|
description={ sprintf(
|
||||||
|
// translators: %s: Link to PayPal business fees guide
|
||||||
|
__(
|
||||||
|
'Seamless payments for customers across the globe using their preferred payment methods. <a target="_blank" href="%s">Learn more</a>',
|
||||||
|
'woocommerce-paypal-payments'
|
||||||
|
),
|
||||||
|
'https://www.paypal.com/us/business/paypal-business-fees'
|
||||||
|
) }
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="ppcp-r-optional-payment-methods__wrapper">
|
||||||
|
<BadgeBox
|
||||||
|
title={ __(
|
||||||
|
'Custom Card Fields',
|
||||||
|
'woocommerce-paypal-payments'
|
||||||
|
) }
|
||||||
|
imageBadge={ [
|
||||||
|
'icon-button-visa.svg',
|
||||||
|
'icon-button-mastercard.svg',
|
||||||
|
'icon-button-amex.svg',
|
||||||
|
'icon-button-discover.svg',
|
||||||
|
] }
|
||||||
|
textBadge={ generatePriceText(
|
||||||
|
'ccf',
|
||||||
|
countryPriceInfo[ storeCountry ],
|
||||||
|
storeCurrency
|
||||||
|
) }
|
||||||
|
description={ sprintf(
|
||||||
|
// translators: %s: Link to PayPal business fees guide
|
||||||
|
__(
|
||||||
|
'Style the credit card fields to match your own style. Includes advanced processing with risk management, 3D Secure, fraud protection options, and chargeback protection. <a target="_blank" href="%s">Learn more</a>',
|
||||||
|
'woocommerce-paypal-payments'
|
||||||
|
),
|
||||||
|
'https://www.paypal.com/us/business/paypal-business-fees'
|
||||||
|
) }
|
||||||
|
/>
|
||||||
|
<Separator className="ppcp-r-optional-payment-methods__separator" />
|
||||||
|
<BadgeBox
|
||||||
|
title={ __( 'Digital Wallets', 'woocommerce-paypal-payments' ) }
|
||||||
|
imageBadge={ [
|
||||||
|
'icon-button-apple-pay.svg',
|
||||||
|
'icon-button-google-pay.svg',
|
||||||
|
] }
|
||||||
|
textBadge={ generatePriceText(
|
||||||
|
'dw',
|
||||||
|
countryPriceInfo[ storeCountry ],
|
||||||
|
storeCurrency
|
||||||
|
) }
|
||||||
|
description={ sprintf(
|
||||||
|
// translators: %s: Link to PayPal business fees guide
|
||||||
|
__(
|
||||||
|
'Accept Apple Pay on eligible devices and Google Pay through mobile and web. <a target="_blank" href="%s">Learn more</a>',
|
||||||
|
'woocommerce-paypal-payments'
|
||||||
|
),
|
||||||
|
'https://www.paypal.com/us/business/paypal-business-fees'
|
||||||
|
) }
|
||||||
|
/>
|
||||||
|
<Separator className="ppcp-r-optional-payment-methods__separator" />
|
||||||
|
<BadgeBox
|
||||||
|
title={ __(
|
||||||
|
'Alternative Payment Methods',
|
||||||
|
'woocommerce-paypal-payments'
|
||||||
|
) }
|
||||||
|
imageBadge={ [
|
||||||
|
'icon-button-sepa.svg',
|
||||||
|
'icon-button-ideal.svg',
|
||||||
|
'icon-button-blik.svg',
|
||||||
|
'icon-button-bancontact.svg',
|
||||||
|
] }
|
||||||
|
textBadge={ generatePriceText(
|
||||||
|
'apm',
|
||||||
|
countryPriceInfo[ storeCountry ],
|
||||||
|
storeCurrency
|
||||||
|
) }
|
||||||
|
description={ sprintf(
|
||||||
|
// translators: %s: Link to PayPal business fees guide
|
||||||
|
__(
|
||||||
|
'Seamless payments for customers across the globe using their preferred payment methods. <a target="_blank" href="%s">Learn more</a>',
|
||||||
|
'woocommerce-paypal-payments'
|
||||||
|
),
|
||||||
|
'https://www.paypal.com/us/business/paypal-business-fees'
|
||||||
|
) }
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default AcdcOptionalPaymentMethods;
|
|
@ -0,0 +1,74 @@
|
||||||
|
import BadgeBox from '../BadgeBox';
|
||||||
|
import { __, sprintf } from '@wordpress/i18n';
|
||||||
|
import generatePriceText from '../../../utils/badgeBoxUtils';
|
||||||
|
import { countryPriceInfo } from '../../../utils/countryPriceInfo';
|
||||||
|
|
||||||
|
const BcdcOptionalPaymentMethods = ( {
|
||||||
|
isPayLater,
|
||||||
|
storeCountry,
|
||||||
|
storeCurrency,
|
||||||
|
} ) => {
|
||||||
|
if ( isPayLater && storeCountry === 'us' ) {
|
||||||
|
return (
|
||||||
|
<div className="ppcp-r-optional-payment-methods__wrapper">
|
||||||
|
<BadgeBox
|
||||||
|
title={ __(
|
||||||
|
'Credit and Debit Cards',
|
||||||
|
'woocommerce-paypal-payments'
|
||||||
|
) }
|
||||||
|
imageBadge={ [
|
||||||
|
'icon-button-visa.svg',
|
||||||
|
'icon-button-mastercard.svg',
|
||||||
|
'icon-button-amex.svg',
|
||||||
|
'icon-button-discover.svg',
|
||||||
|
] }
|
||||||
|
textBadge={ generatePriceText(
|
||||||
|
'standardCardFields',
|
||||||
|
countryPriceInfo[ storeCountry ],
|
||||||
|
storeCurrency
|
||||||
|
) }
|
||||||
|
description={ sprintf(
|
||||||
|
// translators: %s: Link to PayPal REST application guide
|
||||||
|
__(
|
||||||
|
'Process major credit and debit cards through PayPal’s card fields. <a target="_blank" href="%s">Learn more</a>',
|
||||||
|
'woocommerce-paypal-payments'
|
||||||
|
),
|
||||||
|
'https://woocommerce.com/document/woocommerce-paypal-payments/#manual-credential-input '
|
||||||
|
) }
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="ppcp-r-optional-payment-methods__wrapper">
|
||||||
|
<BadgeBox
|
||||||
|
title={ __(
|
||||||
|
'Credit and Debit Cards',
|
||||||
|
'woocommerce-paypal-payments'
|
||||||
|
) }
|
||||||
|
imageBadge={ [
|
||||||
|
'icon-button-visa.svg',
|
||||||
|
'icon-button-mastercard.svg',
|
||||||
|
'icon-button-amex.svg',
|
||||||
|
'icon-button-discover.svg',
|
||||||
|
] }
|
||||||
|
textBadge={ generatePriceText(
|
||||||
|
'standardCardFields',
|
||||||
|
countryPriceInfo[ storeCountry ],
|
||||||
|
storeCurrency
|
||||||
|
) }
|
||||||
|
description={ sprintf(
|
||||||
|
// translators: %s: Link to PayPal REST application guide
|
||||||
|
__(
|
||||||
|
'Process major credit and debit cards through PayPal’s card fields. <a target="_blank" href="%s">Learn more</a>',
|
||||||
|
'woocommerce-paypal-payments'
|
||||||
|
),
|
||||||
|
'https://woocommerce.com/document/woocommerce-paypal-payments/#manual-credential-input '
|
||||||
|
) }
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default BcdcOptionalPaymentMethods;
|
|
@ -0,0 +1,31 @@
|
||||||
|
import AcdcOptionalPaymentMethods from './AcdcOptionalPaymentMethods';
|
||||||
|
import BcdcOptionalPaymentMethods from './BcdcOptionalPaymentMethods';
|
||||||
|
|
||||||
|
const OptionalPaymentMethods = ( {
|
||||||
|
useAcdc,
|
||||||
|
isFastlane,
|
||||||
|
isPayLater,
|
||||||
|
storeCountry,
|
||||||
|
storeCurrency,
|
||||||
|
} ) => {
|
||||||
|
return (
|
||||||
|
<div className="ppcp-r-optional-payment-methods">
|
||||||
|
{ useAcdc ? (
|
||||||
|
<AcdcOptionalPaymentMethods
|
||||||
|
isFastlane={ isFastlane }
|
||||||
|
isPayLater={ isPayLater }
|
||||||
|
storeCountry={ storeCountry }
|
||||||
|
storeCurrency={ storeCurrency }
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<BcdcOptionalPaymentMethods
|
||||||
|
isPayLater={ isPayLater }
|
||||||
|
storeCountry={ storeCountry }
|
||||||
|
storeCurrency={ storeCurrency }
|
||||||
|
/>
|
||||||
|
) }
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default OptionalPaymentMethods;
|
|
@ -1,5 +1,5 @@
|
||||||
import data from '../../utils/data';
|
import data from '../../utils/data';
|
||||||
import { PayPalCheckbox, PayPalRdb, handleCheckboxState } from './Fields';
|
import { PayPalCheckbox, PayPalRdb } from './Fields';
|
||||||
|
|
||||||
const SelectBox = ( props ) => {
|
const SelectBox = ( props ) => {
|
||||||
let boxClassName = 'ppcp-r-select-box';
|
let boxClassName = 'ppcp-r-select-box';
|
||||||
|
@ -24,10 +24,7 @@ const SelectBox = ( props ) => {
|
||||||
) }
|
) }
|
||||||
{ props.type === 'checkbox' && (
|
{ props.type === 'checkbox' && (
|
||||||
<PayPalCheckbox
|
<PayPalCheckbox
|
||||||
{ ...{
|
{ ...props }
|
||||||
...props,
|
|
||||||
handleCheckboxState,
|
|
||||||
} }
|
|
||||||
/>
|
/>
|
||||||
) }
|
) }
|
||||||
<div className="ppcp-r-select-box__content">
|
<div className="ppcp-r-select-box__content">
|
||||||
|
|
|
@ -1,24 +1,32 @@
|
||||||
const Separator = ( props ) => {
|
const Separator = ( { className = '', text = '', withLine = true } ) => {
|
||||||
let separatorClass = 'ppcp-r-separator';
|
const separatorClass = [ 'ppcp-r-separator' ];
|
||||||
|
const innerClass = withLine
|
||||||
|
? 'ppcp-r-separator__line'
|
||||||
|
: 'ppcp-r-separator__space';
|
||||||
|
|
||||||
if ( props?.className ) {
|
if ( className ) {
|
||||||
separatorClass += ' ' + props.className;
|
separatorClass.push( className );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( props.text ) {
|
const getClass = ( type ) => `${ innerClass } ${ innerClass }--${ type }`;
|
||||||
return (
|
|
||||||
<div className={ separatorClass }>
|
|
||||||
<span className="ppcp-r-separator__line ppcp-r-separator__line--before"></span>
|
|
||||||
|
|
||||||
<span className="ppcp-r-separator__text">{ props.text }</span>
|
const renderSeparator = () => {
|
||||||
<span className="ppcp-r-separator__line ppcp-r-separator__line--after"></span>
|
if ( text ) {
|
||||||
</div>
|
return (
|
||||||
);
|
<>
|
||||||
}
|
<span className={ getClass( 'before' ) }></span>
|
||||||
|
<span className="ppcp-r-separator__text">{ text }</span>
|
||||||
|
<span className={ getClass( 'after' ) }></span>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return <span className={ getClass( 'full' ) }></span>;
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={ separatorClass }>
|
<div className={ separatorClass.join( ' ' ) }>
|
||||||
<span className="ppcp-r-separator__line ppcp-r-separator__line--before"></span>
|
{ renderSeparator() }
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,327 +1,290 @@
|
||||||
import BadgeBox, { BADGE_BOX_TITLE_BIG } from "../BadgeBox";
|
import BadgeBox, { BADGE_BOX_TITLE_BIG } from '../BadgeBox';
|
||||||
import { __, sprintf } from '@wordpress/i18n';
|
import { __, sprintf } from '@wordpress/i18n';
|
||||||
import Separator from '../Separator';
|
import Separator from '../Separator';
|
||||||
|
import generatePriceText from '../../../utils/badgeBoxUtils';
|
||||||
|
import { countryPriceInfo } from '../../../utils/countryPriceInfo';
|
||||||
|
|
||||||
const AcdcFlow = ( { isFastlane, isPayLater, storeCountry } ) => {
|
import OptionalPaymentMethods from '../OptionalPaymentMethods/OptionalPaymentMethods';
|
||||||
if (isFastlane && isPayLater && storeCountry === 'us') {
|
|
||||||
return (
|
|
||||||
<div className="ppcp-r-welcome-docs__wrapper">
|
|
||||||
<div className="ppcp-r-welcome-docs__col">
|
|
||||||
<BadgeBox
|
|
||||||
title={__('PayPal Checkout', 'woocommerce-paypal-payments')}
|
|
||||||
titleType={BADGE_BOX_TITLE_BIG}
|
|
||||||
textBadge={__('from 3.49% + $0.49 USD<sup>1</sup>', 'woocommerce-paypal-payments')}
|
|
||||||
description={__(
|
|
||||||
'Our all-in-one checkout solution lets you offer PayPal, Venmo, Pay Later options, and more to help maximise conversion',
|
|
||||||
'woocommerce-paypal-payments'
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
<BadgeBox
|
|
||||||
title={__('Included in PayPal Checkout', 'woocommerce-paypal-payments')}
|
|
||||||
titleType={BADGE_BOX_TITLE_BIG}/>
|
|
||||||
<BadgeBox
|
|
||||||
title={__('Pay with PayPal', 'woocommerce-paypal-payments')}
|
|
||||||
imageBadge={['icon-button-paypal.svg']}
|
|
||||||
description={sprintf(
|
|
||||||
// translators: %s: Link to PayPal REST application guide
|
|
||||||
__(
|
|
||||||
'Our brand recognition helps give customers the confidence to buy. <a target="_blank" href="%s">Learn more</a>',
|
|
||||||
'woocommerce-paypal-payments'
|
|
||||||
),
|
|
||||||
'https://woocommerce.com/document/woocommerce-paypal-payments/#manual-credential-input '
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
<Separator className="ppcp-r-page-welcome-mode-separator"/>
|
|
||||||
<BadgeBox
|
|
||||||
title={__('Pay Later', 'woocommerce-paypal-payments')}
|
|
||||||
imageBadge={['icon-payment-method-paypal-small.svg']}
|
|
||||||
description={sprintf(
|
|
||||||
// translators: %s: Link to PayPal REST application guide
|
|
||||||
__(
|
|
||||||
'Offer installment payment options and get paid upfront - at no extra cost to you. <a target="_blank" href="%s">Learn more</a>',
|
|
||||||
'woocommerce-paypal-payments'
|
|
||||||
),
|
|
||||||
'https://woocommerce.com/document/woocommerce-paypal-payments/#manual-credential-input '
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
<Separator className="ppcp-r-page-welcome-mode-separator"/>
|
|
||||||
<BadgeBox
|
|
||||||
title={__('Venmo', 'woocommerce-paypal-payments')}
|
|
||||||
imageBadge={['icon-button-venmo.svg']}
|
|
||||||
description={sprintf(
|
|
||||||
// translators: %s: Link to PayPal REST application guide
|
|
||||||
__(
|
|
||||||
'Automatically offer Venmo checkout to millions of active users. <a target="_blank" href="%s">Learn more</a>',
|
|
||||||
'woocommerce-paypal-payments'
|
|
||||||
),
|
|
||||||
'https://woocommerce.com/document/woocommerce-paypal-payments/#manual-credential-input '
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
<Separator className="ppcp-r-page-welcome-mode-separator"/>
|
|
||||||
<BadgeBox
|
|
||||||
title={__('Crypto', 'woocommerce-paypal-payments')}
|
|
||||||
imageBadge={['icon-payment-method-crypto.svg']}
|
|
||||||
description={sprintf(
|
|
||||||
// translators: %s: Link to PayPal REST application guide
|
|
||||||
__(
|
|
||||||
'Let customers checkout with Crypto while you get paid in cash. <a target="_blank" href="%s">Learn more</a>',
|
|
||||||
'woocommerce-paypal-payments'
|
|
||||||
),
|
|
||||||
'https://woocommerce.com/document/woocommerce-paypal-payments/#manual-credential-input '
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="ppcp-r-welcome-docs__col">
|
|
||||||
<BadgeBox
|
|
||||||
title={__('Optional payment methods', 'woocommerce-paypal-payments')}
|
|
||||||
titleType={BADGE_BOX_TITLE_BIG}
|
|
||||||
description={__('with additional application', 'woocommerce-paypal-payments')}
|
|
||||||
/>
|
|
||||||
<BadgeBox
|
|
||||||
title={__('Custom Card Fields', 'woocommerce-paypal-payments')}
|
|
||||||
imageBadge={['icon-button-visa.svg', 'icon-button-mastercard.svg', 'icon-button-amex.svg', 'icon-button-discover.svg']}
|
|
||||||
textBadge={__('from 2.59% + $0.49 USD<sup>1</sup>', 'woocommerce-paypal-payments')}
|
|
||||||
description={sprintf(
|
|
||||||
// translators: %s: Link to PayPal REST application guide
|
|
||||||
__(
|
|
||||||
'Style the credit card fields to match your own style. Includes advanced processing with risk management, 3D Secure, fraud protection options, and chargeback protection. <a target="_blank" href="%s">Learn more</a>',
|
|
||||||
'woocommerce-paypal-payments'
|
|
||||||
),
|
|
||||||
'https://woocommerce.com/document/woocommerce-paypal-payments/#manual-credential-input '
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
<Separator className="ppcp-r-page-welcome-mode-separator"/>
|
|
||||||
<BadgeBox
|
|
||||||
title={__('Digital Wallets', 'woocommerce-paypal-payments')}
|
|
||||||
imageBadge={['icon-button-apple-pay.svg', 'icon-button-google-pay.svg']}
|
|
||||||
textBadge={__('from 2.59% + $0.49 USD<sup>1</sup>', 'woocommerce-paypal-payments')}
|
|
||||||
description={sprintf(
|
|
||||||
// translators: %s: Link to PayPal REST application guide
|
|
||||||
__(
|
|
||||||
'Accept Apple Pay on eligible devices and Google Pay through mobile and web. <a target="_blank" href="%s">Learn more</a>',
|
|
||||||
'woocommerce-paypal-payments'
|
|
||||||
),
|
|
||||||
'https://woocommerce.com/document/woocommerce-paypal-payments/#manual-credential-input '
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
<Separator className="ppcp-r-page-welcome-mode-separator"/>
|
|
||||||
<BadgeBox
|
|
||||||
title={__('Alternative Payment Methods', 'woocommerce-paypal-payments')}
|
|
||||||
imageBadge={['icon-button-sepa.svg', 'icon-button-ideal.svg', 'icon-button-blik.svg', 'icon-button-bancontact.svg']}
|
|
||||||
textBadge={__('from 3.49% + $0.49 USD<sup>1</sup>', 'woocommerce-paypal-payments')}
|
|
||||||
description={sprintf(
|
|
||||||
// translators: %s: Link to PayPal REST application guide
|
|
||||||
__(
|
|
||||||
'Seamless payments for customers across the globe using their preferred payment methods. <a target="_blank" href="%s">Learn more</a>',
|
|
||||||
'woocommerce-paypal-payments'
|
|
||||||
),
|
|
||||||
'https://woocommerce.com/document/woocommerce-paypal-payments/#manual-credential-input '
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
<Separator className="ppcp-r-page-welcome-mode-separator"/>
|
|
||||||
<BadgeBox
|
|
||||||
title={__('', 'woocommerce-paypal-payments')}
|
|
||||||
imageBadge={['icon-payment-method-fastlane-small.svg']}
|
|
||||||
textBadge={__('from 2.59% + $0.49 USD<sup>1</sup>', 'woocommerce-paypal-payments')}
|
|
||||||
description={sprintf(
|
|
||||||
// translators: %s: Link to PayPal REST application guide
|
|
||||||
__(
|
|
||||||
'Speed up guest checkout with Fatslane. Link a customer\'s email address to their payment details. <a target="_blank" href="%s">Learn more</a>',
|
|
||||||
'woocommerce-paypal-payments'
|
|
||||||
),
|
|
||||||
'https://woocommerce.com/document/woocommerce-paypal-payments/#manual-credential-input '
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isPayLater && storeCountry === 'uk') {
|
const AcdcFlow = ( {
|
||||||
return (
|
isFastlane,
|
||||||
<div className="ppcp-r-welcome-docs__wrapper">
|
isPayLater,
|
||||||
<div className="ppcp-r-welcome-docs__col">
|
storeCountry,
|
||||||
<BadgeBox
|
storeCurrency,
|
||||||
title={__('PayPal Checkout', 'woocommerce-paypal-payments')}
|
} ) => {
|
||||||
titleType={BADGE_BOX_TITLE_BIG}
|
if ( isFastlane && isPayLater && storeCountry === 'us' ) {
|
||||||
textBadge={__('from 2.90% + £0.30 GBP<sup>1</sup>', 'woocommerce-paypal-payments')}
|
return (
|
||||||
description={__(
|
<div className="ppcp-r-welcome-docs__wrapper">
|
||||||
'Our all-in-one checkout solution lets you offer PayPal, Venmo, Pay Later options, and more to help maximise conversion',
|
<div className="ppcp-r-welcome-docs__col">
|
||||||
'woocommerce-paypal-payments'
|
<BadgeBox
|
||||||
)}
|
title={ __(
|
||||||
/>
|
'PayPal Checkout',
|
||||||
<BadgeBox
|
'woocommerce-paypal-payments'
|
||||||
title={__('Included in PayPal Checkout', 'woocommerce-paypal-payments')}
|
) }
|
||||||
titleType={BADGE_BOX_TITLE_BIG}/>
|
titleType={ BADGE_BOX_TITLE_BIG }
|
||||||
<BadgeBox
|
textBadge={ generatePriceText(
|
||||||
title={__('Pay with PayPal', 'woocommerce-paypal-payments')}
|
'checkout',
|
||||||
imageBadge={['icon-button-paypal.svg']}
|
countryPriceInfo[ storeCountry ],
|
||||||
description={sprintf(
|
storeCurrency
|
||||||
// translators: %s: Link to PayPal REST application guide
|
) }
|
||||||
__(
|
description={ __(
|
||||||
'Our brand recognition helps give customers the confidence to buy. <a target="_blank" href="%s">Learn more</a>',
|
'Our all-in-one checkout solution lets you offer PayPal, Venmo, Pay Later options, and more to help maximise conversion',
|
||||||
'woocommerce-paypal-payments'
|
'woocommerce-paypal-payments'
|
||||||
),
|
) }
|
||||||
'https://woocommerce.com/document/woocommerce-paypal-payments/#manual-credential-input '
|
/>
|
||||||
)}
|
<BadgeBox
|
||||||
/>
|
title={ __(
|
||||||
<Separator className="ppcp-r-page-welcome-mode-separator"/>
|
'Included in PayPal Checkout',
|
||||||
<BadgeBox
|
'woocommerce-paypal-payments'
|
||||||
title={__('Pay in 3', 'woocommerce-paypal-payments')}
|
) }
|
||||||
imageBadge={['icon-payment-method-paypal-small.svg']}
|
titleType={ BADGE_BOX_TITLE_BIG }
|
||||||
description={sprintf(
|
/>
|
||||||
// translators: %s: Link to PayPal REST application guide
|
<BadgeBox
|
||||||
__(
|
title={ __(
|
||||||
'Offer installment payment options and get paid upfront - at no extra cost to you. <a target="_blank" href="%s">Learn more</a>',
|
'Pay with PayPal',
|
||||||
'woocommerce-paypal-payments'
|
'woocommerce-paypal-payments'
|
||||||
),
|
) }
|
||||||
'https://woocommerce.com/document/woocommerce-paypal-payments/#manual-credential-input '
|
imageBadge={ [ 'icon-button-paypal.svg' ] }
|
||||||
)}
|
description={ sprintf(
|
||||||
/>
|
// translators: %s: Link to PayPal business fees guide
|
||||||
</div>
|
__(
|
||||||
<div className="ppcp-r-welcome-docs__col">
|
'Our brand recognition helps give customers the confidence to buy. <a target="_blank" href="%s">Learn more</a>',
|
||||||
<BadgeBox
|
'woocommerce-paypal-payments'
|
||||||
title={__('Optional payment methods', 'woocommerce-paypal-payments')}
|
),
|
||||||
titleType={BADGE_BOX_TITLE_BIG}
|
'https://www.paypal.com/us/business/paypal-business-fees'
|
||||||
description={__('with additional application', 'woocommerce-paypal-payments')}
|
) }
|
||||||
/>
|
/>
|
||||||
<BadgeBox
|
<Separator className="ppcp-r-page-welcome-mode-separator" />
|
||||||
title={__('Custom Card Fields', 'woocommerce-paypal-payments')}
|
<BadgeBox
|
||||||
imageBadge={['icon-button-visa.svg', 'icon-button-mastercard.svg', 'icon-button-amex.svg', 'icon-button-discover.svg']}
|
title={ __(
|
||||||
textBadge={__('from 1.20% + £0.30 GBP<sup>1</sup>', 'woocommerce-paypal-payments')}
|
'Pay Later',
|
||||||
description={sprintf(
|
'woocommerce-paypal-payments'
|
||||||
// translators: %s: Link to PayPal REST application guide
|
) }
|
||||||
__(
|
imageBadge={ [
|
||||||
'Style the credit card fields to match your own style. Includes advanced processing with risk management, 3D Secure, fraud protection options, and chargeback protection. <a target="_blank" href="%s">Learn more</a>',
|
'icon-payment-method-paypal-small.svg',
|
||||||
'woocommerce-paypal-payments'
|
] }
|
||||||
),
|
description={ sprintf(
|
||||||
'https://woocommerce.com/document/woocommerce-paypal-payments/#manual-credential-input '
|
// translators: %s: Link to PayPal business fees guide
|
||||||
)}
|
__(
|
||||||
/>
|
'Offer installment payment options and get paid upfront - at no extra cost to you. <a target="_blank" href="%s">Learn more</a>',
|
||||||
<Separator className="ppcp-r-page-welcome-mode-separator"/>
|
'woocommerce-paypal-payments'
|
||||||
<BadgeBox
|
),
|
||||||
title={__('Digital Wallets', 'woocommerce-paypal-payments')}
|
'https://www.paypal.com/us/business/paypal-business-fees'
|
||||||
imageBadge={['icon-button-apple-pay.svg', 'icon-button-google-pay.svg']}
|
) }
|
||||||
textBadge={__('from 1.20% + £0.30 GBP<sup>1</sup>', 'woocommerce-paypal-payments')}
|
/>
|
||||||
description={sprintf(
|
<Separator className="ppcp-r-page-welcome-mode-separator" />
|
||||||
// translators: %s: Link to PayPal REST application guide
|
<BadgeBox
|
||||||
__(
|
title={ __( 'Venmo', 'woocommerce-paypal-payments' ) }
|
||||||
'Accept Apple Pay on eligible devices and Google Pay through mobile and web. <a target="_blank" href="%s">Learn more</a>',
|
imageBadge={ [ 'icon-button-venmo.svg' ] }
|
||||||
'woocommerce-paypal-payments'
|
description={ sprintf(
|
||||||
),
|
// translators: %s: Link to PayPal business fees guide
|
||||||
'https://woocommerce.com/document/woocommerce-paypal-payments/#manual-credential-input '
|
__(
|
||||||
)}
|
'Automatically offer Venmo checkout to millions of active users. <a target="_blank" href="%s">Learn more</a>',
|
||||||
/>
|
'woocommerce-paypal-payments'
|
||||||
<Separator className="ppcp-r-page-welcome-mode-separator"/>
|
),
|
||||||
<BadgeBox
|
'https://www.paypal.com/us/business/paypal-business-fees'
|
||||||
title={__('Alternative Payment Methods', 'woocommerce-paypal-payments')}
|
) }
|
||||||
imageBadge={['icon-button-sepa.svg', 'icon-button-ideal.svg', 'icon-button-blik.svg', 'icon-button-bancontact.svg']}
|
/>
|
||||||
textBadge={__('from 1.20% + £0.30 GBP<sup>1</sup>', 'woocommerce-paypal-payments')}
|
<Separator className="ppcp-r-page-welcome-mode-separator" />
|
||||||
description={sprintf(
|
<BadgeBox
|
||||||
// translators: %s: Link to PayPal REST application guide
|
title={ __( 'Crypto', 'woocommerce-paypal-payments' ) }
|
||||||
__(
|
imageBadge={ [ 'icon-payment-method-crypto.svg' ] }
|
||||||
'Seamless payments for customers across the globe using their preferred payment methods. <a target="_blank" href="%s">Learn more</a>',
|
description={ sprintf(
|
||||||
'woocommerce-paypal-payments'
|
// translators: %s: Link to PayPal business fees guide
|
||||||
),
|
__(
|
||||||
'https://woocommerce.com/document/woocommerce-paypal-payments/#manual-credential-input '
|
'Let customers checkout with Crypto while you get paid in cash. <a target="_blank" href="%s">Learn more</a>',
|
||||||
)}
|
'woocommerce-paypal-payments'
|
||||||
/>
|
),
|
||||||
</div>
|
'https://www.paypal.com/us/business/paypal-business-fees'
|
||||||
</div>
|
) }
|
||||||
);
|
/>
|
||||||
}
|
</div>
|
||||||
|
<div className="ppcp-r-welcome-docs__col">
|
||||||
|
<BadgeBox
|
||||||
|
title={ __(
|
||||||
|
'Optional payment methods',
|
||||||
|
'woocommerce-paypal-payments'
|
||||||
|
) }
|
||||||
|
titleType={ BADGE_BOX_TITLE_BIG }
|
||||||
|
description={ __(
|
||||||
|
'with additional application',
|
||||||
|
'woocommerce-paypal-payments'
|
||||||
|
) }
|
||||||
|
/>
|
||||||
|
<OptionalPaymentMethods
|
||||||
|
useAcdc={ true }
|
||||||
|
isFastlane={ isFastlane }
|
||||||
|
isPayLater={ isPayLater }
|
||||||
|
storeCountry={ storeCountry }
|
||||||
|
storeCurrency={ storeCurrency }
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
if ( isPayLater && storeCountry === 'uk' ) {
|
||||||
<div className="ppcp-r-welcome-docs__wrapper">
|
return (
|
||||||
<div className="ppcp-r-welcome-docs__col">
|
<div className="ppcp-r-welcome-docs__wrapper">
|
||||||
<BadgeBox
|
<div className="ppcp-r-welcome-docs__col">
|
||||||
title={__('PayPal Checkout', 'woocommerce-paypal-payments')}
|
<BadgeBox
|
||||||
titleType={BADGE_BOX_TITLE_BIG}
|
title={ __(
|
||||||
textBadge={__('from 3.40% + €0.35 EUR<sup>1</sup>', 'woocommerce-paypal-payments')}
|
'PayPal Checkout',
|
||||||
description={__(
|
'woocommerce-paypal-payments'
|
||||||
'Our all-in-one checkout solution lets you offer PayPal, Venmo, Pay Later options, and more to help maximise conversion',
|
) }
|
||||||
'woocommerce-paypal-payments'
|
titleType={ BADGE_BOX_TITLE_BIG }
|
||||||
)}
|
textBadge={ generatePriceText(
|
||||||
/>
|
'checkout',
|
||||||
<BadgeBox
|
countryPriceInfo[ storeCountry ],
|
||||||
title={__('Included in PayPal Checkout', 'woocommerce-paypal-payments')}
|
storeCurrency
|
||||||
titleType={BADGE_BOX_TITLE_BIG}/>
|
) }
|
||||||
<BadgeBox
|
description={ __(
|
||||||
title={__('Pay with PayPal', 'woocommerce-paypal-payments')}
|
'Our all-in-one checkout solution lets you offer PayPal, Venmo, Pay Later options, and more to help maximise conversion',
|
||||||
imageBadge={['icon-button-paypal.svg']}
|
'woocommerce-paypal-payments'
|
||||||
description={sprintf(
|
) }
|
||||||
// translators: %s: Link to PayPal REST application guide
|
/>
|
||||||
__(
|
<BadgeBox
|
||||||
'Our brand recognition helps give customers the confidence to buy. <a target="_blank" href="%s">Learn more</a>',
|
title={ __(
|
||||||
'woocommerce-paypal-payments'
|
'Included in PayPal Checkout',
|
||||||
),
|
'woocommerce-paypal-payments'
|
||||||
'https://woocommerce.com/document/woocommerce-paypal-payments/#manual-credential-input '
|
) }
|
||||||
)}
|
titleType={ BADGE_BOX_TITLE_BIG }
|
||||||
/>
|
/>
|
||||||
<Separator className="ppcp-r-page-welcome-mode-separator"/>
|
<BadgeBox
|
||||||
<BadgeBox
|
title={ __(
|
||||||
title={__('Pay Later', 'woocommerce-paypal-payments')}
|
'Pay with PayPal',
|
||||||
imageBadge={['icon-payment-method-paypal-small.svg']}
|
'woocommerce-paypal-payments'
|
||||||
description={sprintf(
|
) }
|
||||||
// translators: %s: Link to PayPal REST application guide
|
imageBadge={ [ 'icon-button-paypal.svg' ] }
|
||||||
__(
|
description={ sprintf(
|
||||||
'Offer installment payment options and get paid upfront - at no extra cost to you. <a target="_blank" href="%s">Learn more</a>',
|
// translators: %s: Link to PayPal REST application guide
|
||||||
'woocommerce-paypal-payments'
|
__(
|
||||||
),
|
'Our brand recognition helps give customers the confidence to buy. <a target="_blank" href="%s">Learn more</a>',
|
||||||
'https://woocommerce.com/document/woocommerce-paypal-payments/#manual-credential-input '
|
'woocommerce-paypal-payments'
|
||||||
)}
|
),
|
||||||
/>
|
'https://woocommerce.com/document/woocommerce-paypal-payments/#manual-credential-input '
|
||||||
</div>
|
) }
|
||||||
<div className="ppcp-r-welcome-docs__col">
|
/>
|
||||||
<BadgeBox
|
<Separator className="ppcp-r-page-welcome-mode-separator" />
|
||||||
title={__('Optional payment methods', 'woocommerce-paypal-payments')}
|
<BadgeBox
|
||||||
titleType={BADGE_BOX_TITLE_BIG}
|
title={ __(
|
||||||
description={__('with additional application', 'woocommerce-paypal-payments')}
|
'Pay in 3',
|
||||||
/>
|
'woocommerce-paypal-payments'
|
||||||
<BadgeBox
|
) }
|
||||||
title={__('Custom Card Fields', 'woocommerce-paypal-payments')}
|
imageBadge={ [
|
||||||
imageBadge={['icon-button-visa.svg', 'icon-button-mastercard.svg', 'icon-button-amex.svg', 'icon-button-discover.svg']}
|
'icon-payment-method-paypal-small.svg',
|
||||||
textBadge={__('from 3.40% + €0.35 EUR<sup>1</sup>', 'woocommerce-paypal-payments')}
|
] }
|
||||||
description={sprintf(
|
description={ sprintf(
|
||||||
// translators: %s: Link to PayPal REST application guide
|
// translators: %s: Link to PayPal REST application guide
|
||||||
__(
|
__(
|
||||||
'Style the credit card fields to match your own style. Includes advanced processing with risk management, 3D Secure, fraud protection options, and chargeback protection. <a target="_blank" href="%s">Learn more</a>',
|
'Offer installment payment options and get paid upfront - at no extra cost to you. <a target="_blank" href="%s">Learn more</a>',
|
||||||
'woocommerce-paypal-payments'
|
'woocommerce-paypal-payments'
|
||||||
),
|
),
|
||||||
'https://woocommerce.com/document/woocommerce-paypal-payments/#manual-credential-input '
|
'https://woocommerce.com/document/woocommerce-paypal-payments/#manual-credential-input '
|
||||||
)}
|
) }
|
||||||
/>
|
/>
|
||||||
<Separator className="ppcp-r-page-welcome-mode-separator"/>
|
</div>
|
||||||
<BadgeBox
|
<div className="ppcp-r-welcome-docs__col">
|
||||||
title={__('Digital Wallets', 'woocommerce-paypal-payments')}
|
<BadgeBox
|
||||||
imageBadge={['icon-button-apple-pay.svg', 'icon-button-google-pay.svg']}
|
title={ __(
|
||||||
textBadge={__('from 3.40% + €0.35 EUR<sup>1</sup>', 'woocommerce-paypal-payments')}
|
'Optional payment methods',
|
||||||
description={sprintf(
|
'woocommerce-paypal-payments'
|
||||||
// translators: %s: Link to PayPal REST application guide
|
) }
|
||||||
__(
|
titleType={ BADGE_BOX_TITLE_BIG }
|
||||||
'Accept Apple Pay on eligible devices and Google Pay through mobile and web. <a target="_blank" href="%s">Learn more</a>',
|
description={ __(
|
||||||
'woocommerce-paypal-payments'
|
'with additional application',
|
||||||
),
|
'woocommerce-paypal-payments'
|
||||||
'https://woocommerce.com/document/woocommerce-paypal-payments/#manual-credential-input '
|
) }
|
||||||
)}
|
/>
|
||||||
/>
|
<OptionalPaymentMethods
|
||||||
<Separator className="ppcp-r-page-welcome-mode-separator"/>
|
useAcdc={ true }
|
||||||
<BadgeBox
|
isFastlane={ isFastlane }
|
||||||
title={__('Alternative Payment Methods', 'woocommerce-paypal-payments')}
|
isPayLater={ isPayLater }
|
||||||
imageBadge={['icon-button-sepa.svg', 'icon-button-ideal.svg', 'icon-button-blik.svg', 'icon-button-bancontact.svg']}
|
storeCountry={ storeCountry }
|
||||||
textBadge={__('from 3.40% + €0.35 EUR<sup>1</sup>', 'woocommerce-paypal-payments')}
|
storeCurrency={ storeCurrency }
|
||||||
description={sprintf(
|
/>
|
||||||
// translators: %s: Link to PayPal REST application guide
|
</div>
|
||||||
__(
|
</div>
|
||||||
'Seamless payments for customers across the globe using their preferred payment methods. <a target="_blank" href="%s">Learn more</a>',
|
);
|
||||||
'woocommerce-paypal-payments'
|
}
|
||||||
),
|
|
||||||
'https://woocommerce.com/document/woocommerce-paypal-payments/#manual-credential-input '
|
return (
|
||||||
)}
|
<div className="ppcp-r-welcome-docs__wrapper">
|
||||||
/>
|
<div className="ppcp-r-welcome-docs__col">
|
||||||
</div>
|
<BadgeBox
|
||||||
</div>
|
title={ __(
|
||||||
);
|
'PayPal Checkout',
|
||||||
|
'woocommerce-paypal-payments'
|
||||||
|
) }
|
||||||
|
titleType={ BADGE_BOX_TITLE_BIG }
|
||||||
|
textBadge={ generatePriceText(
|
||||||
|
'checkout',
|
||||||
|
countryPriceInfo[ storeCountry ],
|
||||||
|
storeCurrency
|
||||||
|
) }
|
||||||
|
description={ __(
|
||||||
|
'Our all-in-one checkout solution lets you offer PayPal, Venmo, Pay Later options, and more to help maximise conversion',
|
||||||
|
'woocommerce-paypal-payments'
|
||||||
|
) }
|
||||||
|
/>
|
||||||
|
<BadgeBox
|
||||||
|
title={ __(
|
||||||
|
'Included in PayPal Checkout',
|
||||||
|
'woocommerce-paypal-payments'
|
||||||
|
) }
|
||||||
|
titleType={ BADGE_BOX_TITLE_BIG }
|
||||||
|
/>
|
||||||
|
<BadgeBox
|
||||||
|
title={ __(
|
||||||
|
'Pay with PayPal',
|
||||||
|
'woocommerce-paypal-payments'
|
||||||
|
) }
|
||||||
|
imageBadge={ [ 'icon-button-paypal.svg' ] }
|
||||||
|
description={ sprintf(
|
||||||
|
// translators: %s: Link to PayPal REST application guide
|
||||||
|
__(
|
||||||
|
'Our brand recognition helps give customers the confidence to buy. <a target="_blank" href="%s">Learn more</a>',
|
||||||
|
'woocommerce-paypal-payments'
|
||||||
|
),
|
||||||
|
'https://woocommerce.com/document/woocommerce-paypal-payments/#manual-credential-input '
|
||||||
|
) }
|
||||||
|
/>
|
||||||
|
<Separator className="ppcp-r-page-welcome-mode-separator" />
|
||||||
|
<BadgeBox
|
||||||
|
title={ __( 'Pay Later', 'woocommerce-paypal-payments' ) }
|
||||||
|
imageBadge={ [ 'icon-payment-method-paypal-small.svg' ] }
|
||||||
|
description={ sprintf(
|
||||||
|
// translators: %s: Link to PayPal REST application guide
|
||||||
|
__(
|
||||||
|
'Offer installment payment options and get paid upfront - at no extra cost to you. <a target="_blank" href="%s">Learn more</a>',
|
||||||
|
'woocommerce-paypal-payments'
|
||||||
|
),
|
||||||
|
'https://woocommerce.com/document/woocommerce-paypal-payments/#manual-credential-input '
|
||||||
|
) }
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="ppcp-r-welcome-docs__col">
|
||||||
|
<BadgeBox
|
||||||
|
title={ __(
|
||||||
|
'Optional payment methods',
|
||||||
|
'woocommerce-paypal-payments'
|
||||||
|
) }
|
||||||
|
titleType={ BADGE_BOX_TITLE_BIG }
|
||||||
|
description={ __(
|
||||||
|
'with additional application',
|
||||||
|
'woocommerce-paypal-payments'
|
||||||
|
) }
|
||||||
|
/>
|
||||||
|
<OptionalPaymentMethods
|
||||||
|
useAcdc={ true }
|
||||||
|
isFastlane={ isFastlane }
|
||||||
|
isPayLater={ isPayLater }
|
||||||
|
storeCountry={ storeCountry }
|
||||||
|
storeCurrency={ storeCurrency }
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default AcdcFlow;
|
export default AcdcFlow;
|
||||||
|
|
|
@ -1,160 +1,190 @@
|
||||||
import BadgeBox, { BADGE_BOX_TITLE_BIG } from "../BadgeBox";
|
import BadgeBox, { BADGE_BOX_TITLE_BIG } from '../BadgeBox';
|
||||||
import { __, sprintf } from '@wordpress/i18n';
|
import { __, sprintf } from '@wordpress/i18n';
|
||||||
import Separator from '../Separator';
|
import Separator from '../Separator';
|
||||||
|
import generatePriceText from '../../../utils/badgeBoxUtils';
|
||||||
|
import { countryPriceInfo } from '../../../utils/countryPriceInfo';
|
||||||
|
import OptionalPaymentMethods from '../OptionalPaymentMethods/OptionalPaymentMethods';
|
||||||
|
|
||||||
const BcdcFlow = ( { isPayLater, storeCountry } ) => {
|
const BcdcFlow = ( { isPayLater, storeCountry, storeCurrency } ) => {
|
||||||
if (isPayLater && storeCountry === 'us') {
|
if ( isPayLater && storeCountry === 'us' ) {
|
||||||
return (
|
return (
|
||||||
<div className="ppcp-r-welcome-docs__wrapper">
|
<div className="ppcp-r-welcome-docs__wrapper">
|
||||||
<div className="ppcp-r-welcome-docs__col">
|
<div className="ppcp-r-welcome-docs__col">
|
||||||
<BadgeBox
|
<BadgeBox
|
||||||
title={__('PayPal Checkout', 'woocommerce-paypal-payments')}
|
title={ __(
|
||||||
titleType={BADGE_BOX_TITLE_BIG}
|
'PayPal Checkout',
|
||||||
textBadge={__('from 3.49% + $0.49 USD<sup>1</sup>', 'woocommerce-paypal-payments')}
|
'woocommerce-paypal-payments'
|
||||||
description={__(
|
) }
|
||||||
'Our all-in-one checkout solution lets you offer PayPal, Venmo, Pay Later options, and more to help maximise conversion',
|
titleType={ BADGE_BOX_TITLE_BIG }
|
||||||
'woocommerce-paypal-payments'
|
textBadge={ generatePriceText(
|
||||||
)}
|
'checkout',
|
||||||
/>
|
countryPriceInfo[ storeCountry ],
|
||||||
<BadgeBox
|
storeCurrency
|
||||||
title={__('Included in PayPal Checkout', 'woocommerce-paypal-payments')}
|
) }
|
||||||
titleType={BADGE_BOX_TITLE_BIG}/>
|
description={ __(
|
||||||
<BadgeBox
|
'Our all-in-one checkout solution lets you offer PayPal, Venmo, Pay Later options, and more to help maximise conversion',
|
||||||
title={__('Pay with PayPal', 'woocommerce-paypal-payments')}
|
'woocommerce-paypal-payments'
|
||||||
imageBadge={['icon-button-paypal.svg']}
|
) }
|
||||||
description={sprintf(
|
/>
|
||||||
// translators: %s: Link to PayPal REST application guide
|
<BadgeBox
|
||||||
__(
|
title={ __(
|
||||||
'Our brand recognition helps give customers the confidence to buy. <a target="_blank" href="%s">Learn more</a>',
|
'Included in PayPal Checkout',
|
||||||
'woocommerce-paypal-payments'
|
'woocommerce-paypal-payments'
|
||||||
),
|
) }
|
||||||
'https://woocommerce.com/document/woocommerce-paypal-payments/#manual-credential-input '
|
titleType={ BADGE_BOX_TITLE_BIG }
|
||||||
)}
|
/>
|
||||||
/>
|
<BadgeBox
|
||||||
<Separator className="ppcp-r-page-welcome-mode-separator"/>
|
title={ __(
|
||||||
<BadgeBox
|
'Pay with PayPal',
|
||||||
title={__('Pay Later', 'woocommerce-paypal-payments')}
|
'woocommerce-paypal-payments'
|
||||||
imageBadge={['icon-payment-method-paypal-small.svg']}
|
) }
|
||||||
description={sprintf(
|
imageBadge={ [ 'icon-button-paypal.svg' ] }
|
||||||
// translators: %s: Link to PayPal REST application guide
|
description={ sprintf(
|
||||||
__(
|
// translators: %s: Link to PayPal REST application guide
|
||||||
'Offer installment payment options and get paid upfront - at no extra cost to you. <a target="_blank" href="%s">Learn more</a>',
|
__(
|
||||||
'woocommerce-paypal-payments'
|
'Our brand recognition helps give customers the confidence to buy. <a target="_blank" href="%s">Learn more</a>',
|
||||||
),
|
'woocommerce-paypal-payments'
|
||||||
'https://woocommerce.com/document/woocommerce-paypal-payments/#manual-credential-input '
|
),
|
||||||
)}
|
'https://woocommerce.com/document/woocommerce-paypal-payments/#manual-credential-input '
|
||||||
/>
|
) }
|
||||||
<Separator className="ppcp-r-page-welcome-mode-separator"/>
|
/>
|
||||||
<BadgeBox
|
<Separator className="ppcp-r-page-welcome-mode-separator" />
|
||||||
title={__('Venmo', 'woocommerce-paypal-payments')}
|
<BadgeBox
|
||||||
imageBadge={['icon-button-venmo.svg']}
|
title={ __(
|
||||||
description={sprintf(
|
'Pay Later',
|
||||||
// translators: %s: Link to PayPal REST application guide
|
'woocommerce-paypal-payments'
|
||||||
__(
|
) }
|
||||||
'Automatically offer Venmo checkout to millions of active users. <a target="_blank" href="%s">Learn more</a>',
|
imageBadge={ [
|
||||||
'woocommerce-paypal-payments'
|
'icon-payment-method-paypal-small.svg',
|
||||||
),
|
] }
|
||||||
'https://woocommerce.com/document/woocommerce-paypal-payments/#manual-credential-input '
|
description={ sprintf(
|
||||||
)}
|
// translators: %s: Link to PayPal REST application guide
|
||||||
/>
|
__(
|
||||||
<Separator className="ppcp-r-page-welcome-mode-separator"/>
|
'Offer installment payment options and get paid upfront - at no extra cost to you. <a target="_blank" href="%s">Learn more</a>',
|
||||||
<BadgeBox
|
'woocommerce-paypal-payments'
|
||||||
title={__('Crypto', 'woocommerce-paypal-payments')}
|
),
|
||||||
imageBadge={['icon-payment-method-crypto.svg']}
|
'https://woocommerce.com/document/woocommerce-paypal-payments/#manual-credential-input '
|
||||||
description={sprintf(
|
) }
|
||||||
// translators: %s: Link to PayPal REST application guide
|
/>
|
||||||
__(
|
<Separator className="ppcp-r-page-welcome-mode-separator" />
|
||||||
'Let customers checkout with Crypto while you get paid in cash. <a target="_blank" href="%s">Learn more</a>',
|
<BadgeBox
|
||||||
'woocommerce-paypal-payments'
|
title={ __( 'Venmo', 'woocommerce-paypal-payments' ) }
|
||||||
),
|
imageBadge={ [ 'icon-button-venmo.svg' ] }
|
||||||
'https://woocommerce.com/document/woocommerce-paypal-payments/#manual-credential-input '
|
description={ sprintf(
|
||||||
)}
|
// translators: %s: Link to PayPal REST application guide
|
||||||
/>
|
__(
|
||||||
</div>
|
'Automatically offer Venmo checkout to millions of active users. <a target="_blank" href="%s">Learn more</a>',
|
||||||
<div className="ppcp-r-welcome-docs__col">
|
'woocommerce-paypal-payments'
|
||||||
<BadgeBox
|
),
|
||||||
title={__('Optional payment methods', 'woocommerce-paypal-payments')}
|
'https://woocommerce.com/document/woocommerce-paypal-payments/#manual-credential-input '
|
||||||
titleType={BADGE_BOX_TITLE_BIG}
|
) }
|
||||||
description={__('with additional application', 'woocommerce-paypal-payments')}
|
/>
|
||||||
/>
|
<Separator className="ppcp-r-page-welcome-mode-separator" />
|
||||||
<BadgeBox
|
<BadgeBox
|
||||||
title={__('Credit and Debit Cards', 'woocommerce-paypal-payments')}
|
title={ __( 'Crypto', 'woocommerce-paypal-payments' ) }
|
||||||
imageBadge={['icon-button-visa.svg', 'icon-button-mastercard.svg', 'icon-button-amex.svg', 'icon-button-discover.svg']}
|
imageBadge={ [ 'icon-payment-method-crypto.svg' ] }
|
||||||
textBadge={__('from 2.59% + $0.49 USD<sup>1</sup>', 'woocommerce-paypal-payments')}
|
description={ sprintf(
|
||||||
description={sprintf(
|
// translators: %s: Link to PayPal REST application guide
|
||||||
// translators: %s: Link to PayPal REST application guide
|
__(
|
||||||
__(
|
'Let customers checkout with Crypto while you get paid in cash. <a target="_blank" href="%s">Learn more</a>',
|
||||||
'Process major credit and debit cards through PayPal’s card fields. <a target="_blank" href="%s">Learn more</a>',
|
'woocommerce-paypal-payments'
|
||||||
'woocommerce-paypal-payments'
|
),
|
||||||
),
|
'https://woocommerce.com/document/woocommerce-paypal-payments/#manual-credential-input '
|
||||||
'https://woocommerce.com/document/woocommerce-paypal-payments/#manual-credential-input '
|
) }
|
||||||
)}
|
/>
|
||||||
/>
|
</div>
|
||||||
</div>
|
<div className="ppcp-r-welcome-docs__col">
|
||||||
</div>
|
<BadgeBox
|
||||||
);
|
title={ __(
|
||||||
}
|
'Optional payment methods',
|
||||||
|
'woocommerce-paypal-payments'
|
||||||
|
) }
|
||||||
|
titleType={ BADGE_BOX_TITLE_BIG }
|
||||||
|
description={ __(
|
||||||
|
'with additional application',
|
||||||
|
'woocommerce-paypal-payments'
|
||||||
|
) }
|
||||||
|
/>
|
||||||
|
<OptionalPaymentMethods
|
||||||
|
useAcdc={ false }
|
||||||
|
isFastlane={ false }
|
||||||
|
isPayLater={ isPayLater }
|
||||||
|
storeCountry={ storeCountry }
|
||||||
|
storeCurrency={ storeCurrency }
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="ppcp-r-welcome-docs__wrapper ppcp-r-welcome-docs__wrapper--one-col">
|
<div className="ppcp-r-welcome-docs__wrapper ppcp-r-welcome-docs__wrapper--one-col">
|
||||||
<BadgeBox
|
<BadgeBox
|
||||||
title={__('PayPal Checkout', 'woocommerce-paypal-payments')}
|
title={ __( 'PayPal Checkout', 'woocommerce-paypal-payments' ) }
|
||||||
titleType={BADGE_BOX_TITLE_BIG}
|
titleType={ BADGE_BOX_TITLE_BIG }
|
||||||
textBadge={__('from 3.40% + €0.35 EUR<sup>1</sup>', 'woocommerce-paypal-payments')}
|
textBadge={ generatePriceText(
|
||||||
description={__(
|
'checkout',
|
||||||
'Our all-in-one checkout solution lets you offer PayPal, Venmo, Pay Later options, and more to help maximise conversion',
|
countryPriceInfo[ storeCountry ],
|
||||||
'woocommerce-paypal-payments'
|
storeCurrency
|
||||||
)}
|
) }
|
||||||
/>
|
description={ __(
|
||||||
<BadgeBox
|
'Our all-in-one checkout solution lets you offer PayPal, Venmo, Pay Later options, and more to help maximise conversion',
|
||||||
title={__('Included in PayPal Checkout', 'woocommerce-paypal-payments')}
|
'woocommerce-paypal-payments'
|
||||||
titleType={BADGE_BOX_TITLE_BIG}/>
|
) }
|
||||||
<BadgeBox
|
/>
|
||||||
title={__('Pay with PayPal', 'woocommerce-paypal-payments')}
|
<BadgeBox
|
||||||
imageBadge={['icon-button-paypal.svg']}
|
title={ __(
|
||||||
description={sprintf(
|
'Included in PayPal Checkout',
|
||||||
// translators: %s: Link to PayPal REST application guide
|
'woocommerce-paypal-payments'
|
||||||
__(
|
) }
|
||||||
'Our brand recognition helps give customers the confidence to buy. <a target="_blank" href="%s">Learn more</a>',
|
titleType={ BADGE_BOX_TITLE_BIG }
|
||||||
'woocommerce-paypal-payments'
|
/>
|
||||||
),
|
<BadgeBox
|
||||||
'https://woocommerce.com/document/woocommerce-paypal-payments/#manual-credential-input '
|
title={ __( 'Pay with PayPal', 'woocommerce-paypal-payments' ) }
|
||||||
)}
|
imageBadge={ [ 'icon-button-paypal.svg' ] }
|
||||||
/>
|
description={ sprintf(
|
||||||
<Separator className="ppcp-r-page-welcome-mode-separator"/>
|
// translators: %s: Link to PayPal REST application guide
|
||||||
<BadgeBox
|
__(
|
||||||
title={__('Pay Later', 'woocommerce-paypal-payments')}
|
'Our brand recognition helps give customers the confidence to buy. <a target="_blank" href="%s">Learn more</a>',
|
||||||
imageBadge={['icon-payment-method-paypal-small.svg']}
|
'woocommerce-paypal-payments'
|
||||||
description={sprintf(
|
),
|
||||||
// translators: %s: Link to PayPal REST application guide
|
'https://woocommerce.com/document/woocommerce-paypal-payments/#manual-credential-input '
|
||||||
__(
|
) }
|
||||||
'Offer installment payment options and get paid upfront - at no extra cost to you. <a target="_blank" href="%s">Learn more</a>',
|
/>
|
||||||
'woocommerce-paypal-payments'
|
<Separator className="ppcp-r-page-welcome-mode-separator" />
|
||||||
),
|
<BadgeBox
|
||||||
'https://woocommerce.com/document/woocommerce-paypal-payments/#manual-credential-input '
|
title={ __( 'Pay Later', 'woocommerce-paypal-payments' ) }
|
||||||
)}
|
imageBadge={ [ 'icon-payment-method-paypal-small.svg' ] }
|
||||||
/>
|
description={ sprintf(
|
||||||
<Separator className="ppcp-r-page-welcome-mode-separator"/>
|
// translators: %s: Link to PayPal REST application guide
|
||||||
<BadgeBox
|
__(
|
||||||
title={__('Optional payment methods', 'woocommerce-paypal-payments')}
|
'Offer installment payment options and get paid upfront - at no extra cost to you. <a target="_blank" href="%s">Learn more</a>',
|
||||||
titleType={BADGE_BOX_TITLE_BIG}
|
'woocommerce-paypal-payments'
|
||||||
description={__('with additional application', 'woocommerce-paypal-payments')}
|
),
|
||||||
/>
|
'https://woocommerce.com/document/woocommerce-paypal-payments/#manual-credential-input '
|
||||||
<BadgeBox
|
) }
|
||||||
title={__('Credit and Debit Cards', 'woocommerce-paypal-payments')}
|
/>
|
||||||
imageBadge={['icon-button-visa.svg', 'icon-button-mastercard.svg', 'icon-button-amex.svg', 'icon-button-discover.svg']}
|
<Separator className="ppcp-r-page-welcome-mode-separator" />
|
||||||
textBadge={__('from 3.40% + €0.35 EUR<sup>1</sup>', 'woocommerce-paypal-payments')}
|
<BadgeBox
|
||||||
description={sprintf(
|
title={ __(
|
||||||
// translators: %s: Link to PayPal REST application guide
|
'Optional payment methods',
|
||||||
__(
|
'woocommerce-paypal-payments'
|
||||||
'Process major credit and debit cards through PayPal’s card fields. <a target="_blank" href="%s">Learn more</a>',
|
) }
|
||||||
'woocommerce-paypal-payments'
|
titleType={ BADGE_BOX_TITLE_BIG }
|
||||||
),
|
description={ __(
|
||||||
'https://woocommerce.com/document/woocommerce-paypal-payments/#manual-credential-input '
|
'with additional application',
|
||||||
)}
|
'woocommerce-paypal-payments'
|
||||||
/>
|
) }
|
||||||
</div>
|
/>
|
||||||
);
|
<OptionalPaymentMethods
|
||||||
|
useAcdc={ false }
|
||||||
|
isFastlane={ false }
|
||||||
|
isPayLater={ isPayLater }
|
||||||
|
storeCountry={ storeCountry }
|
||||||
|
storeCurrency={ storeCurrency }
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default BcdcFlow;
|
export default BcdcFlow;
|
||||||
|
|
|
@ -1,32 +1,52 @@
|
||||||
import { __, sprintf } from '@wordpress/i18n';
|
import { __, sprintf } from '@wordpress/i18n';
|
||||||
import AcdcFlow from "./AcdcFlow";
|
import AcdcFlow from './AcdcFlow';
|
||||||
import BcdcFlow from "./BcdcFlow";
|
import BcdcFlow from './BcdcFlow';
|
||||||
import {Button} from "@wordpress/components";
|
import { Button } from '@wordpress/components';
|
||||||
|
|
||||||
const WelcomeDocs = ( { useAcdc, isFastlane, isPayLater, storeCountry, storeCurrency } ) => {
|
const WelcomeDocs = ( {
|
||||||
const pricesBasedDescription = sprintf(
|
useAcdc,
|
||||||
// translators: %s: Link to PayPal REST application guide
|
isFastlane,
|
||||||
__(
|
isPayLater,
|
||||||
'<sup>1</sup>Prices based on domestic transactions as of October 25th, 2024. <a target="_blank" href="%s">Click here</a> for full pricing details.',
|
storeCountry,
|
||||||
'woocommerce-paypal-payments'
|
storeCurrency,
|
||||||
),
|
} ) => {
|
||||||
'https://woocommerce.com/document/woocommerce-paypal-payments/#manual-credential-input '
|
const pricesBasedDescription = sprintf(
|
||||||
);
|
// translators: %s: Link to PayPal REST application guide
|
||||||
|
__(
|
||||||
|
'<sup>1</sup>Prices based on domestic transactions as of October 25th, 2024. <a target="_blank" href="%s">Click here</a> for full pricing details.',
|
||||||
|
'woocommerce-paypal-payments'
|
||||||
|
),
|
||||||
|
'https://woocommerce.com/document/woocommerce-paypal-payments/#manual-credential-input '
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="ppcp-r-welcome-docs">
|
<div className="ppcp-r-welcome-docs">
|
||||||
<h2 className="ppcp-r-welcome-docs__title">{__(`Want to know more about PayPal Payments?`, 'woocommerce-paypal-payments')}</h2>
|
<h2 className="ppcp-r-welcome-docs__title">
|
||||||
{useAcdc ? (
|
{ __(
|
||||||
<AcdcFlow isFastlane={ isFastlane } isPayLater={ isPayLater } storeCountry={ storeCountry } />
|
`Want to know more about PayPal Payments?`,
|
||||||
) : (
|
'woocommerce-paypal-payments'
|
||||||
<BcdcFlow isPayLater={ isPayLater } storeCountry={ storeCountry } />
|
) }
|
||||||
)}
|
</h2>
|
||||||
<p
|
{ useAcdc ? (
|
||||||
className="ppcp-r-welcome-docs__description"
|
<AcdcFlow
|
||||||
dangerouslySetInnerHTML={{__html: pricesBasedDescription,}}
|
isFastlane={ isFastlane }
|
||||||
></p>
|
isPayLater={ isPayLater }
|
||||||
</div>
|
storeCountry={ storeCountry }
|
||||||
);
|
storeCurrency={ storeCurrency }
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<BcdcFlow
|
||||||
|
isPayLater={ isPayLater }
|
||||||
|
storeCountry={ storeCountry }
|
||||||
|
storeCurrency={ storeCurrency }
|
||||||
|
/>
|
||||||
|
) }
|
||||||
|
<p
|
||||||
|
className="ppcp-r-optional-payment-methods__description"
|
||||||
|
dangerouslySetInnerHTML={ { __html: pricesBasedDescription } }
|
||||||
|
></p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default WelcomeDocs;
|
export default WelcomeDocs;
|
||||||
|
|
|
@ -1,98 +1,94 @@
|
||||||
import { __, sprintf } from '@wordpress/i18n';
|
import { __, sprintf } from '@wordpress/i18n';
|
||||||
import { Button, TextControl } from '@wordpress/components';
|
import { Button, TextControl } from '@wordpress/components';
|
||||||
import { useRef } from '@wordpress/element';
|
import { useRef, useMemo } from '@wordpress/element';
|
||||||
import { useDispatch } from '@wordpress/data';
|
import { useDispatch } from '@wordpress/data';
|
||||||
import { store as noticesStore } from '@wordpress/notices';
|
import { store as noticesStore } from '@wordpress/notices';
|
||||||
|
|
||||||
import SettingsToggleBlock from '../../../ReusableComponents/SettingsToggleBlock';
|
import SettingsToggleBlock from '../../../ReusableComponents/SettingsToggleBlock';
|
||||||
import Separator from '../../../ReusableComponents/Separator';
|
import Separator from '../../../ReusableComponents/Separator';
|
||||||
import DataStoreControl from '../../../ReusableComponents/DataStoreControl';
|
import DataStoreControl from '../../../ReusableComponents/DataStoreControl';
|
||||||
import { useManualConnect, useOnboardingStepWelcome } from '../../../../data';
|
import { CommonHooks } from '../../../../data';
|
||||||
|
import { openPopup } from '../../../../utils/window';
|
||||||
|
|
||||||
const AdvancedOptionsForm = ( { setCompleted } ) => {
|
const AdvancedOptionsForm = ( { setCompleted } ) => {
|
||||||
|
const { isBusy } = CommonHooks.useBusyState();
|
||||||
|
const { isSandboxMode, setSandboxMode, connectViaSandbox } =
|
||||||
|
CommonHooks.useSandbox();
|
||||||
const {
|
const {
|
||||||
isManualConnectionBusy,
|
|
||||||
isSandboxMode,
|
|
||||||
setSandboxMode,
|
|
||||||
isManualConnectionMode,
|
isManualConnectionMode,
|
||||||
setManualConnectionMode,
|
setManualConnectionMode,
|
||||||
clientId,
|
clientId,
|
||||||
setClientId,
|
setClientId,
|
||||||
clientSecret,
|
clientSecret,
|
||||||
setClientSecret,
|
setClientSecret,
|
||||||
} = useOnboardingStepWelcome();
|
connectViaIdAndSecret,
|
||||||
|
} = CommonHooks.useManualConnection();
|
||||||
|
|
||||||
const { createSuccessNotice, createErrorNotice } =
|
const { createSuccessNotice, createErrorNotice } =
|
||||||
useDispatch( noticesStore );
|
useDispatch( noticesStore );
|
||||||
const { connectManual } = useManualConnect();
|
|
||||||
const refClientId = useRef( null );
|
const refClientId = useRef( null );
|
||||||
const refClientSecret = useRef( null );
|
const refClientSecret = useRef( null );
|
||||||
|
|
||||||
const handleFormValidation = () => {
|
const isValidClientId = useMemo( () => {
|
||||||
const fields = [
|
return /^A[\w-]{79}$/.test( clientId );
|
||||||
{
|
}, [ clientId ] );
|
||||||
ref: refClientId,
|
|
||||||
value: clientId,
|
|
||||||
errorMessage: __(
|
|
||||||
'Please enter your Client ID',
|
|
||||||
'woocommerce-paypal-payments'
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
ref: refClientSecret,
|
|
||||||
value: clientSecret,
|
|
||||||
errorMessage: __(
|
|
||||||
'Please enter your Secret Key',
|
|
||||||
'woocommerce-paypal-payments'
|
|
||||||
),
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
for ( const { ref, value, errorMessage } of fields ) {
|
const isFormValid = useMemo( () => {
|
||||||
if ( value ) {
|
return isValidClientId && clientId && clientSecret;
|
||||||
continue;
|
}, [ isValidClientId, clientId, clientSecret ] );
|
||||||
}
|
|
||||||
|
|
||||||
ref?.current?.focus();
|
const handleServerError = ( res, genericMessage ) => {
|
||||||
createErrorNotice( errorMessage );
|
console.error( 'Connection error', res );
|
||||||
return false;
|
createErrorNotice( res?.message ?? genericMessage );
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleServerError = ( res ) => {
|
|
||||||
if ( res.message ) {
|
|
||||||
createErrorNotice( res.message );
|
|
||||||
} else {
|
|
||||||
createErrorNotice(
|
|
||||||
__(
|
|
||||||
'Could not connect to PayPal. Please make sure your Client ID and Secret Key are correct.',
|
|
||||||
'woocommerce-paypal-payments'
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleServerSuccess = () => {
|
const handleServerSuccess = () => {
|
||||||
createSuccessNotice(
|
createSuccessNotice(
|
||||||
__( 'Connected to PayPal', 'woocommerce-paypal-payments' )
|
__( 'Connected to PayPal', 'woocommerce-paypal-payments' )
|
||||||
);
|
);
|
||||||
|
|
||||||
setCompleted( true );
|
setCompleted( true );
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleConnect = async () => {
|
const handleSandboxConnect = async () => {
|
||||||
if ( ! handleFormValidation() ) {
|
const res = await connectViaSandbox();
|
||||||
|
|
||||||
|
if ( ! res.success || ! res.data ) {
|
||||||
|
handleServerError(
|
||||||
|
res,
|
||||||
|
__(
|
||||||
|
'Could not generate a Sandbox login link.',
|
||||||
|
'woocommerce-paypal-payments'
|
||||||
|
)
|
||||||
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const res = await connectManual();
|
const connectionUrl = res.data;
|
||||||
|
const popup = openPopup( connectionUrl );
|
||||||
|
|
||||||
|
if ( ! popup ) {
|
||||||
|
createErrorNotice(
|
||||||
|
__(
|
||||||
|
'Popup blocked. Please allow popups for this site to connect to PayPal.',
|
||||||
|
'woocommerce-paypal-payments'
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleManualConnect = async () => {
|
||||||
|
const res = await connectViaIdAndSecret();
|
||||||
|
|
||||||
if ( res.success ) {
|
if ( res.success ) {
|
||||||
handleServerSuccess();
|
handleServerSuccess();
|
||||||
} else {
|
} else {
|
||||||
handleServerError( res );
|
handleServerError(
|
||||||
|
res,
|
||||||
|
__(
|
||||||
|
'Could not connect to PayPal. Please make sure your Client ID and Secret Key are correct.',
|
||||||
|
'woocommerce-paypal-payments'
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -118,21 +114,22 @@ const AdvancedOptionsForm = ( { setCompleted } ) => {
|
||||||
) }
|
) }
|
||||||
isToggled={ !! isSandboxMode }
|
isToggled={ !! isSandboxMode }
|
||||||
setToggled={ setSandboxMode }
|
setToggled={ setSandboxMode }
|
||||||
|
isLoading={ isBusy }
|
||||||
>
|
>
|
||||||
<Button variant="secondary">
|
<Button onClick={ handleSandboxConnect } variant="secondary">
|
||||||
{ __( 'Connect Account', 'woocommerce-paypal-payments' ) }
|
{ __( 'Connect Account', 'woocommerce-paypal-payments' ) }
|
||||||
</Button>
|
</Button>
|
||||||
</SettingsToggleBlock>
|
</SettingsToggleBlock>
|
||||||
<Separator className="ppcp-r-page-welcome-mode-separator" />
|
<Separator withLine={ false } />
|
||||||
<SettingsToggleBlock
|
<SettingsToggleBlock
|
||||||
label={ __(
|
label={
|
||||||
'Manually Connect',
|
__( 'Manually Connect', 'woocommerce-paypal-payments' ) +
|
||||||
'woocommerce-paypal-payments'
|
( isBusy ? ' ...' : '' )
|
||||||
) }
|
}
|
||||||
description={ advancedUsersDescription }
|
description={ advancedUsersDescription }
|
||||||
isToggled={ !! isManualConnectionMode }
|
isToggled={ !! isManualConnectionMode }
|
||||||
setToggled={ setManualConnectionMode }
|
setToggled={ setManualConnectionMode }
|
||||||
isLoading={ isManualConnectionBusy }
|
isLoading={ isBusy }
|
||||||
>
|
>
|
||||||
<DataStoreControl
|
<DataStoreControl
|
||||||
control={ TextControl }
|
control={ TextControl }
|
||||||
|
@ -150,7 +147,18 @@ const AdvancedOptionsForm = ( { setCompleted } ) => {
|
||||||
}
|
}
|
||||||
value={ clientId }
|
value={ clientId }
|
||||||
onChange={ setClientId }
|
onChange={ setClientId }
|
||||||
|
className={
|
||||||
|
clientId && ! isValidClientId ? 'has-error' : ''
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
|
{ clientId && ! isValidClientId && (
|
||||||
|
<p className="client-id-error">
|
||||||
|
{ __(
|
||||||
|
'Please enter a valid Client ID',
|
||||||
|
'woocommerce-paypal-payments'
|
||||||
|
) }
|
||||||
|
</p>
|
||||||
|
) }
|
||||||
<DataStoreControl
|
<DataStoreControl
|
||||||
control={ TextControl }
|
control={ TextControl }
|
||||||
ref={ refClientSecret }
|
ref={ refClientSecret }
|
||||||
|
@ -169,7 +177,11 @@ const AdvancedOptionsForm = ( { setCompleted } ) => {
|
||||||
onChange={ setClientSecret }
|
onChange={ setClientSecret }
|
||||||
type="password"
|
type="password"
|
||||||
/>
|
/>
|
||||||
<Button variant="secondary" onClick={ handleConnect }>
|
<Button
|
||||||
|
variant="secondary"
|
||||||
|
onClick={ handleManualConnect }
|
||||||
|
disabled={ ! isFormValid }
|
||||||
|
>
|
||||||
{ __( 'Connect Account', 'woocommerce-paypal-payments' ) }
|
{ __( 'Connect Account', 'woocommerce-paypal-payments' ) }
|
||||||
</Button>
|
</Button>
|
||||||
</SettingsToggleBlock>
|
</SettingsToggleBlock>
|
||||||
|
|
|
@ -1,10 +1,8 @@
|
||||||
import { Button } from '@wordpress/components';
|
import { Button } from '@wordpress/components';
|
||||||
import { __ } from '@wordpress/i18n';
|
import { __ } from '@wordpress/i18n';
|
||||||
import {
|
|
||||||
useOnboardingStepBusiness,
|
import { OnboardingHooks } from '../../../../data';
|
||||||
useOnboardingStepProducts,
|
import data from '../../../../utils/data';
|
||||||
} from '../../data';
|
|
||||||
import data from '../../utils/data';
|
|
||||||
|
|
||||||
const Navigation = ( { setStep, setCompleted, currentStep, stepperOrder } ) => {
|
const Navigation = ( { setStep, setCompleted, currentStep, stepperOrder } ) => {
|
||||||
const isLastStep = () => currentStep + 1 === stepperOrder.length;
|
const isLastStep = () => currentStep + 1 === stepperOrder.length;
|
||||||
|
@ -24,8 +22,8 @@ const Navigation = ( { setStep, setCompleted, currentStep, stepperOrder } ) => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const { products, toggleProduct } = useOnboardingStepProducts();
|
const { products } = OnboardingHooks.useProducts();
|
||||||
const { isCasualSeller, setIsCasualSeller } = useOnboardingStepBusiness();
|
const { isCasualSeller } = OnboardingHooks.useBusiness();
|
||||||
|
|
||||||
let navigationTitle = '';
|
let navigationTitle = '';
|
||||||
let disabled = false;
|
let disabled = false;
|
|
@ -1,7 +1,7 @@
|
||||||
import Container from '../../ReusableComponents/Container';
|
import Container from '../../ReusableComponents/Container';
|
||||||
import { useOnboardingStep } from '../../../data';
|
import { OnboardingHooks } from '../../../data';
|
||||||
import { getSteps } from './availableSteps';
|
import { getSteps } from './availableSteps';
|
||||||
import Navigation from '../../ReusableComponents/Navigation';
|
import Navigation from './Components/Navigation';
|
||||||
|
|
||||||
const getCurrentStep = ( requestedStep, steps ) => {
|
const getCurrentStep = ( requestedStep, steps ) => {
|
||||||
const isValidStep = ( step ) =>
|
const isValidStep = ( step ) =>
|
||||||
|
@ -15,7 +15,7 @@ const getCurrentStep = ( requestedStep, steps ) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const Onboarding = () => {
|
const Onboarding = () => {
|
||||||
const { step, setStep, setCompleted, flags } = useOnboardingStep();
|
const { step, setStep, setCompleted, flags } = OnboardingHooks.useSteps();
|
||||||
const steps = getSteps( flags );
|
const steps = getSteps( flags );
|
||||||
|
|
||||||
const CurrentStepComponent = getCurrentStep( step, steps );
|
const CurrentStepComponent = getCurrentStep( step, steps );
|
||||||
|
|
|
@ -1,20 +1,14 @@
|
||||||
|
import { __ } from '@wordpress/i18n';
|
||||||
|
|
||||||
import OnboardingHeader from '../../ReusableComponents/OnboardingHeader';
|
import OnboardingHeader from '../../ReusableComponents/OnboardingHeader';
|
||||||
import SelectBoxWrapper from '../../ReusableComponents/SelectBoxWrapper';
|
import SelectBoxWrapper from '../../ReusableComponents/SelectBoxWrapper';
|
||||||
import SelectBox from '../../ReusableComponents/SelectBox';
|
import SelectBox from '../../ReusableComponents/SelectBox';
|
||||||
import { __ } from '@wordpress/i18n';
|
import { OnboardingHooks, BUSINESS_TYPES } from '../../../data';
|
||||||
import PaymentMethodIcons from '../../ReusableComponents/PaymentMethodIcons';
|
|
||||||
import { useOnboardingStepBusiness } from '../../../data';
|
|
||||||
import { BUSINESS_TYPES } from '../../../data/constants';
|
|
||||||
|
|
||||||
const BUSINESS_RADIO_GROUP_NAME = 'business';
|
const BUSINESS_RADIO_GROUP_NAME = 'business';
|
||||||
|
|
||||||
const StepBusiness = ( {
|
const StepBusiness = ( {} ) => {
|
||||||
setStep,
|
const { isCasualSeller, setIsCasualSeller } = OnboardingHooks.useBusiness();
|
||||||
currentStep,
|
|
||||||
stepperOrder,
|
|
||||||
setCompleted,
|
|
||||||
} ) => {
|
|
||||||
const { isCasualSeller, setIsCasualSeller } = useOnboardingStepBusiness();
|
|
||||||
|
|
||||||
const handleSellerTypeChange = ( value ) => {
|
const handleSellerTypeChange = ( value ) => {
|
||||||
setIsCasualSeller( BUSINESS_TYPES.CASUAL_SELLER === value );
|
setIsCasualSeller( BUSINESS_TYPES.CASUAL_SELLER === value );
|
||||||
|
@ -40,23 +34,22 @@ const StepBusiness = ( {
|
||||||
/>
|
/>
|
||||||
<div className="ppcp-r-inner-container">
|
<div className="ppcp-r-inner-container">
|
||||||
<SelectBoxWrapper>
|
<SelectBoxWrapper>
|
||||||
<SelectBox
|
<SelectBox
|
||||||
title={ __(
|
title={ __(
|
||||||
'Business',
|
'Business',
|
||||||
'woocommerce-paypal-payments'
|
'woocommerce-paypal-payments'
|
||||||
) }
|
) }
|
||||||
description={ __(
|
description={ __(
|
||||||
'Recommended for individuals and organizations that primarily use PayPal to sell goods or services or receive donations, even if your business is not incorporated.',
|
'Recommended for individuals and organizations that primarily use PayPal to sell goods or services or receive donations, even if your business is not incorporated.',
|
||||||
'woocommerce-paypal-payments'
|
'woocommerce-paypal-payments'
|
||||||
) }
|
) }
|
||||||
name={ BUSINESS_RADIO_GROUP_NAME }
|
name={ BUSINESS_RADIO_GROUP_NAME }
|
||||||
value={ BUSINESS_TYPES.BUSINESS }
|
value={ BUSINESS_TYPES.BUSINESS }
|
||||||
changeCallback={ handleSellerTypeChange }
|
changeCallback={ handleSellerTypeChange }
|
||||||
currentValue={ getCurrentValue() }
|
currentValue={ getCurrentValue() }
|
||||||
checked={ isCasualSeller === false }
|
checked={ isCasualSeller === false }
|
||||||
type="radio"
|
type="radio"
|
||||||
>
|
></SelectBox>
|
||||||
</SelectBox>
|
|
||||||
<SelectBox
|
<SelectBox
|
||||||
title={ __(
|
title={ __(
|
||||||
'Personal Account',
|
'Personal Account',
|
||||||
|
@ -72,8 +65,7 @@ const StepBusiness = ( {
|
||||||
currentValue={ getCurrentValue() }
|
currentValue={ getCurrentValue() }
|
||||||
checked={ isCasualSeller === true }
|
checked={ isCasualSeller === true }
|
||||||
type="radio"
|
type="radio"
|
||||||
>
|
></SelectBox>
|
||||||
</SelectBox>
|
|
||||||
</SelectBoxWrapper>
|
</SelectBoxWrapper>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,31 +1,23 @@
|
||||||
import OnboardingHeader from '../../ReusableComponents/OnboardingHeader';
|
|
||||||
import { __ } from '@wordpress/i18n';
|
import { __ } from '@wordpress/i18n';
|
||||||
import { Button, Icon } from '@wordpress/components';
|
import { Button, Icon } from '@wordpress/components';
|
||||||
|
|
||||||
const StepCompleteSetup = ( {
|
import OnboardingHeader from '../../ReusableComponents/OnboardingHeader';
|
||||||
setStep,
|
|
||||||
currentStep,
|
const StepCompleteSetup = ( { setCompleted } ) => {
|
||||||
stepperOrder,
|
|
||||||
setCompleted,
|
|
||||||
} ) => {
|
|
||||||
const ButtonIcon = () => (
|
const ButtonIcon = () => (
|
||||||
<Icon
|
<Icon
|
||||||
icon={ () => (
|
icon={ () => (
|
||||||
<svg
|
<svg
|
||||||
width="24"
|
width="25"
|
||||||
height="24"
|
height="24"
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 25 24"
|
||||||
fill="none"
|
fill="none"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
>
|
>
|
||||||
<path
|
<path
|
||||||
d="M19.5001 4.5H12.5001V6H16.9394L10.9697 11.9697L12.0304 13.0303L18.0001 7.06066V11.5H19.5001V4.5Z"
|
d="M12.4999 12.75V18.75C12.4999 18.9489 12.4209 19.1397 12.2803 19.2803C12.1396 19.421 11.9488 19.5 11.7499 19.5C11.551 19.5 11.3603 19.421 11.2196 19.2803C11.0789 19.1397 10.9999 18.9489 10.9999 18.75V14.5613L4.78055 20.7806C4.71087 20.8503 4.62815 20.9056 4.5371 20.9433C4.44606 20.981 4.34847 21.0004 4.24993 21.0004C4.15138 21.0004 4.0538 20.981 3.96276 20.9433C3.87171 20.9056 3.78899 20.8503 3.7193 20.7806C3.64962 20.7109 3.59435 20.6282 3.55663 20.5372C3.51892 20.4461 3.49951 20.3485 3.49951 20.25C3.49951 20.1515 3.51892 20.0539 3.55663 19.9628C3.59435 19.8718 3.64962 19.7891 3.7193 19.7194L9.93868 13.5H5.74993C5.55102 13.5 5.36025 13.421 5.2196 13.2803C5.07895 13.1397 4.99993 12.9489 4.99993 12.75C4.99993 12.5511 5.07895 12.3603 5.2196 12.2197C5.36025 12.079 5.55102 12 5.74993 12H11.7499C11.9488 12 12.1396 12.079 12.2803 12.2197C12.4209 12.3603 12.4999 12.5511 12.4999 12.75ZM19.9999 3H7.99993C7.6021 3 7.22057 3.15804 6.93927 3.43934C6.65796 3.72064 6.49993 4.10218 6.49993 4.5V9C6.49993 9.19891 6.57895 9.38968 6.7196 9.53033C6.86025 9.67098 7.05102 9.75 7.24993 9.75C7.44884 9.75 7.63961 9.67098 7.78026 9.53033C7.92091 9.38968 7.99993 9.19891 7.99993 9V4.5H19.9999V16.5H15.4999C15.301 16.5 15.1103 16.579 14.9696 16.7197C14.8289 16.8603 14.7499 17.0511 14.7499 17.25C14.7499 17.4489 14.8289 17.6397 14.9696 17.7803C15.1103 17.921 15.301 18 15.4999 18H19.9999C20.3978 18 20.7793 17.842 21.0606 17.5607C21.3419 17.2794 21.4999 16.8978 21.4999 16.5V4.5C21.4999 4.10218 21.3419 3.72064 21.0606 3.43934C20.7793 3.15804 20.3978 3 19.9999 3Z"
|
||||||
fill="white"
|
fill="white"
|
||||||
/>
|
/>
|
||||||
<path
|
|
||||||
d="M6.5 5.5C5.39543 5.5 4.5 6.39543 4.5 7.5V17.5C4.5 18.6046 5.39543 19.5 6.5 19.5H16.5C17.6046 19.5 18.5 18.6046 18.5 17.5V14.5H17V17.5C17 17.7761 16.7761 18 16.5 18H6.5C6.22386 18 6 17.7761 6 17.5V7.5C6 7.22386 6.22386 7 6.5 7H9.5V5.5H6.5Z"
|
|
||||||
fill="white"
|
|
||||||
/>
|
|
||||||
</svg>
|
</svg>
|
||||||
) }
|
) }
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -0,0 +1,78 @@
|
||||||
|
import { __, sprintf } from '@wordpress/i18n';
|
||||||
|
|
||||||
|
import OnboardingHeader from '../../ReusableComponents/OnboardingHeader';
|
||||||
|
import SelectBoxWrapper from '../../ReusableComponents/SelectBoxWrapper';
|
||||||
|
import SelectBox from '../../ReusableComponents/SelectBox';
|
||||||
|
import { OnboardingHooks } from '../../../data';
|
||||||
|
import OptionalPaymentMethods from '../../ReusableComponents/OptionalPaymentMethods/OptionalPaymentMethods';
|
||||||
|
|
||||||
|
const OPM_RADIO_GROUP_NAME = 'optional-payment-methods';
|
||||||
|
|
||||||
|
const StepPaymentMethods = ( {} ) => {
|
||||||
|
const {
|
||||||
|
areOptionalPaymentMethodsEnabled,
|
||||||
|
setAreOptionalPaymentMethodsEnabled,
|
||||||
|
} = OnboardingHooks.useOptionalPaymentMethods();
|
||||||
|
const pricesBasedDescription = sprintf(
|
||||||
|
// translators: %s: Link to PayPal REST application guide
|
||||||
|
__(
|
||||||
|
'<sup>1</sup>Prices based on domestic transactions as of October 25th, 2024. <a target="_blank" href="%s">Click here</a> for full pricing details.',
|
||||||
|
'woocommerce-paypal-payments'
|
||||||
|
),
|
||||||
|
'https://woocommerce.com/document/woocommerce-paypal-payments/#manual-credential-input '
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="ppcp-r-page-optional-payment-methods">
|
||||||
|
<OnboardingHeader
|
||||||
|
title={ __(
|
||||||
|
'Add optional payment methods to your Checkout',
|
||||||
|
'woocommerce-paypal-payments'
|
||||||
|
) }
|
||||||
|
/>
|
||||||
|
<div className="ppcp-r-inner-container">
|
||||||
|
<SelectBoxWrapper>
|
||||||
|
<SelectBox
|
||||||
|
title={ __(
|
||||||
|
'Available with additional application',
|
||||||
|
'woocommerce-paypal-payments'
|
||||||
|
) }
|
||||||
|
description={
|
||||||
|
<OptionalPaymentMethods
|
||||||
|
useAcdc={ true }
|
||||||
|
isFastlane={ true }
|
||||||
|
isPayLater={ true }
|
||||||
|
storeCountry={ 'us' }
|
||||||
|
storeCurrency={ 'usd' }
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
name={ OPM_RADIO_GROUP_NAME }
|
||||||
|
value={ true }
|
||||||
|
changeCallback={ setAreOptionalPaymentMethodsEnabled }
|
||||||
|
currentValue={ areOptionalPaymentMethodsEnabled }
|
||||||
|
type="radio"
|
||||||
|
></SelectBox>
|
||||||
|
<SelectBox
|
||||||
|
title={ __(
|
||||||
|
'No thanks, I prefer to use a different provider for processing credit cards, digital wallets, and local payment methods',
|
||||||
|
'woocommerce-paypal-payments'
|
||||||
|
) }
|
||||||
|
name={ OPM_RADIO_GROUP_NAME }
|
||||||
|
value={ false }
|
||||||
|
changeCallback={ setAreOptionalPaymentMethodsEnabled }
|
||||||
|
currentValue={ areOptionalPaymentMethodsEnabled }
|
||||||
|
type="radio"
|
||||||
|
></SelectBox>
|
||||||
|
</SelectBoxWrapper>
|
||||||
|
<p
|
||||||
|
className="ppcp-r-optional-payment-methods__description"
|
||||||
|
dangerouslySetInnerHTML={ {
|
||||||
|
__html: pricesBasedDescription,
|
||||||
|
} }
|
||||||
|
></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default StepPaymentMethods;
|
|
@ -1,19 +1,14 @@
|
||||||
import OnboardingHeader from '../../ReusableComponents/OnboardingHeader';
|
|
||||||
import { __ } from '@wordpress/i18n';
|
import { __ } from '@wordpress/i18n';
|
||||||
|
|
||||||
|
import OnboardingHeader from '../../ReusableComponents/OnboardingHeader';
|
||||||
import SelectBox from '../../ReusableComponents/SelectBox';
|
import SelectBox from '../../ReusableComponents/SelectBox';
|
||||||
import SelectBoxWrapper from '../../ReusableComponents/SelectBoxWrapper';
|
import SelectBoxWrapper from '../../ReusableComponents/SelectBoxWrapper';
|
||||||
import { useOnboardingStepProducts } from '../../../data';
|
import { OnboardingHooks, PRODUCT_TYPES } from '../../../data';
|
||||||
import { PRODUCT_TYPES } from '../../../data/constants';
|
|
||||||
|
|
||||||
const PRODUCTS_CHECKBOX_GROUP_NAME = 'products';
|
const PRODUCTS_CHECKBOX_GROUP_NAME = 'products';
|
||||||
|
|
||||||
const StepProducts = ( {
|
const StepProducts = () => {
|
||||||
setStep,
|
const { products, setProducts } = OnboardingHooks.useProducts();
|
||||||
currentStep,
|
|
||||||
stepperOrder,
|
|
||||||
setCompleted,
|
|
||||||
} ) => {
|
|
||||||
const { products, toggleProduct } = useOnboardingStepProducts();
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="ppcp-r-page-products">
|
<div className="ppcp-r-page-products">
|
||||||
|
@ -33,7 +28,7 @@ const StepProducts = ( {
|
||||||
) }
|
) }
|
||||||
name={ PRODUCTS_CHECKBOX_GROUP_NAME }
|
name={ PRODUCTS_CHECKBOX_GROUP_NAME }
|
||||||
value={ PRODUCT_TYPES.VIRTUAL }
|
value={ PRODUCT_TYPES.VIRTUAL }
|
||||||
changeCallback={ toggleProduct }
|
changeCallback={ setProducts }
|
||||||
currentValue={ products }
|
currentValue={ products }
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
>
|
>
|
||||||
|
@ -75,7 +70,7 @@ const StepProducts = ( {
|
||||||
) }
|
) }
|
||||||
name={ PRODUCTS_CHECKBOX_GROUP_NAME }
|
name={ PRODUCTS_CHECKBOX_GROUP_NAME }
|
||||||
value={ PRODUCT_TYPES.PHYSICAL }
|
value={ PRODUCT_TYPES.PHYSICAL }
|
||||||
changeCallback={ toggleProduct }
|
changeCallback={ setProducts }
|
||||||
currentValue={ products }
|
currentValue={ products }
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
>
|
>
|
||||||
|
@ -102,7 +97,7 @@ const StepProducts = ( {
|
||||||
) }
|
) }
|
||||||
name={ PRODUCTS_CHECKBOX_GROUP_NAME }
|
name={ PRODUCTS_CHECKBOX_GROUP_NAME }
|
||||||
value={ PRODUCT_TYPES.SUBSCRIPTIONS }
|
value={ PRODUCT_TYPES.SUBSCRIPTIONS }
|
||||||
changeCallback={ toggleProduct }
|
changeCallback={ setProducts }
|
||||||
currentValue={ products }
|
currentValue={ products }
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
>
|
>
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
import { __, sprintf } from '@wordpress/i18n';
|
import { __ } from '@wordpress/i18n';
|
||||||
import { Button } from '@wordpress/components';
|
import { Button } from '@wordpress/components';
|
||||||
|
|
||||||
import OnboardingHeader from '../../ReusableComponents/OnboardingHeader';
|
import OnboardingHeader from '../../ReusableComponents/OnboardingHeader';
|
||||||
import PaymentMethodIcons from '../../ReusableComponents/PaymentMethodIcons';
|
import PaymentMethodIcons from '../../ReusableComponents/PaymentMethodIcons';
|
||||||
import Separator from '../../ReusableComponents/Separator';
|
import Separator from '../../ReusableComponents/Separator';
|
||||||
import WelcomeDocs from '../../ReusableComponents/WelcomeDocs/WelcomeDocs';
|
import WelcomeDocs from '../../ReusableComponents/WelcomeDocs/WelcomeDocs';
|
||||||
|
import AccordionSection from '../../ReusableComponents/AccordionSection';
|
||||||
|
|
||||||
import AdvancedOptionsForm from './Components/AdvancedOptionsForm';
|
import AdvancedOptionsForm from './Components/AdvancedOptionsForm';
|
||||||
import AccordionSection from '../../ReusableComponents/AccordionSection';
|
|
||||||
|
|
||||||
const StepWelcome = ( { setStep, currentStep, setCompleted } ) => {
|
const StepWelcome = ( { setStep, currentStep, setCompleted } ) => {
|
||||||
return (
|
return (
|
||||||
|
@ -48,7 +48,7 @@ const StepWelcome = ( { setStep, currentStep, setCompleted } ) => {
|
||||||
isFastlane={ true }
|
isFastlane={ true }
|
||||||
isPayLater={ true }
|
isPayLater={ true }
|
||||||
storeCountry={ 'us' }
|
storeCountry={ 'us' }
|
||||||
storeCurrency={ 'usd' }
|
storeCurrency={ 'USD' }
|
||||||
/>
|
/>
|
||||||
<Separator text={ __( 'or', 'woocommerce-paypal-payments' ) } />
|
<Separator text={ __( 'or', 'woocommerce-paypal-payments' ) } />
|
||||||
<AccordionSection
|
<AccordionSection
|
||||||
|
@ -57,7 +57,7 @@ const StepWelcome = ( { setStep, currentStep, setCompleted } ) => {
|
||||||
'woocommerce-paypal-payments'
|
'woocommerce-paypal-payments'
|
||||||
) }
|
) }
|
||||||
className="onboarding-advanced-options"
|
className="onboarding-advanced-options"
|
||||||
initiallyOpen={ false }
|
id="advanced-options"
|
||||||
>
|
>
|
||||||
<AdvancedOptionsForm setCompleted={ setCompleted } />
|
<AdvancedOptionsForm setCompleted={ setCompleted } />
|
||||||
</AccordionSection>
|
</AccordionSection>
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import StepWelcome from './StepWelcome';
|
import StepWelcome from './StepWelcome';
|
||||||
import StepBusiness from './StepBusiness';
|
import StepBusiness from './StepBusiness';
|
||||||
import StepProducts from './StepProducts';
|
import StepProducts from './StepProducts';
|
||||||
|
import StepPaymentMethods from './StepPaymentMethods';
|
||||||
import StepCompleteSetup from './StepCompleteSetup';
|
import StepCompleteSetup from './StepCompleteSetup';
|
||||||
|
|
||||||
export const getSteps = ( flags ) => {
|
export const getSteps = ( flags ) => {
|
||||||
|
@ -8,6 +9,7 @@ export const getSteps = ( flags ) => {
|
||||||
StepWelcome,
|
StepWelcome,
|
||||||
StepBusiness,
|
StepBusiness,
|
||||||
StepProducts,
|
StepProducts,
|
||||||
|
StepPaymentMethods,
|
||||||
StepCompleteSetup,
|
StepCompleteSetup,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
|
@ -1,15 +1,28 @@
|
||||||
import PaymentMethodModal from '../../../ReusableComponents/PaymentMethodModal';
|
import PaymentMethodModal from '../../../ReusableComponents/PaymentMethodModal';
|
||||||
import { __ } from '@wordpress/i18n';
|
import { __ } from '@wordpress/i18n';
|
||||||
import { Button } from '@wordpress/components';
|
import { Button } from '@wordpress/components';
|
||||||
import {
|
|
||||||
PayPalRdb,
|
|
||||||
PayPalRdbWithContent,
|
|
||||||
} from '../../../ReusableComponents/Fields';
|
|
||||||
import { useState } from '@wordpress/element';
|
import { useState } from '@wordpress/element';
|
||||||
|
import { RadioControl } from '@wordpress/components';
|
||||||
|
|
||||||
const THREED_SECURE_GROUP_NAME = 'threed-secure';
|
|
||||||
const ModalAcdc = ( { setModalIsVisible } ) => {
|
const ModalAcdc = ( { setModalIsVisible } ) => {
|
||||||
const [ threeDSecure, setThreeDSecure ] = useState( 'no-3d-secure' );
|
const [ threeDSecure, setThreeDSecure ] = useState( 'no-3d-secure' );
|
||||||
|
const acdcOptions = [
|
||||||
|
{
|
||||||
|
label: __( 'No 3D Secure', 'woocommerce-paypal-payments' ),
|
||||||
|
value: 'no-3d-secure',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: __( 'Only when required', 'woocommerce-paypal-payments' ),
|
||||||
|
value: 'only-required-3d-secure',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: __(
|
||||||
|
'Always require 3D Secure',
|
||||||
|
'woocommerce-paypal-payments'
|
||||||
|
),
|
||||||
|
value: 'always-3d-secure',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PaymentMethodModal
|
<PaymentMethodModal
|
||||||
|
@ -30,39 +43,10 @@ const ModalAcdc = ( { setModalIsVisible } ) => {
|
||||||
) }
|
) }
|
||||||
</p>
|
</p>
|
||||||
<div className="ppcp-r-modal__field-rows ppcp-r-modal__field-rows--acdc">
|
<div className="ppcp-r-modal__field-rows ppcp-r-modal__field-rows--acdc">
|
||||||
<PayPalRdbWithContent
|
<RadioControl
|
||||||
id="no-3d-secure"
|
onChange={ setThreeDSecure }
|
||||||
name={ THREED_SECURE_GROUP_NAME }
|
selected={ threeDSecure }
|
||||||
value="no-3d-secure"
|
options={ acdcOptions }
|
||||||
currentValue={ threeDSecure }
|
|
||||||
handleRdbState={ setThreeDSecure }
|
|
||||||
label={ __(
|
|
||||||
'No 3D Secure',
|
|
||||||
'woocommerce-paypal-payments'
|
|
||||||
) }
|
|
||||||
/>
|
|
||||||
<PayPalRdbWithContent
|
|
||||||
id="only-required-3d-secure"
|
|
||||||
name={ THREED_SECURE_GROUP_NAME }
|
|
||||||
value="only-required-3d-secure"
|
|
||||||
currentValue={ threeDSecure }
|
|
||||||
handleRdbState={ setThreeDSecure }
|
|
||||||
label={ __(
|
|
||||||
'Only when required',
|
|
||||||
'woocommerce-paypal-payments'
|
|
||||||
) }
|
|
||||||
/>
|
|
||||||
|
|
||||||
<PayPalRdbWithContent
|
|
||||||
id="always-3d-secure"
|
|
||||||
name={ THREED_SECURE_GROUP_NAME }
|
|
||||||
value="always-3d-secure"
|
|
||||||
currentValue={ threeDSecure }
|
|
||||||
handleRdbState={ setThreeDSecure }
|
|
||||||
label={ __(
|
|
||||||
'Always require 3D Secure',
|
|
||||||
'woocommerce-paypal-payments'
|
|
||||||
) }
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div className="ppcp-r-modal__field-row ppcp-r-modal__field-row--save">
|
<div className="ppcp-r-modal__field-row ppcp-r-modal__field-row--save">
|
||||||
|
|
|
@ -25,7 +25,6 @@ const TabSettings = () => {
|
||||||
buttonLanguage: '',
|
buttonLanguage: '',
|
||||||
} );
|
} );
|
||||||
const updateFormValue = ( key, value ) => {
|
const updateFormValue = ( key, value ) => {
|
||||||
console.log( key, value );
|
|
||||||
setSettings( { ...settings, [ key ]: value } );
|
setSettings( { ...settings, [ key ]: value } );
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,338 @@
|
||||||
|
import { __, sprintf } from '@wordpress/i18n';
|
||||||
|
import { SelectControl, RadioControl } from '@wordpress/components';
|
||||||
|
import { PayPalCheckboxGroup } from '../../ReusableComponents/Fields';
|
||||||
|
import { useState, useMemo, useEffect } from '@wordpress/element';
|
||||||
|
import { PayPalScriptProvider, PayPalButtons } from '@paypal/react-paypal-js';
|
||||||
|
|
||||||
|
import {
|
||||||
|
defaultLocationSettings,
|
||||||
|
paymentMethodOptions,
|
||||||
|
colorOptions,
|
||||||
|
shapeOptions,
|
||||||
|
buttonLayoutOptions,
|
||||||
|
buttonLabelOptions,
|
||||||
|
} from '../../../data/settings/tab-styling-data';
|
||||||
|
|
||||||
const TabStyling = () => {
|
const TabStyling = () => {
|
||||||
return <div>Styling tab</div>;
|
const [ location, setLocation ] = useState( 'cart' );
|
||||||
|
const [ canRender, setCanRender ] = useState( false );
|
||||||
|
const [ locationSettings, setLocationSettings ] = useState( {
|
||||||
|
...defaultLocationSettings,
|
||||||
|
} );
|
||||||
|
|
||||||
|
// Sometimes buttons won't render. This fixes the timing problem.
|
||||||
|
useEffect( () => {
|
||||||
|
const handleDOMContentLoaded = () => setCanRender( true );
|
||||||
|
if (
|
||||||
|
document.readyState === 'interactive' ||
|
||||||
|
document.readyState === 'complete'
|
||||||
|
) {
|
||||||
|
handleDOMContentLoaded();
|
||||||
|
} else {
|
||||||
|
document.addEventListener(
|
||||||
|
'DOMContentLoaded',
|
||||||
|
handleDOMContentLoaded
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}, [] );
|
||||||
|
|
||||||
|
const currentLocationSettings = useMemo( () => {
|
||||||
|
return locationSettings[ location ];
|
||||||
|
}, [ location, locationSettings ] );
|
||||||
|
|
||||||
|
const locationOptions = useMemo( () => {
|
||||||
|
return Object.keys( locationSettings ).reduce(
|
||||||
|
( locationOptionsData, key ) => {
|
||||||
|
locationOptionsData.push( {
|
||||||
|
value: locationSettings[ key ].value,
|
||||||
|
label: locationSettings[ key ].label,
|
||||||
|
} );
|
||||||
|
|
||||||
|
return locationOptionsData;
|
||||||
|
},
|
||||||
|
[]
|
||||||
|
);
|
||||||
|
}, [] );
|
||||||
|
|
||||||
|
const updateButtonSettings = ( key, value ) => {
|
||||||
|
setLocationSettings( {
|
||||||
|
...locationSettings,
|
||||||
|
[ location ]: {
|
||||||
|
...currentLocationSettings,
|
||||||
|
settings: {
|
||||||
|
...currentLocationSettings.settings,
|
||||||
|
[ key ]: value,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
} );
|
||||||
|
};
|
||||||
|
|
||||||
|
const updateButtonStyle = ( key, value ) => {
|
||||||
|
setLocationSettings( {
|
||||||
|
...locationSettings,
|
||||||
|
[ location ]: {
|
||||||
|
...currentLocationSettings,
|
||||||
|
settings: {
|
||||||
|
...currentLocationSettings.settings,
|
||||||
|
style: {
|
||||||
|
...currentLocationSettings.settings.style,
|
||||||
|
[ key ]: value,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
} );
|
||||||
|
};
|
||||||
|
|
||||||
|
if ( ! canRender ) {
|
||||||
|
return <></>;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="ppcp-r-styling">
|
||||||
|
<div className="ppcp-r-styling__settings">
|
||||||
|
<SectionIntro />
|
||||||
|
<SectionLocations
|
||||||
|
locationOptions={ locationOptions }
|
||||||
|
location={ location }
|
||||||
|
setLocation={ setLocation }
|
||||||
|
/>
|
||||||
|
<SectionPaymentMethods
|
||||||
|
locationSettings={ currentLocationSettings }
|
||||||
|
updateButtonSettings={ updateButtonSettings }
|
||||||
|
/>
|
||||||
|
|
||||||
|
<SectionButtonLayout
|
||||||
|
locationSettings={ currentLocationSettings }
|
||||||
|
updateButtonStyle={ updateButtonStyle }
|
||||||
|
/>
|
||||||
|
|
||||||
|
<SectionButtonShape
|
||||||
|
locationSettings={ currentLocationSettings }
|
||||||
|
updateButtonStyle={ updateButtonStyle }
|
||||||
|
/>
|
||||||
|
<SectionButtonLabel
|
||||||
|
locationSettings={ currentLocationSettings }
|
||||||
|
updateButtonStyle={ updateButtonStyle }
|
||||||
|
/>
|
||||||
|
<SectionButtonColor
|
||||||
|
locationSettings={ currentLocationSettings }
|
||||||
|
updateButtonStyle={ updateButtonStyle }
|
||||||
|
/>
|
||||||
|
<SectionButtonTagline
|
||||||
|
locationSettings={ currentLocationSettings }
|
||||||
|
updateButtonStyle={ updateButtonStyle }
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="ppcp-preview ppcp-r-button-preview ppcp-r-styling__preview">
|
||||||
|
<div className="ppcp-r-styling__preview-inner">
|
||||||
|
<SectionButtonPreview
|
||||||
|
locationSettings={ currentLocationSettings }
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const TabStylingSection = ( props ) => {
|
||||||
|
let sectionTitleClassName = 'ppcp-r-styling__section';
|
||||||
|
|
||||||
|
if ( props?.className ) {
|
||||||
|
sectionTitleClassName += ` ${ props.className }`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={ sectionTitleClassName }>
|
||||||
|
<span className="ppcp-r-styling__title">{ props.title }</span>
|
||||||
|
{ props?.description && (
|
||||||
|
<p
|
||||||
|
dangerouslySetInnerHTML={ {
|
||||||
|
__html: props.description,
|
||||||
|
} }
|
||||||
|
className="ppcp-r-styling__description"
|
||||||
|
/>
|
||||||
|
) }
|
||||||
|
{ props.children }
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const SectionIntro = () => {
|
||||||
|
const buttonStyleDescription = sprintf(
|
||||||
|
// translators: %s: Link to Classic checkout page
|
||||||
|
__(
|
||||||
|
'Customize the appearance of the PayPal smart buttons on the <a href="%s">[MISSING LINK]Classic Checkout page</a>. Checkout Buttons must be enabled to display the PayPal gateway on the Checkout page.'
|
||||||
|
),
|
||||||
|
'#'
|
||||||
|
);
|
||||||
|
return (
|
||||||
|
<TabStylingSection
|
||||||
|
className="ppcp-r-styling__section--rc ppcp-r-styling__section--empty"
|
||||||
|
title={ __( 'Button Styling', 'wooocommerce-paypal-payments' ) }
|
||||||
|
description={ buttonStyleDescription }
|
||||||
|
></TabStylingSection>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const SectionLocations = ( { locationOptions, location, setLocation } ) => {
|
||||||
|
return (
|
||||||
|
<TabStylingSection className="ppcp-r-styling__section--rc">
|
||||||
|
<SelectControl
|
||||||
|
className="ppcp-r-styling__select"
|
||||||
|
value={ location }
|
||||||
|
onChange={ ( newLocation ) => setLocation( newLocation ) }
|
||||||
|
label={ __( 'Locations', 'woocommerce-paypal-payments' ) }
|
||||||
|
options={ locationOptions }
|
||||||
|
/>
|
||||||
|
</TabStylingSection>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const SectionPaymentMethods = ( {
|
||||||
|
locationSettings,
|
||||||
|
updateButtonSettings,
|
||||||
|
} ) => {
|
||||||
|
return (
|
||||||
|
<TabStylingSection
|
||||||
|
title={ __( 'Payment Methods', 'woocommerce-paypal-payments' ) }
|
||||||
|
className="ppcp-r-styling__section--rc"
|
||||||
|
>
|
||||||
|
<div className="ppcp-r-styling__payment-method-checkboxes">
|
||||||
|
<PayPalCheckboxGroup
|
||||||
|
value={ paymentMethodOptions }
|
||||||
|
changeCallback={ ( newValue ) =>
|
||||||
|
updateButtonSettings( 'paymentMethods', newValue )
|
||||||
|
}
|
||||||
|
currentValue={ locationSettings.settings.paymentMethods }
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</TabStylingSection>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const SectionButtonLayout = ( { locationSettings, updateButtonStyle } ) => {
|
||||||
|
const buttonLayoutIsAllowed =
|
||||||
|
locationSettings.settings.style?.layout &&
|
||||||
|
locationSettings.settings.style?.tagline === false;
|
||||||
|
return (
|
||||||
|
buttonLayoutIsAllowed && (
|
||||||
|
<TabStylingSection
|
||||||
|
className="ppcp-r-styling__section--rc"
|
||||||
|
title={ __( 'Button Layout', 'woocommerce-paypal-payments' ) }
|
||||||
|
>
|
||||||
|
<RadioControl
|
||||||
|
className="ppcp-r__horizontal-control"
|
||||||
|
onChange={ ( newValue ) =>
|
||||||
|
updateButtonStyle( 'layout', newValue )
|
||||||
|
}
|
||||||
|
selected={ locationSettings.settings.style.layout }
|
||||||
|
options={ buttonLayoutOptions }
|
||||||
|
/>
|
||||||
|
</TabStylingSection>
|
||||||
|
)
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const SectionButtonShape = ( { locationSettings, updateButtonStyle } ) => {
|
||||||
|
return (
|
||||||
|
<TabStylingSection
|
||||||
|
title={ __( 'Shape', 'woocommerce-paypal-payments' ) }
|
||||||
|
className="ppcp-r-styling__section--rc"
|
||||||
|
>
|
||||||
|
<RadioControl
|
||||||
|
className="ppcp-r__horizontal-control"
|
||||||
|
onChange={ ( newValue ) =>
|
||||||
|
updateButtonStyle( 'shape', newValue )
|
||||||
|
}
|
||||||
|
selected={ locationSettings.settings.style.shape }
|
||||||
|
options={ shapeOptions }
|
||||||
|
/>
|
||||||
|
</TabStylingSection>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const SectionButtonLabel = ( { locationSettings, updateButtonStyle } ) => {
|
||||||
|
return (
|
||||||
|
<TabStylingSection>
|
||||||
|
<SelectControl
|
||||||
|
className="ppcp-r-styling__select"
|
||||||
|
onChange={ ( newValue ) =>
|
||||||
|
updateButtonStyle( 'label', newValue )
|
||||||
|
}
|
||||||
|
value={ locationSettings.settings.style.label }
|
||||||
|
label={ __( 'Button Label', 'woocommerce-paypal-payments' ) }
|
||||||
|
options={ buttonLabelOptions }
|
||||||
|
/>
|
||||||
|
</TabStylingSection>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const SectionButtonColor = ( { locationSettings, updateButtonStyle } ) => {
|
||||||
|
return (
|
||||||
|
<TabStylingSection>
|
||||||
|
<SelectControl
|
||||||
|
className=" ppcp-r-styling__select"
|
||||||
|
label={ __( 'Button Color', 'woocommerce-paypal-payments' ) }
|
||||||
|
onChange={ ( newValue ) =>
|
||||||
|
updateButtonStyle( 'color', newValue )
|
||||||
|
}
|
||||||
|
value={ locationSettings.settings.style.color }
|
||||||
|
options={ colorOptions }
|
||||||
|
/>
|
||||||
|
</TabStylingSection>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const SectionButtonTagline = ( { locationSettings, updateButtonStyle } ) => {
|
||||||
|
const taglineIsAllowed =
|
||||||
|
locationSettings.settings.style.hasOwnProperty( 'tagline' ) &&
|
||||||
|
locationSettings.settings.style?.layout === 'horizontal';
|
||||||
|
|
||||||
|
return (
|
||||||
|
taglineIsAllowed && (
|
||||||
|
<TabStylingSection
|
||||||
|
title={ __( 'Tagline', 'woocommerce-paypal-payments' ) }
|
||||||
|
className="ppcp-r-styling__section--rc"
|
||||||
|
>
|
||||||
|
<PayPalCheckboxGroup
|
||||||
|
value={ [
|
||||||
|
{
|
||||||
|
value: 'tagline',
|
||||||
|
label: __(
|
||||||
|
'Enable Tagline',
|
||||||
|
'woocommerce-paypal-payments'
|
||||||
|
),
|
||||||
|
},
|
||||||
|
] }
|
||||||
|
changeCallback={ ( newValue ) => {
|
||||||
|
updateButtonStyle( 'tagline', newValue );
|
||||||
|
} }
|
||||||
|
currentValue={ locationSettings.settings.style.tagline }
|
||||||
|
/>
|
||||||
|
</TabStylingSection>
|
||||||
|
)
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const SectionButtonPreview = ( { locationSettings } ) => {
|
||||||
|
return (
|
||||||
|
<PayPalScriptProvider
|
||||||
|
options={ {
|
||||||
|
clientId: 'test',
|
||||||
|
merchantId: 'QTQX5NP6N9WZU',
|
||||||
|
components: 'buttons,googlepay',
|
||||||
|
'buyer-country': 'US',
|
||||||
|
currency: 'USD',
|
||||||
|
} }
|
||||||
|
>
|
||||||
|
<PayPalButtons
|
||||||
|
style={ locationSettings.settings.style }
|
||||||
|
forceReRender={ [ locationSettings.settings.style ] }
|
||||||
|
>
|
||||||
|
Error
|
||||||
|
</PayPalButtons>
|
||||||
|
</PayPalScriptProvider>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default TabStyling;
|
export default TabStyling;
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import { useOnboardingStep } from '../../data';
|
import { OnboardingHooks } from '../../data';
|
||||||
import Onboarding from './Onboarding/Onboarding';
|
import Onboarding from './Onboarding/Onboarding';
|
||||||
import SettingsScreen from './SettingsScreen';
|
import SettingsScreen from './SettingsScreen';
|
||||||
|
|
||||||
const Settings = () => {
|
const Settings = () => {
|
||||||
const onboardingProgress = useOnboardingStep();
|
const onboardingProgress = OnboardingHooks.useSteps();
|
||||||
|
|
||||||
if ( ! onboardingProgress.isReady ) {
|
if ( ! onboardingProgress.isReady ) {
|
||||||
// TODO: Use better loading state indicator.
|
// TODO: Use better loading state indicator.
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
/**
|
||||||
|
* Action Types: Define unique identifiers for actions across all store modules.
|
||||||
|
*
|
||||||
|
* @file
|
||||||
|
*/
|
||||||
|
|
||||||
|
export default {
|
||||||
|
// Transient data.
|
||||||
|
SET_TRANSIENT: 'COMMON:SET_TRANSIENT',
|
||||||
|
|
||||||
|
// Persistent data.
|
||||||
|
SET_PERSISTENT: 'COMMON:SET_PERSISTENT',
|
||||||
|
HYDRATE: 'COMMON:HYDRATE',
|
||||||
|
|
||||||
|
// Controls - always start with "DO_".
|
||||||
|
DO_PERSIST_DATA: 'COMMON:DO_PERSIST_DATA',
|
||||||
|
DO_MANUAL_CONNECTION: 'COMMON:DO_MANUAL_CONNECTION',
|
||||||
|
DO_SANDBOX_LOGIN: 'COMMON:DO_SANDBOX_LOGIN',
|
||||||
|
};
|
154
modules/ppcp-settings/resources/js/data/common/actions.js
Normal file
154
modules/ppcp-settings/resources/js/data/common/actions.js
Normal file
|
@ -0,0 +1,154 @@
|
||||||
|
/**
|
||||||
|
* Action Creators: Define functions to create action objects.
|
||||||
|
*
|
||||||
|
* These functions update state or trigger side effects (e.g., async operations).
|
||||||
|
* Actions are categorized as Transient, Persistent, or Side effect.
|
||||||
|
*
|
||||||
|
* @file
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { select } from '@wordpress/data';
|
||||||
|
|
||||||
|
import ACTION_TYPES from './action-types';
|
||||||
|
import { STORE_NAME } from './constants';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {Object} Action An action object that is handled by a reducer or control.
|
||||||
|
* @property {string} type - The action type.
|
||||||
|
* @property {Object?} payload - Optional payload for the action.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Persistent. Set the full onboarding details, usually during app initialization.
|
||||||
|
*
|
||||||
|
* @param {{data: {}, flags?: {}}} payload
|
||||||
|
* @return {Action} The action.
|
||||||
|
*/
|
||||||
|
export const hydrate = ( payload ) => ( {
|
||||||
|
type: ACTION_TYPES.HYDRATE,
|
||||||
|
payload,
|
||||||
|
} );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transient. Marks the onboarding details as "ready", i.e., fully initialized.
|
||||||
|
*
|
||||||
|
* @param {boolean} isReady
|
||||||
|
* @return {Action} The action.
|
||||||
|
*/
|
||||||
|
export const setIsReady = ( isReady ) => ( {
|
||||||
|
type: ACTION_TYPES.SET_TRANSIENT,
|
||||||
|
payload: { isReady },
|
||||||
|
} );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transient. Changes the "saving" flag.
|
||||||
|
*
|
||||||
|
* @param {boolean} isSaving
|
||||||
|
* @return {Action} The action.
|
||||||
|
*/
|
||||||
|
export const setIsSaving = ( isSaving ) => ( {
|
||||||
|
type: ACTION_TYPES.SET_TRANSIENT,
|
||||||
|
payload: { isSaving },
|
||||||
|
} );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transient. Changes the "manual connection is busy" flag.
|
||||||
|
*
|
||||||
|
* @param {boolean} isBusy
|
||||||
|
* @return {Action} The action.
|
||||||
|
*/
|
||||||
|
export const setIsBusy = ( isBusy ) => ( {
|
||||||
|
type: ACTION_TYPES.SET_TRANSIENT,
|
||||||
|
payload: { isBusy },
|
||||||
|
} );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Persistent. Sets the sandbox mode on or off.
|
||||||
|
*
|
||||||
|
* @param {boolean} useSandbox
|
||||||
|
* @return {Action} The action.
|
||||||
|
*/
|
||||||
|
export const setSandboxMode = ( useSandbox ) => ( {
|
||||||
|
type: ACTION_TYPES.SET_PERSISTENT,
|
||||||
|
payload: { useSandbox },
|
||||||
|
} );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Persistent. Toggles the "Manual Connection" mode on or off.
|
||||||
|
*
|
||||||
|
* @param {boolean} useManualConnection
|
||||||
|
* @return {Action} The action.
|
||||||
|
*/
|
||||||
|
export const setManualConnectionMode = ( useManualConnection ) => ( {
|
||||||
|
type: ACTION_TYPES.SET_PERSISTENT,
|
||||||
|
payload: { useManualConnection },
|
||||||
|
} );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Persistent. Changes the "client ID" value.
|
||||||
|
*
|
||||||
|
* @param {string} clientId
|
||||||
|
* @return {Action} The action.
|
||||||
|
*/
|
||||||
|
export const setClientId = ( clientId ) => ( {
|
||||||
|
type: ACTION_TYPES.SET_PERSISTENT,
|
||||||
|
payload: { clientId },
|
||||||
|
} );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Persistent. Changes the "client secret" value.
|
||||||
|
*
|
||||||
|
* @param {string} clientSecret
|
||||||
|
* @return {Action} The action.
|
||||||
|
*/
|
||||||
|
export const setClientSecret = ( clientSecret ) => ( {
|
||||||
|
type: ACTION_TYPES.SET_PERSISTENT,
|
||||||
|
payload: { clientSecret },
|
||||||
|
} );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Side effect. Saves the persistent details to the WP database.
|
||||||
|
*
|
||||||
|
* @return {Action} The action.
|
||||||
|
*/
|
||||||
|
export const persist = function* () {
|
||||||
|
const data = yield select( STORE_NAME ).persistentData();
|
||||||
|
|
||||||
|
yield { type: ACTION_TYPES.DO_PERSIST_DATA, data };
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Side effect. Initiates the sandbox login ISU.
|
||||||
|
*
|
||||||
|
* @return {Action} The action.
|
||||||
|
*/
|
||||||
|
export const connectViaSandbox = function* () {
|
||||||
|
yield setIsBusy( true );
|
||||||
|
|
||||||
|
const result = yield { type: ACTION_TYPES.DO_SANDBOX_LOGIN };
|
||||||
|
yield setIsBusy( false );
|
||||||
|
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Side effect. Initiates a manual connection attempt using the provided client ID and secret.
|
||||||
|
*
|
||||||
|
* @return {Action} The action.
|
||||||
|
*/
|
||||||
|
export const connectViaIdAndSecret = function* () {
|
||||||
|
const { clientId, clientSecret, useSandbox } =
|
||||||
|
yield select( STORE_NAME ).persistentData();
|
||||||
|
|
||||||
|
yield setIsBusy( true );
|
||||||
|
|
||||||
|
const result = yield {
|
||||||
|
type: ACTION_TYPES.DO_MANUAL_CONNECTION,
|
||||||
|
clientId,
|
||||||
|
clientSecret,
|
||||||
|
useSandbox,
|
||||||
|
};
|
||||||
|
yield setIsBusy( false );
|
||||||
|
|
||||||
|
return result;
|
||||||
|
};
|
46
modules/ppcp-settings/resources/js/data/common/constants.js
Normal file
46
modules/ppcp-settings/resources/js/data/common/constants.js
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
/**
|
||||||
|
* Name of the module-store in the main Redux store.
|
||||||
|
*
|
||||||
|
* Helps to isolate data, used by reducer and selectors.
|
||||||
|
*
|
||||||
|
* @type {string}
|
||||||
|
*/
|
||||||
|
export const STORE_NAME = 'wc/paypal/common';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* REST path to hydrate data of this module by loading data from the WP DB..
|
||||||
|
*
|
||||||
|
* Used by resolvers.
|
||||||
|
*
|
||||||
|
* @type {string}
|
||||||
|
*/
|
||||||
|
export const REST_HYDRATE_PATH = '/wc/v3/wc_paypal/common';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* REST path to persist data of this module to the WP DB.
|
||||||
|
*
|
||||||
|
* Used by controls.
|
||||||
|
*
|
||||||
|
* @type {string}
|
||||||
|
*/
|
||||||
|
export const REST_PERSIST_PATH = '/wc/v3/wc_paypal/common';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* REST path to perform the manual connection check, using client ID and secret,
|
||||||
|
*
|
||||||
|
* Used by: Controls
|
||||||
|
* See: ConnectManualRestEndpoint.php
|
||||||
|
*
|
||||||
|
* @type {string}
|
||||||
|
*/
|
||||||
|
export const REST_MANUAL_CONNECTION_PATH = '/wc/v3/wc_paypal/connect_manual';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* REST path to generate an ISU URL for the sandbox-login.
|
||||||
|
*
|
||||||
|
* Used by: Controls
|
||||||
|
* See: LoginLinkRestEndpoint.php
|
||||||
|
*
|
||||||
|
* @type {string}
|
||||||
|
*/
|
||||||
|
export const REST_SANDBOX_CONNECTION_PATH = '/wc/v3/wc_paypal/login_link';
|
80
modules/ppcp-settings/resources/js/data/common/controls.js
vendored
Normal file
80
modules/ppcp-settings/resources/js/data/common/controls.js
vendored
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
/**
|
||||||
|
* Controls: Implement side effects, typically asynchronous operations.
|
||||||
|
*
|
||||||
|
* Controls use ACTION_TYPES keys as identifiers.
|
||||||
|
* They are triggered by corresponding actions and handle external interactions.
|
||||||
|
*
|
||||||
|
* @file
|
||||||
|
*/
|
||||||
|
|
||||||
|
import apiFetch from '@wordpress/api-fetch';
|
||||||
|
|
||||||
|
import {
|
||||||
|
REST_PERSIST_PATH,
|
||||||
|
REST_MANUAL_CONNECTION_PATH,
|
||||||
|
REST_SANDBOX_CONNECTION_PATH,
|
||||||
|
} from './constants';
|
||||||
|
import ACTION_TYPES from './action-types';
|
||||||
|
|
||||||
|
export const controls = {
|
||||||
|
async [ ACTION_TYPES.DO_PERSIST_DATA ]( { data } ) {
|
||||||
|
try {
|
||||||
|
return await apiFetch( {
|
||||||
|
path: REST_PERSIST_PATH,
|
||||||
|
method: 'POST',
|
||||||
|
data,
|
||||||
|
} );
|
||||||
|
} catch ( error ) {
|
||||||
|
console.error( 'Error saving data.', error );
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
async [ ACTION_TYPES.DO_SANDBOX_LOGIN ]() {
|
||||||
|
let result = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
result = await apiFetch( {
|
||||||
|
path: REST_SANDBOX_CONNECTION_PATH,
|
||||||
|
method: 'POST',
|
||||||
|
data: {
|
||||||
|
environment: 'sandbox',
|
||||||
|
products: [ 'EXPRESS_CHECKOUT' ],
|
||||||
|
},
|
||||||
|
} );
|
||||||
|
} catch ( e ) {
|
||||||
|
result = {
|
||||||
|
success: false,
|
||||||
|
error: e,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
},
|
||||||
|
|
||||||
|
async [ ACTION_TYPES.DO_MANUAL_CONNECTION ]( {
|
||||||
|
clientId,
|
||||||
|
clientSecret,
|
||||||
|
useSandbox,
|
||||||
|
} ) {
|
||||||
|
let result = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
result = await apiFetch( {
|
||||||
|
path: REST_MANUAL_CONNECTION_PATH,
|
||||||
|
method: 'POST',
|
||||||
|
data: {
|
||||||
|
clientId,
|
||||||
|
clientSecret,
|
||||||
|
useSandbox,
|
||||||
|
},
|
||||||
|
} );
|
||||||
|
} catch ( e ) {
|
||||||
|
result = {
|
||||||
|
success: false,
|
||||||
|
error: e,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
},
|
||||||
|
};
|
111
modules/ppcp-settings/resources/js/data/common/hooks.js
Normal file
111
modules/ppcp-settings/resources/js/data/common/hooks.js
Normal file
|
@ -0,0 +1,111 @@
|
||||||
|
/**
|
||||||
|
* Hooks: Provide the main API for components to interact with the store.
|
||||||
|
*
|
||||||
|
* These encapsulate store interactions, offering a consistent interface.
|
||||||
|
* Hooks simplify data access and manipulation for components.
|
||||||
|
*
|
||||||
|
* @file
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { useDispatch, useSelect } from '@wordpress/data';
|
||||||
|
import { useCallback } from '@wordpress/element';
|
||||||
|
|
||||||
|
import { STORE_NAME } from './constants';
|
||||||
|
|
||||||
|
const useTransient = ( key ) =>
|
||||||
|
useSelect(
|
||||||
|
( select ) => select( STORE_NAME ).transientData()?.[ key ],
|
||||||
|
[ key ]
|
||||||
|
);
|
||||||
|
|
||||||
|
const usePersistent = ( key ) =>
|
||||||
|
useSelect(
|
||||||
|
( select ) => select( STORE_NAME ).persistentData()?.[ key ],
|
||||||
|
[ key ]
|
||||||
|
);
|
||||||
|
|
||||||
|
const useHooks = () => {
|
||||||
|
const {
|
||||||
|
persist,
|
||||||
|
setSandboxMode,
|
||||||
|
setManualConnectionMode,
|
||||||
|
setClientId,
|
||||||
|
setClientSecret,
|
||||||
|
connectViaSandbox,
|
||||||
|
connectViaIdAndSecret,
|
||||||
|
} = useDispatch( STORE_NAME );
|
||||||
|
|
||||||
|
// Transient accessors.
|
||||||
|
const isReady = useTransient( 'isReady' );
|
||||||
|
|
||||||
|
// Persistent accessors.
|
||||||
|
const clientId = usePersistent( 'clientId' );
|
||||||
|
const clientSecret = usePersistent( 'clientSecret' );
|
||||||
|
const isSandboxMode = usePersistent( 'useSandbox' );
|
||||||
|
const isManualConnectionMode = usePersistent( 'useManualConnection' );
|
||||||
|
|
||||||
|
const savePersistent = async ( setter, value ) => {
|
||||||
|
setter( value );
|
||||||
|
await persist();
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
isReady,
|
||||||
|
isSandboxMode,
|
||||||
|
setSandboxMode: ( state ) => {
|
||||||
|
return savePersistent( setSandboxMode, state );
|
||||||
|
},
|
||||||
|
isManualConnectionMode,
|
||||||
|
setManualConnectionMode: ( state ) => {
|
||||||
|
return savePersistent( setManualConnectionMode, state );
|
||||||
|
},
|
||||||
|
clientId,
|
||||||
|
setClientId: ( value ) => {
|
||||||
|
return savePersistent( setClientId, value );
|
||||||
|
},
|
||||||
|
clientSecret,
|
||||||
|
setClientSecret: ( value ) => {
|
||||||
|
return savePersistent( setClientSecret, value );
|
||||||
|
},
|
||||||
|
connectViaSandbox,
|
||||||
|
connectViaIdAndSecret,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useBusyState = () => {
|
||||||
|
const { setIsBusy } = useDispatch( STORE_NAME );
|
||||||
|
const isBusy = useTransient( 'isBusy' );
|
||||||
|
|
||||||
|
return {
|
||||||
|
isBusy,
|
||||||
|
setIsBusy: useCallback( ( busy ) => setIsBusy( busy ), [ setIsBusy ] ),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useSandbox = () => {
|
||||||
|
const { isSandboxMode, setSandboxMode, connectViaSandbox } = useHooks();
|
||||||
|
|
||||||
|
return { isSandboxMode, setSandboxMode, connectViaSandbox };
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useManualConnection = () => {
|
||||||
|
const {
|
||||||
|
isManualConnectionMode,
|
||||||
|
setManualConnectionMode,
|
||||||
|
clientId,
|
||||||
|
setClientId,
|
||||||
|
clientSecret,
|
||||||
|
setClientSecret,
|
||||||
|
connectViaIdAndSecret,
|
||||||
|
} = useHooks();
|
||||||
|
|
||||||
|
return {
|
||||||
|
isManualConnectionMode,
|
||||||
|
setManualConnectionMode,
|
||||||
|
clientId,
|
||||||
|
setClientId,
|
||||||
|
clientSecret,
|
||||||
|
setClientSecret,
|
||||||
|
connectViaIdAndSecret,
|
||||||
|
};
|
||||||
|
};
|
24
modules/ppcp-settings/resources/js/data/common/index.js
Normal file
24
modules/ppcp-settings/resources/js/data/common/index.js
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
import { createReduxStore, register } from '@wordpress/data';
|
||||||
|
import { controls as wpControls } from '@wordpress/data-controls';
|
||||||
|
|
||||||
|
import { STORE_NAME } from './constants';
|
||||||
|
import reducer from './reducer';
|
||||||
|
import * as selectors from './selectors';
|
||||||
|
import * as actions from './actions';
|
||||||
|
import * as hooks from './hooks';
|
||||||
|
import { resolvers } from './resolvers';
|
||||||
|
import { controls } from './controls';
|
||||||
|
|
||||||
|
export const initStore = () => {
|
||||||
|
const store = createReduxStore( STORE_NAME, {
|
||||||
|
reducer,
|
||||||
|
controls: { ...wpControls, ...controls },
|
||||||
|
actions,
|
||||||
|
selectors,
|
||||||
|
resolvers,
|
||||||
|
} );
|
||||||
|
|
||||||
|
register( store );
|
||||||
|
};
|
||||||
|
|
||||||
|
export { hooks, selectors, STORE_NAME };
|
45
modules/ppcp-settings/resources/js/data/common/reducer.js
Normal file
45
modules/ppcp-settings/resources/js/data/common/reducer.js
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
/**
|
||||||
|
* Reducer: Defines store structure and state updates for this module.
|
||||||
|
*
|
||||||
|
* Manages both transient (temporary) and persistent (saved) state.
|
||||||
|
* The initial state must define all properties, as dynamic additions are not supported.
|
||||||
|
*
|
||||||
|
* @file
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { createReducer, createSetters } from '../utils';
|
||||||
|
import ACTION_TYPES from './action-types';
|
||||||
|
|
||||||
|
// Store structure.
|
||||||
|
|
||||||
|
const defaultTransient = {
|
||||||
|
isReady: false,
|
||||||
|
isBusy: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
const defaultPersistent = {
|
||||||
|
useSandbox: false,
|
||||||
|
useManualConnection: false,
|
||||||
|
clientId: '',
|
||||||
|
clientSecret: '',
|
||||||
|
};
|
||||||
|
|
||||||
|
// Reducer logic.
|
||||||
|
|
||||||
|
const [ setTransient, setPersistent ] = createSetters(
|
||||||
|
defaultTransient,
|
||||||
|
defaultPersistent
|
||||||
|
);
|
||||||
|
|
||||||
|
const commonReducer = createReducer( defaultTransient, defaultPersistent, {
|
||||||
|
[ ACTION_TYPES.SET_TRANSIENT ]: ( state, action ) =>
|
||||||
|
setTransient( state, action ),
|
||||||
|
|
||||||
|
[ ACTION_TYPES.SET_PERSISTENT ]: ( state, action ) =>
|
||||||
|
setPersistent( state, action ),
|
||||||
|
|
||||||
|
[ ACTION_TYPES.HYDRATE ]: ( state, payload ) =>
|
||||||
|
setPersistent( state, payload.data ),
|
||||||
|
} );
|
||||||
|
|
||||||
|
export default commonReducer;
|
36
modules/ppcp-settings/resources/js/data/common/resolvers.js
Normal file
36
modules/ppcp-settings/resources/js/data/common/resolvers.js
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
/**
|
||||||
|
* Resolvers: Handle asynchronous data fetching for the store.
|
||||||
|
*
|
||||||
|
* These functions update store state with data from external sources.
|
||||||
|
* Each resolver corresponds to a specific selector (selector with same name must exist).
|
||||||
|
* Resolvers are called automatically when selectors request unavailable data.
|
||||||
|
*
|
||||||
|
* @file
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { dispatch } from '@wordpress/data';
|
||||||
|
import { __ } from '@wordpress/i18n';
|
||||||
|
import { apiFetch } from '@wordpress/data-controls';
|
||||||
|
|
||||||
|
import { STORE_NAME, REST_HYDRATE_PATH } from './constants';
|
||||||
|
|
||||||
|
export const resolvers = {
|
||||||
|
/**
|
||||||
|
* Retrieve settings from the site's REST API.
|
||||||
|
*/
|
||||||
|
*persistentData() {
|
||||||
|
try {
|
||||||
|
const result = yield apiFetch( { path: REST_HYDRATE_PATH } );
|
||||||
|
|
||||||
|
yield dispatch( STORE_NAME ).hydrate( result );
|
||||||
|
yield dispatch( STORE_NAME ).setIsReady( true );
|
||||||
|
} catch ( e ) {
|
||||||
|
yield dispatch( 'core/notices' ).createErrorNotice(
|
||||||
|
__(
|
||||||
|
'Error retrieving plugin details.',
|
||||||
|
'woocommerce-paypal-payments'
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
21
modules/ppcp-settings/resources/js/data/common/selectors.js
Normal file
21
modules/ppcp-settings/resources/js/data/common/selectors.js
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
/**
|
||||||
|
* Selectors: Extract specific pieces of state from the store.
|
||||||
|
*
|
||||||
|
* These functions provide a consistent interface for accessing store data.
|
||||||
|
* They allow components to retrieve data without knowing the store structure.
|
||||||
|
*
|
||||||
|
* @file
|
||||||
|
*/
|
||||||
|
|
||||||
|
const EMPTY_OBJ = Object.freeze( {} );
|
||||||
|
|
||||||
|
const getState = ( state ) => state || EMPTY_OBJ;
|
||||||
|
|
||||||
|
export const persistentData = ( state ) => {
|
||||||
|
return getState( state ).data || EMPTY_OBJ;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const transientData = ( state ) => {
|
||||||
|
const { data, ...transientState } = getState( state );
|
||||||
|
return transientState || EMPTY_OBJ;
|
||||||
|
};
|
|
@ -1,6 +1,3 @@
|
||||||
export const NAMESPACE = '/wc/v3/wc_paypal';
|
|
||||||
export const STORE_NAME = 'wc/paypal';
|
|
||||||
|
|
||||||
export const BUSINESS_TYPES = {
|
export const BUSINESS_TYPES = {
|
||||||
CASUAL_SELLER: 'casual_seller',
|
CASUAL_SELLER: 'casual_seller',
|
||||||
BUSINESS: 'business',
|
BUSINESS: 'business',
|
||||||
|
|
47
modules/ppcp-settings/resources/js/data/debug.js
Normal file
47
modules/ppcp-settings/resources/js/data/debug.js
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
import { OnboardingStoreName } from './index';
|
||||||
|
|
||||||
|
export const addDebugTools = ( context, modules ) => {
|
||||||
|
if ( ! context || ! context?.debug ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
context.dumpStore = async () => {
|
||||||
|
/* eslint-disable no-console */
|
||||||
|
if ( ! console?.groupCollapsed ) {
|
||||||
|
console.error( 'console.groupCollapsed is not supported.' );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
modules.forEach( ( module ) => {
|
||||||
|
const storeName = module.STORE_NAME;
|
||||||
|
const storeSelector = `wp.data.select( '${ storeName }' )`;
|
||||||
|
console.group( `[STORE] ${ storeSelector }` );
|
||||||
|
|
||||||
|
const dumpStore = ( selector ) => {
|
||||||
|
const contents = wp.data.select( storeName )[ selector ]();
|
||||||
|
|
||||||
|
console.groupCollapsed( `.${ selector }()` );
|
||||||
|
console.table( contents );
|
||||||
|
console.groupEnd();
|
||||||
|
};
|
||||||
|
|
||||||
|
Object.keys( module.selectors ).forEach( dumpStore );
|
||||||
|
|
||||||
|
console.groupEnd();
|
||||||
|
} );
|
||||||
|
/* eslint-enable no-console */
|
||||||
|
};
|
||||||
|
|
||||||
|
context.resetStore = () => {
|
||||||
|
const onboarding = wp.data.dispatch( OnboardingStoreName );
|
||||||
|
onboarding.reset();
|
||||||
|
onboarding.persist();
|
||||||
|
};
|
||||||
|
|
||||||
|
context.startOnboarding = () => {
|
||||||
|
const onboarding = wp.data.dispatch( OnboardingStoreName );
|
||||||
|
onboarding.setCompleted( false );
|
||||||
|
onboarding.setStep( 0 );
|
||||||
|
onboarding.persist();
|
||||||
|
};
|
||||||
|
};
|
|
@ -1,7 +1,16 @@
|
||||||
import { STORE_NAME } from './constants';
|
import { addDebugTools } from './debug';
|
||||||
import { initStore } from './store';
|
import * as Onboarding from './onboarding';
|
||||||
|
import * as Common from './common';
|
||||||
|
|
||||||
initStore();
|
Onboarding.initStore();
|
||||||
|
Common.initStore();
|
||||||
|
|
||||||
export const WC_PAYPAL_STORE_NAME = STORE_NAME;
|
export const OnboardingHooks = Onboarding.hooks;
|
||||||
export * from './onboarding/hooks';
|
export const CommonHooks = Common.hooks;
|
||||||
|
|
||||||
|
export const OnboardingStoreName = Onboarding.STORE_NAME;
|
||||||
|
export const CommonStoreName = Common.STORE_NAME;
|
||||||
|
|
||||||
|
export * from './constants';
|
||||||
|
|
||||||
|
addDebugTools( window.ppcpSettings, [ Onboarding, Common ] );
|
||||||
|
|
|
@ -1,19 +1,18 @@
|
||||||
export default {
|
/**
|
||||||
RESET_ONBOARDING: 'RESET_ONBOARDING',
|
* Action Types: Define unique identifiers for actions across all store modules.
|
||||||
|
*
|
||||||
|
* @file
|
||||||
|
*/
|
||||||
|
|
||||||
|
export default {
|
||||||
// Transient data.
|
// Transient data.
|
||||||
SET_ONBOARDING_IS_READY: 'SET_ONBOARDING_IS_READY',
|
SET_TRANSIENT: 'ONBOARDING:SET_TRANSIENT',
|
||||||
SET_IS_SAVING_ONBOARDING: 'SET_IS_SAVING_ONBOARDING',
|
|
||||||
SET_MANUAL_CONNECTION_BUSY: 'SET_MANUAL_CONNECTION_BUSY',
|
|
||||||
|
|
||||||
// Persistent data.
|
// Persistent data.
|
||||||
SET_ONBOARDING_COMPLETED: 'SET_ONBOARDING_COMPLETED',
|
SET_PERSISTENT: 'ONBOARDING:SET_PERSISTENT',
|
||||||
SET_ONBOARDING_DETAILS: 'SET_ONBOARDING_DETAILS',
|
RESET: 'ONBOARDING:RESET',
|
||||||
SET_ONBOARDING_STEP: 'SET_ONBOARDING_STEP',
|
HYDRATE: 'ONBOARDING:HYDRATE',
|
||||||
SET_SANDBOX_MODE: 'SET_SANDBOX_MODE',
|
|
||||||
SET_MANUAL_CONNECTION_MODE: 'SET_MANUAL_CONNECTION_MODE',
|
// Controls - always start with "DO_".
|
||||||
SET_CLIENT_ID: 'SET_CLIENT_ID',
|
DO_PERSIST_DATA: 'ONBOARDING:DO_PERSIST_DATA',
|
||||||
SET_CLIENT_SECRET: 'SET_CLIENT_SECRET',
|
|
||||||
SET_IS_CASUAL_SELLER: 'SET_IS_CASUAL_SELLER',
|
|
||||||
SET_PRODUCTS: 'SET_PRODUCTS',
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,235 +1,116 @@
|
||||||
|
/**
|
||||||
|
* Action Creators: Define functions to create action objects.
|
||||||
|
*
|
||||||
|
* These functions update state or trigger side effects (e.g., async operations).
|
||||||
|
* Actions are categorized as Transient, Persistent, or Side effect.
|
||||||
|
*
|
||||||
|
* @file
|
||||||
|
*/
|
||||||
|
|
||||||
import { select } from '@wordpress/data';
|
import { select } from '@wordpress/data';
|
||||||
import { apiFetch } from '@wordpress/data-controls';
|
|
||||||
import ACTION_TYPES from './action-types';
|
import ACTION_TYPES from './action-types';
|
||||||
import { NAMESPACE, STORE_NAME } from '../constants';
|
import { STORE_NAME } from './constants';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {Object} Action An action object that is handled by a reducer or control.
|
||||||
|
* @property {string} type - The action type.
|
||||||
|
* @property {Object?} payload - Optional payload for the action.
|
||||||
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Special. Resets all values in the onboarding store to initial defaults.
|
* Special. Resets all values in the onboarding store to initial defaults.
|
||||||
*
|
*
|
||||||
* @return {{type: string}} The action.
|
* @return {Action} The action.
|
||||||
*/
|
*/
|
||||||
export const resetOnboarding = () => {
|
export const reset = () => ( { type: ACTION_TYPES.RESET } );
|
||||||
return { type: ACTION_TYPES.RESET_ONBOARDING };
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Non-persistent. Marks the onboarding details as "ready", i.e., fully initialized.
|
|
||||||
*
|
|
||||||
* @param {boolean} isReady
|
|
||||||
* @return {{type: string, isReady}} The action.
|
|
||||||
*/
|
|
||||||
export const setIsReady = ( isReady ) => {
|
|
||||||
return {
|
|
||||||
type: ACTION_TYPES.SET_ONBOARDING_IS_READY,
|
|
||||||
isReady,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Non-persistent. Changes the "saving" flag.
|
|
||||||
*
|
|
||||||
* @param {boolean} isSaving
|
|
||||||
* @return {{type: string, isSaving}} The action.
|
|
||||||
*/
|
|
||||||
export const setIsSaving = ( isSaving ) => {
|
|
||||||
return {
|
|
||||||
type: ACTION_TYPES.SET_IS_SAVING_ONBOARDING,
|
|
||||||
isSaving,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Non-persistent. Changes the "manual connection is busy" flag.
|
|
||||||
*
|
|
||||||
* @param {boolean} isBusy
|
|
||||||
* @return {{type: string, isBusy}} The action.
|
|
||||||
*/
|
|
||||||
export const setManualConnectionIsBusy = ( isBusy ) => {
|
|
||||||
return {
|
|
||||||
type: ACTION_TYPES.SET_MANUAL_CONNECTION_BUSY,
|
|
||||||
isBusy,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Persistent. Set the full onboarding details, usually during app initialization.
|
* Persistent. Set the full onboarding details, usually during app initialization.
|
||||||
*
|
*
|
||||||
* @param {{data: {}, flags?: {}}} payload
|
* @param {{data: {}, flags?: {}}} payload
|
||||||
* @return {{type: string, payload}} The action.
|
* @return {Action} The action.
|
||||||
*/
|
*/
|
||||||
export const setOnboardingDetails = ( payload ) => {
|
export const hydrate = ( payload ) => ( {
|
||||||
return {
|
type: ACTION_TYPES.HYDRATE,
|
||||||
type: ACTION_TYPES.SET_ONBOARDING_DETAILS,
|
payload,
|
||||||
payload,
|
} );
|
||||||
};
|
|
||||||
};
|
/**
|
||||||
|
* Transient. Marks the onboarding details as "ready", i.e., fully initialized.
|
||||||
|
*
|
||||||
|
* @param {boolean} isReady
|
||||||
|
* @return {Action} The action.
|
||||||
|
*/
|
||||||
|
export const setIsReady = ( isReady ) => ( {
|
||||||
|
type: ACTION_TYPES.SET_TRANSIENT,
|
||||||
|
payload: { isReady },
|
||||||
|
} );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Persistent.Set the "onboarding completed" flag which shows or hides the wizard.
|
* Persistent.Set the "onboarding completed" flag which shows or hides the wizard.
|
||||||
*
|
*
|
||||||
* @param {boolean} completed
|
* @param {boolean} completed
|
||||||
* @return {{type: string, payload}} The action.
|
* @return {Action} The action.
|
||||||
*/
|
*/
|
||||||
export const setCompleted = ( completed ) => {
|
export const setCompleted = ( completed ) => ( {
|
||||||
return {
|
type: ACTION_TYPES.SET_PERSISTENT,
|
||||||
type: ACTION_TYPES.SET_ONBOARDING_COMPLETED,
|
payload: { completed },
|
||||||
completed,
|
} );
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Persistent. Sets the onboarding wizard to a new step.
|
* Persistent. Sets the onboarding wizard to a new step.
|
||||||
*
|
*
|
||||||
* @param {number} step
|
* @param {number} step
|
||||||
* @return {{type: string, step}} An action.
|
* @return {Action} The action.
|
||||||
*/
|
*/
|
||||||
export const setOnboardingStep = ( step ) => {
|
export const setStep = ( step ) => ( {
|
||||||
return {
|
type: ACTION_TYPES.SET_PERSISTENT,
|
||||||
type: ACTION_TYPES.SET_ONBOARDING_STEP,
|
payload: { step },
|
||||||
step,
|
} );
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Persistent. Sets the sandbox mode on or off.
|
|
||||||
*
|
|
||||||
* @param {boolean} sandboxMode
|
|
||||||
* @return {{type: string, useSandbox}} An action.
|
|
||||||
*/
|
|
||||||
export const setSandboxMode = ( sandboxMode ) => {
|
|
||||||
return {
|
|
||||||
type: ACTION_TYPES.SET_SANDBOX_MODE,
|
|
||||||
useSandbox: sandboxMode,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Persistent. Toggles the "Manual Connection" mode on or off.
|
|
||||||
*
|
|
||||||
* @param {boolean} manualConnectionMode
|
|
||||||
* @return {{type: string, useManualConnection}} An action.
|
|
||||||
*/
|
|
||||||
export const setManualConnectionMode = ( manualConnectionMode ) => {
|
|
||||||
return {
|
|
||||||
type: ACTION_TYPES.SET_MANUAL_CONNECTION_MODE,
|
|
||||||
useManualConnection: manualConnectionMode,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Persistent. Changes the "client ID" value.
|
|
||||||
*
|
|
||||||
* @param {string} clientId
|
|
||||||
* @return {{type: string, clientId}} The action.
|
|
||||||
*/
|
|
||||||
export const setClientId = ( clientId ) => {
|
|
||||||
return {
|
|
||||||
type: ACTION_TYPES.SET_CLIENT_ID,
|
|
||||||
clientId,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Persistent. Changes the "client secret" value.
|
|
||||||
*
|
|
||||||
* @param {string} clientSecret
|
|
||||||
* @return {{type: string, clientSecret}} The action.
|
|
||||||
*/
|
|
||||||
export const setClientSecret = ( clientSecret ) => {
|
|
||||||
return {
|
|
||||||
type: ACTION_TYPES.SET_CLIENT_SECRET,
|
|
||||||
clientSecret,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Persistent. Sets the "isCasualSeller" value.
|
* Persistent. Sets the "isCasualSeller" value.
|
||||||
*
|
*
|
||||||
* @param {boolean} isCasualSeller
|
* @param {boolean} isCasualSeller
|
||||||
* @return {{type: string, isCasualSeller}} The action.
|
* @return {Action} The action.
|
||||||
*/
|
*/
|
||||||
export const setIsCasualSeller = ( isCasualSeller ) => {
|
export const setIsCasualSeller = ( isCasualSeller ) => ( {
|
||||||
return {
|
type: ACTION_TYPES.SET_PERSISTENT,
|
||||||
type: ACTION_TYPES.SET_IS_CASUAL_SELLER,
|
payload: { isCasualSeller },
|
||||||
isCasualSeller,
|
} );
|
||||||
};
|
|
||||||
};
|
/**
|
||||||
|
* Persistent. Sets the "areOptionalPaymentMethodsEnabled" value.
|
||||||
|
*
|
||||||
|
* @param {boolean} areOptionalPaymentMethodsEnabled
|
||||||
|
* @return {Action} The action.
|
||||||
|
*/
|
||||||
|
export const setAreOptionalPaymentMethodsEnabled = (
|
||||||
|
areOptionalPaymentMethodsEnabled
|
||||||
|
) => ( {
|
||||||
|
type: ACTION_TYPES.SET_PERSISTENT,
|
||||||
|
payload: { areOptionalPaymentMethodsEnabled },
|
||||||
|
} );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Persistent. Sets the "products" array.
|
* Persistent. Sets the "products" array.
|
||||||
*
|
*
|
||||||
* @param {string[]} products
|
* @param {string[]} products
|
||||||
* @return {{type: string, products}} The action.
|
* @return {Action} The action.
|
||||||
*/
|
*/
|
||||||
export const setProducts = ( products ) => {
|
export const setProducts = ( products ) => ( {
|
||||||
return {
|
type: ACTION_TYPES.SET_PERSISTENT,
|
||||||
type: ACTION_TYPES.SET_PRODUCTS,
|
payload: { products },
|
||||||
products,
|
} );
|
||||||
};
|
|
||||||
|
/**
|
||||||
|
* Side effect. Triggers the persistence of onboarding data to the server.
|
||||||
|
*
|
||||||
|
* @return {Action} The action.
|
||||||
|
*/
|
||||||
|
export const persist = function* () {
|
||||||
|
const data = yield select( STORE_NAME ).persistentData();
|
||||||
|
|
||||||
|
yield { type: ACTION_TYPES.DO_PERSIST_DATA, data };
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Attempts to establish a connection using client ID and secret via the server-side
|
|
||||||
* connection endpoint.
|
|
||||||
*
|
|
||||||
* @return {Object} The server response object
|
|
||||||
*/
|
|
||||||
export function* connectViaIdAndSecret() {
|
|
||||||
let result = null;
|
|
||||||
|
|
||||||
try {
|
|
||||||
const path = `${ NAMESPACE }/connect_manual`;
|
|
||||||
const { clientId, clientSecret, useSandbox } =
|
|
||||||
yield select( STORE_NAME ).getPersistentData();
|
|
||||||
|
|
||||||
yield setManualConnectionIsBusy( true );
|
|
||||||
|
|
||||||
result = yield apiFetch( {
|
|
||||||
path,
|
|
||||||
method: 'POST',
|
|
||||||
data: {
|
|
||||||
clientId,
|
|
||||||
clientSecret,
|
|
||||||
useSandbox,
|
|
||||||
},
|
|
||||||
} );
|
|
||||||
} catch ( e ) {
|
|
||||||
result = {
|
|
||||||
success: false,
|
|
||||||
error: e,
|
|
||||||
};
|
|
||||||
} finally {
|
|
||||||
yield setManualConnectionIsBusy( false );
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Saves the persistent details to the WP database.
|
|
||||||
*
|
|
||||||
* @return {boolean} True, if the values were successfully saved.
|
|
||||||
*/
|
|
||||||
export function* persist() {
|
|
||||||
let error = null;
|
|
||||||
|
|
||||||
try {
|
|
||||||
const path = `${ NAMESPACE }/onboarding`;
|
|
||||||
const data = select( STORE_NAME ).getPersistentData();
|
|
||||||
|
|
||||||
yield setIsSaving( true );
|
|
||||||
|
|
||||||
yield apiFetch( {
|
|
||||||
path,
|
|
||||||
method: 'post',
|
|
||||||
data,
|
|
||||||
} );
|
|
||||||
} catch ( e ) {
|
|
||||||
error = e;
|
|
||||||
console.error( 'Error saving progress.', e );
|
|
||||||
} finally {
|
|
||||||
yield setIsSaving( false );
|
|
||||||
}
|
|
||||||
|
|
||||||
return error === null;
|
|
||||||
}
|
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
/**
|
||||||
|
* Name of the Redux store module.
|
||||||
|
*
|
||||||
|
* Used by: Reducer, Selector, Index
|
||||||
|
*
|
||||||
|
* @type {string}
|
||||||
|
*/
|
||||||
|
export const STORE_NAME = 'wc/paypal/onboarding';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* REST path to hydrate data of this module by loading data from the WP DB..
|
||||||
|
*
|
||||||
|
* Used by: Resolvers
|
||||||
|
* See: OnboardingRestEndpoint.php
|
||||||
|
*
|
||||||
|
* @type {string}
|
||||||
|
*/
|
||||||
|
export const REST_HYDRATE_PATH = '/wc/v3/wc_paypal/onboarding';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* REST path to persist data of this module to the WP DB.
|
||||||
|
*
|
||||||
|
* Used by: Controls
|
||||||
|
* See: OnboardingRestEndpoint.php
|
||||||
|
*
|
||||||
|
* @type {string}
|
||||||
|
*/
|
||||||
|
export const REST_PERSIST_PATH = '/wc/v3/wc_paypal/onboarding';
|
27
modules/ppcp-settings/resources/js/data/onboarding/controls.js
vendored
Normal file
27
modules/ppcp-settings/resources/js/data/onboarding/controls.js
vendored
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
/**
|
||||||
|
* Controls: Implement side effects, typically asynchronous operations.
|
||||||
|
*
|
||||||
|
* Controls use ACTION_TYPES keys as identifiers.
|
||||||
|
* They are triggered by corresponding actions and handle external interactions.
|
||||||
|
*
|
||||||
|
* @file
|
||||||
|
*/
|
||||||
|
|
||||||
|
import apiFetch from '@wordpress/api-fetch';
|
||||||
|
|
||||||
|
import { REST_PERSIST_PATH } from './constants';
|
||||||
|
import ACTION_TYPES from './action-types';
|
||||||
|
|
||||||
|
export const controls = {
|
||||||
|
async [ ACTION_TYPES.DO_PERSIST_DATA ]( { data } ) {
|
||||||
|
try {
|
||||||
|
await apiFetch( {
|
||||||
|
path: REST_PERSIST_PATH,
|
||||||
|
method: 'POST',
|
||||||
|
data,
|
||||||
|
} );
|
||||||
|
} catch ( e ) {
|
||||||
|
console.error( 'Error saving progress.', e );
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
|
@ -1,163 +1,115 @@
|
||||||
import { useSelect, useDispatch } from '@wordpress/data';
|
/**
|
||||||
import apiFetch from '@wordpress/api-fetch';
|
* Hooks: Provide the main API for components to interact with the store.
|
||||||
import { NAMESPACE, PRODUCT_TYPES, STORE_NAME } from '../constants';
|
*
|
||||||
import { getFlags } from './selectors';
|
* These encapsulate store interactions, offering a consistent interface.
|
||||||
|
* Hooks simplify data access and manipulation for components.
|
||||||
|
*
|
||||||
|
* @file
|
||||||
|
*/
|
||||||
|
|
||||||
const useOnboardingDetails = () => {
|
import { useSelect, useDispatch } from '@wordpress/data';
|
||||||
|
|
||||||
|
import { PRODUCT_TYPES } from '../constants';
|
||||||
|
import { STORE_NAME } from './constants';
|
||||||
|
|
||||||
|
const useTransient = ( key ) =>
|
||||||
|
useSelect(
|
||||||
|
( select ) => select( STORE_NAME ).transientData()?.[ key ],
|
||||||
|
[ key ]
|
||||||
|
);
|
||||||
|
|
||||||
|
const usePersistent = ( key ) =>
|
||||||
|
useSelect(
|
||||||
|
( select ) => select( STORE_NAME ).persistentData()?.[ key ],
|
||||||
|
[ key ]
|
||||||
|
);
|
||||||
|
|
||||||
|
const useHooks = () => {
|
||||||
const {
|
const {
|
||||||
persist,
|
persist,
|
||||||
setOnboardingStep,
|
setStep,
|
||||||
setCompleted,
|
setCompleted,
|
||||||
setSandboxMode,
|
|
||||||
setManualConnectionMode,
|
|
||||||
setClientId,
|
|
||||||
setClientSecret,
|
|
||||||
setIsCasualSeller,
|
setIsCasualSeller,
|
||||||
|
setAreOptionalPaymentMethodsEnabled,
|
||||||
setProducts,
|
setProducts,
|
||||||
} = useDispatch( STORE_NAME );
|
} = useDispatch( STORE_NAME );
|
||||||
|
|
||||||
// Transient accessors.
|
|
||||||
const isSaving = useSelect( ( select ) => {
|
|
||||||
return select( STORE_NAME ).getTransientData().isSaving;
|
|
||||||
}, [] );
|
|
||||||
|
|
||||||
const isReady = useSelect( ( select ) => {
|
|
||||||
return select( STORE_NAME ).getTransientData().isReady;
|
|
||||||
} );
|
|
||||||
|
|
||||||
const isManualConnectionBusy = useSelect( ( select ) => {
|
|
||||||
return select( STORE_NAME ).getTransientData().isManualConnectionBusy;
|
|
||||||
}, [] );
|
|
||||||
|
|
||||||
// Read-only flags.
|
// Read-only flags.
|
||||||
const flags = useSelect( ( select ) => {
|
const flags = useSelect( ( select ) => select( STORE_NAME ).flags(), [] );
|
||||||
return select( STORE_NAME ).getFlags();
|
|
||||||
} );
|
// Transient accessors.
|
||||||
|
const isReady = useTransient( 'isReady' );
|
||||||
|
|
||||||
// Persistent accessors.
|
// Persistent accessors.
|
||||||
const step = useSelect( ( select ) => {
|
const step = usePersistent( 'step' );
|
||||||
return select( STORE_NAME ).getPersistentData().step || 0;
|
const completed = usePersistent( 'completed' );
|
||||||
} );
|
const isCasualSeller = usePersistent( 'isCasualSeller' );
|
||||||
|
const areOptionalPaymentMethodsEnabled = usePersistent(
|
||||||
|
'areOptionalPaymentMethodsEnabled'
|
||||||
|
);
|
||||||
|
const products = usePersistent( 'products' );
|
||||||
|
|
||||||
const completed = useSelect( ( select ) => {
|
const savePersistent = async ( setter, value ) => {
|
||||||
return select( STORE_NAME ).getPersistentData().completed;
|
|
||||||
} );
|
|
||||||
|
|
||||||
const clientId = useSelect( ( select ) => {
|
|
||||||
return select( STORE_NAME ).getPersistentData().clientId;
|
|
||||||
}, [] );
|
|
||||||
|
|
||||||
const clientSecret = useSelect( ( select ) => {
|
|
||||||
return select( STORE_NAME ).getPersistentData().clientSecret;
|
|
||||||
}, [] );
|
|
||||||
|
|
||||||
const isSandboxMode = useSelect( ( select ) => {
|
|
||||||
return select( STORE_NAME ).getPersistentData().useSandbox;
|
|
||||||
}, [] );
|
|
||||||
|
|
||||||
const isManualConnectionMode = useSelect( ( select ) => {
|
|
||||||
return select( STORE_NAME ).getPersistentData().useManualConnection;
|
|
||||||
}, [] );
|
|
||||||
|
|
||||||
const isCasualSeller = useSelect( ( select ) => {
|
|
||||||
return select( STORE_NAME ).getPersistentData().isCasualSeller;
|
|
||||||
}, [] );
|
|
||||||
|
|
||||||
const products = useSelect( ( select ) => {
|
|
||||||
return select( STORE_NAME ).getPersistentData().products || [];
|
|
||||||
}, [] );
|
|
||||||
|
|
||||||
const toggleProduct = ( list ) => {
|
|
||||||
const validProducts = list.filter( ( item ) =>
|
|
||||||
Object.values( PRODUCT_TYPES ).includes( item )
|
|
||||||
);
|
|
||||||
return setDetailAndPersist( setProducts, validProducts );
|
|
||||||
};
|
|
||||||
|
|
||||||
const setDetailAndPersist = async ( setter, value ) => {
|
|
||||||
setter( value );
|
setter( value );
|
||||||
await persist();
|
await persist();
|
||||||
};
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
isSaving,
|
|
||||||
isReady,
|
|
||||||
isManualConnectionBusy,
|
|
||||||
step,
|
|
||||||
setStep: ( value ) => setDetailAndPersist( setOnboardingStep, value ),
|
|
||||||
completed,
|
|
||||||
setCompleted: ( state ) => setDetailAndPersist( setCompleted, state ),
|
|
||||||
isSandboxMode,
|
|
||||||
setSandboxMode: ( state ) =>
|
|
||||||
setDetailAndPersist( setSandboxMode, state ),
|
|
||||||
isManualConnectionMode,
|
|
||||||
setManualConnectionMode: ( state ) =>
|
|
||||||
setDetailAndPersist( setManualConnectionMode, state ),
|
|
||||||
clientId,
|
|
||||||
setClientId: ( value ) => setDetailAndPersist( setClientId, value ),
|
|
||||||
clientSecret,
|
|
||||||
setClientSecret: ( value ) =>
|
|
||||||
setDetailAndPersist( setClientSecret, value ),
|
|
||||||
isCasualSeller,
|
|
||||||
setIsCasualSeller: ( value ) =>
|
|
||||||
setDetailAndPersist( setIsCasualSeller, value ),
|
|
||||||
products,
|
|
||||||
toggleProduct,
|
|
||||||
flags,
|
flags,
|
||||||
|
isReady,
|
||||||
|
step,
|
||||||
|
setStep: ( value ) => {
|
||||||
|
return savePersistent( setStep, value );
|
||||||
|
},
|
||||||
|
completed,
|
||||||
|
setCompleted: ( state ) => {
|
||||||
|
return savePersistent( setCompleted, state );
|
||||||
|
},
|
||||||
|
isCasualSeller,
|
||||||
|
setIsCasualSeller: ( value ) => {
|
||||||
|
return savePersistent( setIsCasualSeller, value );
|
||||||
|
},
|
||||||
|
areOptionalPaymentMethodsEnabled,
|
||||||
|
setAreOptionalPaymentMethodsEnabled: ( value ) => {
|
||||||
|
return savePersistent( setAreOptionalPaymentMethodsEnabled, value );
|
||||||
|
},
|
||||||
|
products,
|
||||||
|
setProducts: ( activeProducts ) => {
|
||||||
|
const validProducts = activeProducts.filter( ( item ) =>
|
||||||
|
Object.values( PRODUCT_TYPES ).includes( item )
|
||||||
|
);
|
||||||
|
return savePersistent( setProducts, validProducts );
|
||||||
|
},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useOnboardingStepWelcome = () => {
|
export const useBusiness = () => {
|
||||||
const {
|
const { isCasualSeller, setIsCasualSeller } = useHooks();
|
||||||
isSaving,
|
|
||||||
isManualConnectionBusy,
|
|
||||||
isSandboxMode,
|
|
||||||
setSandboxMode,
|
|
||||||
isManualConnectionMode,
|
|
||||||
setManualConnectionMode,
|
|
||||||
clientId,
|
|
||||||
setClientId,
|
|
||||||
clientSecret,
|
|
||||||
setClientSecret,
|
|
||||||
} = useOnboardingDetails();
|
|
||||||
|
|
||||||
return {
|
|
||||||
isSaving,
|
|
||||||
isManualConnectionBusy,
|
|
||||||
isSandboxMode,
|
|
||||||
setSandboxMode,
|
|
||||||
isManualConnectionMode,
|
|
||||||
setManualConnectionMode,
|
|
||||||
clientId,
|
|
||||||
setClientId,
|
|
||||||
clientSecret,
|
|
||||||
setClientSecret,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export const useOnboardingStepBusiness = () => {
|
|
||||||
const { isCasualSeller, setIsCasualSeller } = useOnboardingDetails();
|
|
||||||
|
|
||||||
return { isCasualSeller, setIsCasualSeller };
|
return { isCasualSeller, setIsCasualSeller };
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useOnboardingStepProducts = () => {
|
export const useProducts = () => {
|
||||||
const { products, toggleProduct } = useOnboardingDetails();
|
const { products, setProducts } = useHooks();
|
||||||
|
|
||||||
return { products, toggleProduct };
|
return { products, setProducts };
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useOnboardingStep = () => {
|
export const useOptionalPaymentMethods = () => {
|
||||||
const { isReady, step, setStep, completed, setCompleted, flags } =
|
const {
|
||||||
useOnboardingDetails();
|
areOptionalPaymentMethodsEnabled,
|
||||||
|
setAreOptionalPaymentMethodsEnabled,
|
||||||
return { isReady, step, setStep, completed, setCompleted, flags };
|
} = useHooks();
|
||||||
};
|
|
||||||
|
|
||||||
export const useManualConnect = () => {
|
|
||||||
const { connectViaIdAndSecret } = useDispatch( STORE_NAME );
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
connectManual: connectViaIdAndSecret,
|
areOptionalPaymentMethodsEnabled,
|
||||||
|
setAreOptionalPaymentMethodsEnabled,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const useSteps = () => {
|
||||||
|
const { flags, isReady, step, setStep, completed, setCompleted } =
|
||||||
|
useHooks();
|
||||||
|
|
||||||
|
return { flags, isReady, step, setStep, completed, setCompleted };
|
||||||
|
};
|
||||||
|
|
|
@ -1,6 +1,24 @@
|
||||||
|
import { createReduxStore, register } from '@wordpress/data';
|
||||||
|
import { controls as wpControls } from '@wordpress/data-controls';
|
||||||
|
|
||||||
|
import { STORE_NAME } from './constants';
|
||||||
import reducer from './reducer';
|
import reducer from './reducer';
|
||||||
import * as selectors from './selectors';
|
import * as selectors from './selectors';
|
||||||
import * as actions from './actions';
|
import * as actions from './actions';
|
||||||
import * as resolvers from './resolvers';
|
import * as hooks from './hooks';
|
||||||
|
import { resolvers } from './resolvers';
|
||||||
|
import { controls } from './controls';
|
||||||
|
|
||||||
export { reducer, selectors, actions, resolvers };
|
export const initStore = () => {
|
||||||
|
const store = createReduxStore( STORE_NAME, {
|
||||||
|
reducer,
|
||||||
|
controls: { ...wpControls, ...controls },
|
||||||
|
actions,
|
||||||
|
selectors,
|
||||||
|
resolvers,
|
||||||
|
} );
|
||||||
|
|
||||||
|
register( store );
|
||||||
|
};
|
||||||
|
|
||||||
|
export { hooks, selectors, STORE_NAME };
|
||||||
|
|
|
@ -1,21 +1,19 @@
|
||||||
|
/**
|
||||||
|
* Reducer: Defines store structure and state updates for this module.
|
||||||
|
*
|
||||||
|
* Manages both transient (temporary) and persistent (saved) state.
|
||||||
|
* The initial state must define all properties, as dynamic additions are not supported.
|
||||||
|
*
|
||||||
|
* @file
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { createReducer, createSetters } from '../utils';
|
||||||
import ACTION_TYPES from './action-types';
|
import ACTION_TYPES from './action-types';
|
||||||
|
|
||||||
const defaultState = {
|
// Store structure.
|
||||||
isReady: false,
|
|
||||||
isSaving: false,
|
|
||||||
isManualConnectionBusy: false,
|
|
||||||
|
|
||||||
// Data persisted to the server.
|
const defaultTransient = {
|
||||||
data: {
|
isReady: false,
|
||||||
completed: false,
|
|
||||||
step: 0,
|
|
||||||
useSandbox: false,
|
|
||||||
useManualConnection: false,
|
|
||||||
clientId: '',
|
|
||||||
clientSecret: '',
|
|
||||||
isCasualSeller: null, // null value will uncheck both options in the UI.
|
|
||||||
products: [],
|
|
||||||
},
|
|
||||||
|
|
||||||
// Read only values, provided by the server.
|
// Read only values, provided by the server.
|
||||||
flags: {
|
flags: {
|
||||||
|
@ -25,83 +23,41 @@ const defaultState = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export const onboardingReducer = (
|
const defaultPersistent = {
|
||||||
state = defaultState,
|
completed: false,
|
||||||
{ type, ...action }
|
step: 0,
|
||||||
) => {
|
isCasualSeller: null, // null value will uncheck both options in the UI.
|
||||||
const setTransient = ( changes ) => {
|
areOptionalPaymentMethodsEnabled: true,
|
||||||
const { data, ...transientChanges } = changes;
|
products: [],
|
||||||
return { ...state, ...transientChanges };
|
|
||||||
};
|
|
||||||
|
|
||||||
const setPersistent = ( changes ) => {
|
|
||||||
const validChanges = Object.keys( changes ).reduce( ( acc, key ) => {
|
|
||||||
if ( key in defaultState.data ) {
|
|
||||||
acc[ key ] = changes[ key ];
|
|
||||||
}
|
|
||||||
return acc;
|
|
||||||
}, {} );
|
|
||||||
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
data: { ...state.data, ...validChanges },
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
switch ( type ) {
|
|
||||||
// Reset store to initial state.
|
|
||||||
case ACTION_TYPES.RESET_ONBOARDING:
|
|
||||||
return setPersistent( defaultState.data );
|
|
||||||
|
|
||||||
// Transient data.
|
|
||||||
case ACTION_TYPES.SET_ONBOARDING_IS_READY:
|
|
||||||
return setTransient( { isReady: action.isReady } );
|
|
||||||
|
|
||||||
case ACTION_TYPES.SET_IS_SAVING_ONBOARDING:
|
|
||||||
return setTransient( { isSaving: action.isSaving } );
|
|
||||||
|
|
||||||
case ACTION_TYPES.SET_MANUAL_CONNECTION_BUSY:
|
|
||||||
return setTransient( { isManualConnectionBusy: action.isBusy } );
|
|
||||||
|
|
||||||
// Persistent data.
|
|
||||||
case ACTION_TYPES.SET_ONBOARDING_DETAILS:
|
|
||||||
const newState = setPersistent( action.payload.data );
|
|
||||||
|
|
||||||
if ( action.payload.flags ) {
|
|
||||||
newState.flags = { ...newState.flags, ...action.payload.flags };
|
|
||||||
}
|
|
||||||
|
|
||||||
return newState;
|
|
||||||
|
|
||||||
case ACTION_TYPES.SET_ONBOARDING_COMPLETED:
|
|
||||||
return setPersistent( { completed: action.completed } );
|
|
||||||
|
|
||||||
case ACTION_TYPES.SET_CLIENT_ID:
|
|
||||||
return setPersistent( { clientId: action.clientId } );
|
|
||||||
|
|
||||||
case ACTION_TYPES.SET_CLIENT_SECRET:
|
|
||||||
return setPersistent( { clientSecret: action.clientSecret } );
|
|
||||||
|
|
||||||
case ACTION_TYPES.SET_ONBOARDING_STEP:
|
|
||||||
return setPersistent( { step: action.step } );
|
|
||||||
|
|
||||||
case ACTION_TYPES.SET_SANDBOX_MODE:
|
|
||||||
return setPersistent( { useSandbox: action.useSandbox } );
|
|
||||||
|
|
||||||
case ACTION_TYPES.SET_MANUAL_CONNECTION_MODE:
|
|
||||||
return setPersistent( {
|
|
||||||
useManualConnection: action.useManualConnection,
|
|
||||||
} );
|
|
||||||
|
|
||||||
case ACTION_TYPES.SET_IS_CASUAL_SELLER:
|
|
||||||
return setPersistent( { isCasualSeller: action.isCasualSeller } );
|
|
||||||
|
|
||||||
case ACTION_TYPES.SET_PRODUCTS:
|
|
||||||
return setPersistent( { products: action.products } );
|
|
||||||
|
|
||||||
default:
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Reducer logic.
|
||||||
|
|
||||||
|
const [ setTransient, setPersistent ] = createSetters(
|
||||||
|
defaultTransient,
|
||||||
|
defaultPersistent
|
||||||
|
);
|
||||||
|
|
||||||
|
const onboardingReducer = createReducer( defaultTransient, defaultPersistent, {
|
||||||
|
[ ACTION_TYPES.SET_TRANSIENT ]: ( state, payload ) =>
|
||||||
|
setTransient( state, payload ),
|
||||||
|
|
||||||
|
[ ACTION_TYPES.SET_PERSISTENT ]: ( state, payload ) =>
|
||||||
|
setPersistent( state, payload ),
|
||||||
|
|
||||||
|
[ ACTION_TYPES.RESET ]: ( state ) =>
|
||||||
|
setPersistent( state, defaultPersistent ),
|
||||||
|
|
||||||
|
[ ACTION_TYPES.HYDRATE ]: ( state, payload ) => {
|
||||||
|
const newState = setPersistent( state, payload.data );
|
||||||
|
|
||||||
|
// Flags are not updated by `setPersistent()`.
|
||||||
|
if ( payload.flags ) {
|
||||||
|
newState.flags = { ...newState.flags, ...payload.flags };
|
||||||
|
}
|
||||||
|
|
||||||
|
return newState;
|
||||||
|
},
|
||||||
|
} );
|
||||||
|
|
||||||
export default onboardingReducer;
|
export default onboardingReducer;
|
||||||
|
|
|
@ -1,25 +1,36 @@
|
||||||
|
/**
|
||||||
|
* Resolvers: Handle asynchronous data fetching for the store.
|
||||||
|
*
|
||||||
|
* These functions update store state with data from external sources.
|
||||||
|
* Each resolver corresponds to a specific selector (selector with same name must exist).
|
||||||
|
* Resolvers are called automatically when selectors request unavailable data.
|
||||||
|
*
|
||||||
|
* @file
|
||||||
|
*/
|
||||||
|
|
||||||
import { dispatch } from '@wordpress/data';
|
import { dispatch } from '@wordpress/data';
|
||||||
import { __ } from '@wordpress/i18n';
|
import { __ } from '@wordpress/i18n';
|
||||||
import { apiFetch } from '@wordpress/data-controls';
|
import { apiFetch } from '@wordpress/data-controls';
|
||||||
import { NAMESPACE } from '../constants';
|
|
||||||
import { setIsReady, setOnboardingDetails } from './actions';
|
|
||||||
|
|
||||||
/**
|
import { STORE_NAME, REST_HYDRATE_PATH } from './constants';
|
||||||
* Retrieve settings from the site's REST API.
|
|
||||||
*/
|
|
||||||
export function* getPersistentData() {
|
|
||||||
const path = `${ NAMESPACE }/onboarding`;
|
|
||||||
|
|
||||||
try {
|
export const resolvers = {
|
||||||
const result = yield apiFetch( { path } );
|
/**
|
||||||
yield setOnboardingDetails( result );
|
* Retrieve settings from the site's REST API.
|
||||||
yield setIsReady( true );
|
*/
|
||||||
} catch ( e ) {
|
*persistentData() {
|
||||||
yield dispatch( 'core/notices' ).createErrorNotice(
|
try {
|
||||||
__(
|
const result = yield apiFetch( { path: REST_HYDRATE_PATH } );
|
||||||
'Error retrieving onboarding details.',
|
|
||||||
'woocommerce-paypal-payments'
|
yield dispatch( STORE_NAME ).hydrate( result );
|
||||||
)
|
yield dispatch( STORE_NAME ).setIsReady( true );
|
||||||
);
|
} catch ( e ) {
|
||||||
}
|
yield dispatch( 'core/notices' ).createErrorNotice(
|
||||||
}
|
__(
|
||||||
|
'Error retrieving onboarding details.',
|
||||||
|
'woocommerce-paypal-payments'
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
|
@ -1,22 +1,25 @@
|
||||||
|
/**
|
||||||
|
* Selectors: Extract specific pieces of state from the store.
|
||||||
|
*
|
||||||
|
* These functions provide a consistent interface for accessing store data.
|
||||||
|
* They allow components to retrieve data without knowing the store structure.
|
||||||
|
*
|
||||||
|
* @file
|
||||||
|
*/
|
||||||
|
|
||||||
const EMPTY_OBJ = Object.freeze( {} );
|
const EMPTY_OBJ = Object.freeze( {} );
|
||||||
|
|
||||||
const getOnboardingState = ( state ) => {
|
const getState = ( state ) => state || EMPTY_OBJ;
|
||||||
if ( ! state ) {
|
|
||||||
return EMPTY_OBJ;
|
|
||||||
}
|
|
||||||
|
|
||||||
return state.onboarding || EMPTY_OBJ;
|
export const persistentData = ( state ) => {
|
||||||
|
return getState( state ).data || EMPTY_OBJ;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getPersistentData = ( state ) => {
|
export const transientData = ( state ) => {
|
||||||
return getOnboardingState( state ).data || EMPTY_OBJ;
|
const { data, flags, ...transientState } = getState( state );
|
||||||
};
|
|
||||||
|
|
||||||
export const getTransientData = ( state ) => {
|
|
||||||
const { data, flags, ...transientState } = getOnboardingState( state );
|
|
||||||
return transientState || EMPTY_OBJ;
|
return transientState || EMPTY_OBJ;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getFlags = ( state ) => {
|
export const flags = ( state ) => {
|
||||||
return getOnboardingState( state ).flags || EMPTY_OBJ;
|
return getState( state ).flags || EMPTY_OBJ;
|
||||||
};
|
};
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue