diff --git a/modules/ppcp-paylater-configurator/src/PayLaterConfiguratorModule.php b/modules/ppcp-paylater-configurator/src/PayLaterConfiguratorModule.php index 2c13bed71..8e46bcf33 100644 --- a/modules/ppcp-paylater-configurator/src/PayLaterConfiguratorModule.php +++ b/modules/ppcp-paylater-configurator/src/PayLaterConfiguratorModule.php @@ -9,9 +9,11 @@ namespace WooCommerce\PayPalCommerce\PayLaterConfigurator; +use WooCommerce\PayPalCommerce\Onboarding\State; use WooCommerce\PayPalCommerce\PayLaterConfigurator\Endpoint\GetConfig; use WooCommerce\PayPalCommerce\PayLaterConfigurator\Endpoint\SaveConfig; use WooCommerce\PayPalCommerce\PayLaterConfigurator\Factory\ConfigFactory; +use WooCommerce\PayPalCommerce\Settings\Data\OnboardingProfile; use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ExecutableModule; use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ExtendingModule; use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ModuleClassNameIdTrait; @@ -68,8 +70,9 @@ static function () use ( $c ) { $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' ); + $onboarding_profile = $c->get( 'settings.data.onboarding' ); - self::add_paylater_update_notice( $messaging_locations, $is_wc_settings_page, $current_page_id ); + self::add_paylater_update_notice( $messaging_locations, $is_wc_settings_page, $current_page_id, $onboarding_profile ); $settings = $c->get( 'wcgateway.settings' ); assert( $settings instanceof Settings ); @@ -159,13 +162,19 @@ static function () use ( $c ) { * The notice appears on any PayPal-Settings page, except for the Pay-Later settings page, * when no Pay-Later messaging is used yet. * - * @param array $message_locations PayLater messaging locations. - * @param bool $is_settings_page Whether the current page is a WC settings page. - * @param string $current_page_id ID of current settings page tab. + * @param array $message_locations PayLater messaging locations. + * @param bool $is_settings_page Whether the current page is a WC settings page. + * @param string $current_page_id ID of current settings page tab. + * @param OnboardingProfile $onboarding_profile Onboarding profile. * * @return void */ - private static 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, OnboardingProfile $onboarding_profile ) : void { + // Don't display the notice if the user has not completed the onboarding process. + if ( $onboarding_profile->get_completed() !== true ) { + return; + } + // 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 ) { return; diff --git a/modules/ppcp-settings/resources/js/Components/Screens/Overview/TabPayLaterMessaging.js b/modules/ppcp-settings/resources/js/Components/Screens/Overview/TabPayLaterMessaging.js new file mode 100644 index 000000000..b388a6bee --- /dev/null +++ b/modules/ppcp-settings/resources/js/Components/Screens/Overview/TabPayLaterMessaging.js @@ -0,0 +1,5 @@ +const TabPayLaterMessaging = () => { + return
; +}; + +export default TabPayLaterMessaging; diff --git a/modules/ppcp-settings/resources/js/Components/Screens/SendOnlyMessage.js b/modules/ppcp-settings/resources/js/Components/Screens/SendOnlyMessage.js new file mode 100644 index 000000000..56d780250 --- /dev/null +++ b/modules/ppcp-settings/resources/js/Components/Screens/SendOnlyMessage.js @@ -0,0 +1,54 @@ +import { __, sprintf } from '@wordpress/i18n'; + +import Container from '../ReusableComponents/Container'; +import SettingsCard from '../ReusableComponents/SettingsCard'; +import SettingsNavigation from './SettingsNavigation'; + +const SendOnlyMessage = () => { + const settingsPageUrl = '/wp-admin/admin.php?page=wc-settings'; + + return ( + <> + + + +

+ { __( + 'Your current WooCommerce store location is in a "send-only" country, according to PayPal\'s policies', + 'woocommerce-paypal-payments' + ) } +

+

+ { __( + 'Since receiving payments is essential for using the PayPal Payments extension, you are unable to connect your PayPal account while operating from a "send-only" country.', + 'woocommerce-paypal-payments' + ) } +

+

WooCommerce store location to a supported region and connect a PayPal account eligible for receiving payments.', + 'woocommerce-paypal-payments' + ), + settingsPageUrl + ), + } } + /> + + + + ); +}; + +export default SendOnlyMessage; diff --git a/modules/ppcp-settings/resources/js/Components/Screens/Settings.js b/modules/ppcp-settings/resources/js/Components/Screens/Settings.js index bc79b34b3..128884f10 100644 --- a/modules/ppcp-settings/resources/js/Components/Screens/Settings.js +++ b/modules/ppcp-settings/resources/js/Components/Screens/Settings.js @@ -7,9 +7,15 @@ import SpinnerOverlay from '../ReusableComponents/SpinnerOverlay'; import Onboarding from './Onboarding/Onboarding'; import SettingsScreen from './SettingsScreen'; +import { useMerchantInfo } from '../../data/common/hooks'; +import SendOnlyMessage from './SendOnlyMessage'; const Settings = () => { const onboardingProgress = OnboardingHooks.useSteps(); + const { + isReady: merchantIsReady, + merchant: { isSendOnlyCountry }, + } = useMerchantInfo(); // Disable the "Changes you made might not be saved" browser warning. useEffect( () => { @@ -30,7 +36,7 @@ const Settings = () => { } ); const Content = useMemo( () => { - if ( ! onboardingProgress.isReady ) { + if ( ! onboardingProgress.isReady || ! merchantIsReady ) { return ( { ); } + if ( isSendOnlyCountry ) { + return ; + } + if ( ! onboardingProgress.completed ) { return ; } return ; - }, [ onboardingProgress ] ); + }, [ + isSendOnlyCountry, + merchantIsReady, + onboardingProgress.completed, + onboardingProgress.isReady, + ] ); return

{ Content }
; }; diff --git a/modules/ppcp-settings/resources/js/Components/Screens/tabs.js b/modules/ppcp-settings/resources/js/Components/Screens/tabs.js index c2f3b25e6..e828dab9f 100644 --- a/modules/ppcp-settings/resources/js/Components/Screens/tabs.js +++ b/modules/ppcp-settings/resources/js/Components/Screens/tabs.js @@ -3,6 +3,7 @@ import TabOverview from './Overview/TabOverview'; import TabPaymentMethods from './Overview/TabPaymentMethods'; import TabSettings from './Overview/TabSettings'; import TabStyling from './Overview/TabStyling'; +import TabPayLaterMessaging from './Overview/TabPayLaterMessaging'; export const getSettingsTabs = () => { const tabs = []; @@ -31,5 +32,11 @@ export const getSettingsTabs = () => { component: , } ); + tabs.push( { + name: 'pay-later-messaging', + title: __( 'Pay Later Messaging', 'woocommerce-paypal-payments' ), + component: , + } ); + return tabs; }; diff --git a/modules/ppcp-settings/resources/js/data/common/hooks.js b/modules/ppcp-settings/resources/js/data/common/hooks.js index 4aea08caa..8fcf3f6a9 100644 --- a/modules/ppcp-settings/resources/js/data/common/hooks.js +++ b/modules/ppcp-settings/resources/js/data/common/hooks.js @@ -144,7 +144,7 @@ export const useWebhooks = () => { }; }; export const useMerchantInfo = () => { - const { merchant, features } = useHooks(); + const { isReady, merchant, features } = useHooks(); const { refreshMerchantData } = useDispatch( STORE_NAME ); const verifyLoginStatus = useCallback( async () => { @@ -159,6 +159,7 @@ export const useMerchantInfo = () => { }, [ refreshMerchantData, merchant ] ); return { + isReady, merchant, // Merchant details features, // Eligible merchant features verifyLoginStatus, // Callback diff --git a/modules/ppcp-settings/resources/js/utils/tabSelector.js b/modules/ppcp-settings/resources/js/utils/tabSelector.js index c8b1c5350..5c7105ffc 100644 --- a/modules/ppcp-settings/resources/js/utils/tabSelector.js +++ b/modules/ppcp-settings/resources/js/utils/tabSelector.js @@ -4,6 +4,7 @@ export const TAB_IDS = { PAYMENT_METHODS: 'tab-panel-0-payment-methods', SETTINGS: 'tab-panel-0-settings', STYLING: 'tab-panel-0-styling', + PAY_LATER_MESSAGING: 'tab-panel-0-pay-later-messaging', }; /** diff --git a/modules/ppcp-settings/services.php b/modules/ppcp-settings/services.php index 3c41cd833..6fc9d67e3 100644 --- a/modules/ppcp-settings/services.php +++ b/modules/ppcp-settings/services.php @@ -61,6 +61,7 @@ return new GeneralSettings( $container->get( 'api.shop.country' ), $container->get( 'api.shop.currency.getter' )->get(), + $container->get( 'wcgateway.is-send-only-country' ) ); }, 'settings.rest.onboarding' => static function ( ContainerInterface $container ) : OnboardingRestEndpoint { diff --git a/modules/ppcp-settings/src/Data/GeneralSettings.php b/modules/ppcp-settings/src/Data/GeneralSettings.php index fa0e653a1..94e8a380f 100644 --- a/modules/ppcp-settings/src/Data/GeneralSettings.php +++ b/modules/ppcp-settings/src/Data/GeneralSettings.php @@ -40,18 +40,21 @@ class GeneralSettings extends AbstractDataModel { /** * Constructor. * - * @param string $country WooCommerce store country. - * @param string $currency WooCommerce store currency. + * @param string $country WooCommerce store country. + * @param string $currency WooCommerce store currency. + * @param bool $is_send_only_country Whether the store's country is classified as a send-only + * country. * * @throws RuntimeException When forgetting to define the OPTION_KEY in this class. */ - public function __construct( string $country, string $currency ) { + public function __construct( string $country, string $currency, bool $is_send_only_country ) { parent::__construct(); $this->woo_settings['country'] = $country; $this->woo_settings['currency'] = $currency; - $this->data['merchant_connected'] = $this->is_merchant_connected(); + $this->data['is_send_only_country'] = $is_send_only_country; + $this->data['merchant_connected'] = $this->is_merchant_connected(); } /** @@ -63,6 +66,7 @@ protected function get_defaults() : array { return array( 'use_sandbox' => false, // UI state, not a connection detail. 'use_manual_connection' => false, // UI state, not a connection detail. + 'is_send_only_country' => false, // Read-only flag. // Details about connected merchant account. 'merchant_connected' => false, diff --git a/modules/ppcp-settings/src/Endpoint/CommonRestEndpoint.php b/modules/ppcp-settings/src/Endpoint/CommonRestEndpoint.php index 6d85c1185..d99204c80 100644 --- a/modules/ppcp-settings/src/Endpoint/CommonRestEndpoint.php +++ b/modules/ppcp-settings/src/Endpoint/CommonRestEndpoint.php @@ -61,24 +61,27 @@ class CommonRestEndpoint extends RestEndpoint { * @var array */ private array $merchant_info_map = array( - 'merchant_connected' => array( + 'merchant_connected' => array( 'js_name' => 'isConnected', ), - 'sandbox_merchant' => array( + 'sandbox_merchant' => array( 'js_name' => 'isSandbox', ), - 'merchant_id' => array( + 'merchant_id' => array( 'js_name' => 'id', ), - 'merchant_email' => array( + 'merchant_email' => array( 'js_name' => 'email', ), - 'client_id' => array( + 'client_id' => array( 'js_name' => 'clientId', ), - 'client_secret' => array( + 'client_secret' => array( 'js_name' => 'clientSecret', ), + 'is_send_only_country' => array( + 'js_name' => 'isSendOnlyCountry', + ), ); /** @@ -187,40 +190,6 @@ public function get_merchant_details() : WP_REST_Response { return $this->return_success( $js_data, $extra_data ); } - /** - * Returns mocked merchant data until real data fetching is implemented. - * - * @return array Mocked merchant details including connection status, features, etc. - */ - protected function get_mocked_merchant_data(): array { - return array( - 'isConnected' => true, - 'isSandbox' => false, - 'id' => '', - 'email' => '', - 'features' => array( - 'save_paypal_and_venmo' => array( - 'enabled' => true, - ), - 'advanced_credit_and_debit_cards' => array( - 'enabled' => true, - ), - 'alternative_payment_methods' => array( - 'enabled' => true, - ), - 'google_pay' => array( - 'enabled' => true, - ), - 'apple_pay' => array( - 'enabled' => true, - ), - 'pay_later_messaging' => array( - 'enabled' => true, - ), - ), - ); - } - /** * Appends the "merchant" attribute to the extra_data collection, which * contains details about the merchant's PayPal account, like the merchant ID. @@ -229,7 +198,7 @@ protected function get_mocked_merchant_data(): array { * * @return array Updated extra_data collection. */ - protected function add_merchant_info( array $extra_data ): array { + protected function add_merchant_info( array $extra_data ) : array { $extra_data['merchant'] = $this->sanitize_for_javascript( $this->settings->to_array(), $this->merchant_info_map @@ -242,11 +211,6 @@ protected function add_merchant_info( array $extra_data ): array { ); } - // If no real data is available yet, use mock data. - if ( empty( $extra_data['merchant'] ) || ( empty( $extra_data['merchant']['id'] ) && empty( $extra_data['merchant']['email'] ) ) ) { - $extra_data['merchant'] = $this->get_mocked_merchant_data(); - } - return $extra_data; } diff --git a/modules/ppcp-wc-gateway/services.php b/modules/ppcp-wc-gateway/services.php index 9447c981e..e17c1077d 100644 --- a/modules/ppcp-wc-gateway/services.php +++ b/modules/ppcp-wc-gateway/services.php @@ -343,9 +343,10 @@ static function ( ContainerInterface $container ): Settings { } ), 'wcgateway.notice.connect' => static function ( ContainerInterface $container ): ConnectAdminNotice { - $state = $container->get( 'onboarding.state' ); - $settings = $container->get( 'wcgateway.settings' ); - return new ConnectAdminNotice( $state, $settings ); + $state = $container->get( 'onboarding.state' ); + $settings = $container->get( 'wcgateway.settings' ); + $is_current_country_send_only = $container->get( 'wcgateway.is-send-only-country' ); + return new ConnectAdminNotice( $state, $settings, $is_current_country_send_only ); }, 'wcgateway.notice.currency-unsupported' => static function ( ContainerInterface $container ): UnsupportedCurrencyAdminNotice { $state = $container->get( 'onboarding.state' ); diff --git a/modules/ppcp-wc-gateway/src/Notice/ConnectAdminNotice.php b/modules/ppcp-wc-gateway/src/Notice/ConnectAdminNotice.php index e8d88adec..60085a992 100644 --- a/modules/ppcp-wc-gateway/src/Notice/ConnectAdminNotice.php +++ b/modules/ppcp-wc-gateway/src/Notice/ConnectAdminNotice.php @@ -33,15 +33,24 @@ class ConnectAdminNotice { */ private $settings; + /** + * Whether the current store's country is classified as a send-only country.. + * + * @var bool + */ + private bool $is_current_country_send_only; + /** * ConnectAdminNotice constructor. * * @param State $state The state. * @param ContainerInterface $settings The settings. + * @param bool $is_current_country_send_only Whether the current store's country is classified as a send-only country. */ - public function __construct( State $state, ContainerInterface $settings ) { - $this->state = $state; - $this->settings = $settings; + public function __construct( State $state, ContainerInterface $settings, bool $is_current_country_send_only ) { + $this->state = $state; + $this->settings = $settings; + $this->is_current_country_send_only = $is_current_country_send_only; } /** @@ -71,6 +80,6 @@ public function connect_message() { * @return bool */ protected function should_display(): bool { - return $this->state->current_state() !== State::STATE_ONBOARDED; + return $this->state->current_state() !== State::STATE_ONBOARDED && $this->is_current_country_send_only === false; } }