From 42f3e575bc9789b3b611e7ff9a182fc17e24a921 Mon Sep 17 00:00:00 2001 From: Pedro Silva Date: Fri, 2 Feb 2024 17:16:42 +0000 Subject: [PATCH 1/3] Fix inconsistent instance of AppleProductStatus --- modules/ppcp-applepay/services.php | 19 +++++++++++-------- .../src/Settings/SettingsListener.php | 3 ++- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/modules/ppcp-applepay/services.php b/modules/ppcp-applepay/services.php index e12298179..2a2fb7abd 100644 --- a/modules/ppcp-applepay/services.php +++ b/modules/ppcp-applepay/services.php @@ -18,6 +18,7 @@ use WooCommerce\PayPalCommerce\Applepay\Assets\BlocksPaymentMethod; use WooCommerce\PayPalCommerce\Applepay\Assets\PropertiesDictionary; use WooCommerce\PayPalCommerce\Applepay\Helper\ApmApplies; use WooCommerce\PayPalCommerce\Applepay\Helper\AvailabilityNotice; +use WooCommerce\PayPalCommerce\Common\Pattern\SingletonDecorator; use WooCommerce\PayPalCommerce\Onboarding\Environment; use WooCommerce\PayPalCommerce\Onboarding\State; use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface; @@ -72,14 +73,16 @@ return array( return $settings->has( 'applepay_validated' ) ? $settings->get( 'applepay_validated' ) === true : false; }, - 'applepay.apple-product-status' => static function( ContainerInterface $container ): AppleProductStatus { - return new AppleProductStatus( - $container->get( 'wcgateway.settings' ), - $container->get( 'api.endpoint.partners' ), - $container->get( 'onboarding.state' ), - $container->get( 'api.helper.failure-registry' ) - ); - }, + 'applepay.apple-product-status' => SingletonDecorator::make( + static function( ContainerInterface $container ): AppleProductStatus { + return new AppleProductStatus( + $container->get( 'wcgateway.settings' ), + $container->get( 'api.endpoint.partners' ), + $container->get( 'onboarding.state' ), + $container->get( 'api.helper.failure-registry' ) + ); + } + ), 'applepay.available' => static function ( ContainerInterface $container ): bool { if ( apply_filters( 'woocommerce_paypal_payments_applepay_validate_product_status', true ) ) { $status = $container->get( 'applepay.apple-product-status' ); diff --git a/modules/ppcp-wc-gateway/src/Settings/SettingsListener.php b/modules/ppcp-wc-gateway/src/Settings/SettingsListener.php index 5f1bd38ad..35ff96fff 100644 --- a/modules/ppcp-wc-gateway/src/Settings/SettingsListener.php +++ b/modules/ppcp-wc-gateway/src/Settings/SettingsListener.php @@ -346,9 +346,10 @@ class SettingsListener { /** * Prevent enabling both Pay Later messaging and PayPal vaulting * + * @return void * @throws RuntimeException When API request fails. */ - public function listen_for_vaulting_enabled() { + public function listen_for_vaulting_enabled(): void { if ( ! $this->is_valid_site_request() || State::STATE_ONBOARDED !== $this->state->current_state() ) { return; } From e37177725e28fa903e00728ad96c8ef324338c04 Mon Sep 17 00:00:00 2001 From: Pedro Silva Date: Tue, 13 Feb 2024 15:04:08 +0000 Subject: [PATCH 2/3] Add filters to override ApplePay and GooglePay product status checks. --- modules/ppcp-applepay/src/Assets/AppleProductStatus.php | 5 +++++ modules/ppcp-googlepay/src/Helper/ApmProductStatus.php | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/modules/ppcp-applepay/src/Assets/AppleProductStatus.php b/modules/ppcp-applepay/src/Assets/AppleProductStatus.php index 2c00ba59e..5bef7b933 100644 --- a/modules/ppcp-applepay/src/Assets/AppleProductStatus.php +++ b/modules/ppcp-applepay/src/Assets/AppleProductStatus.php @@ -100,6 +100,11 @@ class AppleProductStatus { return false; } + $status_override = apply_filters( 'woocommerce_paypal_payments_apple_pay_product_status', null ); + if ( null !== $status_override ) { + return $status_override; + } + // If status was already checked on this request return the same result. if ( null !== $this->current_status ) { return $this->current_status; diff --git a/modules/ppcp-googlepay/src/Helper/ApmProductStatus.php b/modules/ppcp-googlepay/src/Helper/ApmProductStatus.php index cf1e6487c..866c6538f 100644 --- a/modules/ppcp-googlepay/src/Helper/ApmProductStatus.php +++ b/modules/ppcp-googlepay/src/Helper/ApmProductStatus.php @@ -100,6 +100,11 @@ class ApmProductStatus { return false; } + $status_override = apply_filters( 'woocommerce_paypal_payments_google_pay_product_status', null ); + if ( null !== $status_override ) { + return $status_override; + } + // If status was already checked on this request return the same result. if ( null !== $this->current_status ) { return $this->current_status; From 4a98c018838aeeb750e9de4a7510d1fad8eb4bcd Mon Sep 17 00:00:00 2001 From: Pedro Silva Date: Wed, 14 Feb 2024 11:20:49 +0000 Subject: [PATCH 3/3] Fix checking of ApplePay and GooglePay product status capabilities --- .../src/Entity/SellerStatus.php | 43 ++++++++++- .../src/Entity/SellerStatusCapability.php | 77 +++++++++++++++++++ .../src/Factory/SellerStatusFactory.php | 14 +++- .../src/Assets/AppleProductStatus.php | 24 ++++-- .../src/Helper/ApmProductStatus.php | 24 ++++-- 5 files changed, 165 insertions(+), 17 deletions(-) create mode 100644 modules/ppcp-api-client/src/Entity/SellerStatusCapability.php diff --git a/modules/ppcp-api-client/src/Entity/SellerStatus.php b/modules/ppcp-api-client/src/Entity/SellerStatus.php index 9f7822615..5b972efc7 100644 --- a/modules/ppcp-api-client/src/Entity/SellerStatus.php +++ b/modules/ppcp-api-client/src/Entity/SellerStatus.php @@ -21,19 +21,37 @@ class SellerStatus { */ private $products; + /** + * The capabilities. + * + * @var SellerStatusCapability[] + */ + private $capabilities; + /** * SellerStatus constructor. * - * @param SellerStatusProduct[] $products The products. + * @param SellerStatusProduct[] $products The products. + * @param SellerStatusCapability[] $capabilities The capabilities. + * + * @psalm-suppress RedundantConditionGivenDocblockType */ - public function __construct( array $products ) { + public function __construct( array $products, array $capabilities ) { foreach ( $products as $key => $product ) { if ( is_a( $product, SellerStatusProduct::class ) ) { continue; } unset( $products[ $key ] ); } - $this->products = $products; + foreach ( $capabilities as $key => $capability ) { + if ( is_a( $capability, SellerStatusCapability::class ) ) { + continue; + } + unset( $capabilities[ $key ] ); + } + + $this->products = $products; + $this->capabilities = $capabilities; } /** @@ -45,6 +63,15 @@ class SellerStatus { return $this->products; } + /** + * Returns the capabilities. + * + * @return SellerStatusCapability[] + */ + public function capabilities() : array { + return $this->capabilities; + } + /** * Returns the enitity as array. * @@ -58,8 +85,16 @@ class SellerStatus { $this->products() ); + $capabilities = array_map( + function( SellerStatusCapability $capability ) : array { + return $capability->to_array(); + }, + $this->capabilities() + ); + return array( - 'products' => $products, + 'products' => $products, + 'capabilities' => $capabilities, ); } } diff --git a/modules/ppcp-api-client/src/Entity/SellerStatusCapability.php b/modules/ppcp-api-client/src/Entity/SellerStatusCapability.php new file mode 100644 index 000000000..7fdb7df04 --- /dev/null +++ b/modules/ppcp-api-client/src/Entity/SellerStatusCapability.php @@ -0,0 +1,77 @@ +name = $name; + $this->status = $status; + } + + /** + * Returns the name of the product. + * + * @return string + */ + public function name() : string { + return $this->name; + } + + /** + * Returns the status for this capability. + * + * @return string + */ + public function status() : string { + return $this->status; + } + + /** + * Returns the entity as array. + * + * @return array + */ + public function to_array() : array { + return array( + 'name' => $this->name(), + 'status' => $this->status(), + ); + } + +} diff --git a/modules/ppcp-api-client/src/Factory/SellerStatusFactory.php b/modules/ppcp-api-client/src/Factory/SellerStatusFactory.php index 8b723a60f..9f1ff31f4 100644 --- a/modules/ppcp-api-client/src/Factory/SellerStatusFactory.php +++ b/modules/ppcp-api-client/src/Factory/SellerStatusFactory.php @@ -11,6 +11,7 @@ namespace WooCommerce\PayPalCommerce\ApiClient\Factory; use WooCommerce\PayPalCommerce\ApiClient\Entity\SellerStatus; use WooCommerce\PayPalCommerce\ApiClient\Entity\SellerStatusProduct; +use WooCommerce\PayPalCommerce\ApiClient\Entity\SellerStatusCapability; /** * Class SellerStatusFactory @@ -37,6 +38,17 @@ class SellerStatusFactory { isset( $json->products ) ? (array) $json->products : array() ); - return new SellerStatus( $products ); + $capabilities = array_map( + function( $json ) : SellerStatusCapability { + $capability = new SellerStatusCapability( + isset( $json->name ) ? (string) $json->name : '', + isset( $json->status ) ? (string) $json->status : '' + ); + return $capability; + }, + isset( $json->capabilities ) ? (array) $json->capabilities : array() + ); + + return new SellerStatus( $products, $capabilities ); } } diff --git a/modules/ppcp-applepay/src/Assets/AppleProductStatus.php b/modules/ppcp-applepay/src/Assets/AppleProductStatus.php index 5bef7b933..d5409ddaf 100644 --- a/modules/ppcp-applepay/src/Assets/AppleProductStatus.php +++ b/modules/ppcp-applepay/src/Assets/AppleProductStatus.php @@ -11,6 +11,7 @@ namespace WooCommerce\PayPalCommerce\Applepay\Assets; use Throwable; use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PartnersEndpoint; +use WooCommerce\PayPalCommerce\ApiClient\Entity\SellerStatusCapability; use WooCommerce\PayPalCommerce\ApiClient\Helper\FailureRegistry; use WooCommerce\PayPalCommerce\Onboarding\State; use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings; @@ -133,21 +134,32 @@ class AppleProductStatus { } // Check the seller status for the intended capability. + $has_capability = false; foreach ( $seller_status->products() as $product ) { if ( $product->name() !== 'PAYMENT_METHODS' ) { continue; } if ( in_array( self::CAPABILITY_NAME, $product->capabilities(), true ) ) { - // Capability found, persist status and return true. - $this->settings->set( self::SETTINGS_KEY, self::SETTINGS_VALUE_ENABLED ); - $this->settings->persist(); - - $this->current_status = true; - return $this->current_status; + $has_capability = true; } } + foreach ( $seller_status->capabilities() as $capability ) { + if ( $capability->name() === self::CAPABILITY_NAME && $capability->status() === SellerStatusCapability::STATUS_ACTIVE ) { + $has_capability = true; + } + } + + if ( $has_capability ) { + // Capability found, persist status and return true. + $this->settings->set( self::SETTINGS_KEY, self::SETTINGS_VALUE_ENABLED ); + $this->settings->persist(); + + $this->current_status = true; + return $this->current_status; + } + // Capability not found, persist status and return false. $this->settings->set( self::SETTINGS_KEY, self::SETTINGS_VALUE_DISABLED ); $this->settings->persist(); diff --git a/modules/ppcp-googlepay/src/Helper/ApmProductStatus.php b/modules/ppcp-googlepay/src/Helper/ApmProductStatus.php index 866c6538f..3639a1717 100644 --- a/modules/ppcp-googlepay/src/Helper/ApmProductStatus.php +++ b/modules/ppcp-googlepay/src/Helper/ApmProductStatus.php @@ -11,6 +11,7 @@ namespace WooCommerce\PayPalCommerce\Googlepay\Helper; use Throwable; use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PartnersEndpoint; +use WooCommerce\PayPalCommerce\ApiClient\Entity\SellerStatusCapability; use WooCommerce\PayPalCommerce\ApiClient\Helper\FailureRegistry; use WooCommerce\PayPalCommerce\Onboarding\State; use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings; @@ -133,21 +134,32 @@ class ApmProductStatus { } // Check the seller status for the intended capability. + $has_capability = false; foreach ( $seller_status->products() as $product ) { if ( $product->name() !== 'PAYMENT_METHODS' ) { continue; } if ( in_array( self::CAPABILITY_NAME, $product->capabilities(), true ) ) { - // Capability found, persist status and return true. - $this->settings->set( self::SETTINGS_KEY, self::SETTINGS_VALUE_ENABLED ); - $this->settings->persist(); - - $this->current_status = true; - return $this->current_status; + $has_capability = true; } } + foreach ( $seller_status->capabilities() as $capability ) { + if ( $capability->name() === self::CAPABILITY_NAME && $capability->status() === SellerStatusCapability::STATUS_ACTIVE ) { + $has_capability = true; + } + } + + if ( $has_capability ) { + // Capability found, persist status and return true. + $this->settings->set( self::SETTINGS_KEY, self::SETTINGS_VALUE_ENABLED ); + $this->settings->persist(); + + $this->current_status = true; + return $this->current_status; + } + // Capability not found, persist status and return false. $this->settings->set( self::SETTINGS_KEY, self::SETTINGS_VALUE_DISABLED ); $this->settings->persist();