From 79200965f30973d80cf80ad0a0b36a0191e76240 Mon Sep 17 00:00:00 2001 From: Emili Castells Guasch Date: Tue, 19 Sep 2023 09:58:24 +0200 Subject: [PATCH 1/8] Add module directory --- modules/ppcp-saved-payment-checked/.gitignore | 3 ++ .../ppcp-saved-payment-checked/composer.json | 17 +++++++++++ .../ppcp-saved-payment-checked/extensions.php | 14 ++++++++++ modules/ppcp-saved-payment-checked/module.php | 16 +++++++++++ .../ppcp-saved-payment-checked/services.php | 14 ++++++++++ .../src/SavedPaymentCheckerModule.php | 28 +++++++++++++++++++ 6 files changed, 92 insertions(+) create mode 100644 modules/ppcp-saved-payment-checked/.gitignore create mode 100644 modules/ppcp-saved-payment-checked/composer.json create mode 100644 modules/ppcp-saved-payment-checked/extensions.php create mode 100644 modules/ppcp-saved-payment-checked/module.php create mode 100644 modules/ppcp-saved-payment-checked/services.php create mode 100644 modules/ppcp-saved-payment-checked/src/SavedPaymentCheckerModule.php diff --git a/modules/ppcp-saved-payment-checked/.gitignore b/modules/ppcp-saved-payment-checked/.gitignore new file mode 100644 index 000000000..0bd2b9f58 --- /dev/null +++ b/modules/ppcp-saved-payment-checked/.gitignore @@ -0,0 +1,3 @@ +node_modules +assets/js +assets/css diff --git a/modules/ppcp-saved-payment-checked/composer.json b/modules/ppcp-saved-payment-checked/composer.json new file mode 100644 index 000000000..e84d9213b --- /dev/null +++ b/modules/ppcp-saved-payment-checked/composer.json @@ -0,0 +1,17 @@ +{ + "name": "woocommerce/ppcp-saved-payment-checked", + "type": "dhii-mod", + "description": "Saved payment checker module for PPCP", + "license": "GPL-2.0", + "require": { + "php": "^7.2 | ^8.0", + "dhii/module-interface": "^0.3.0-alpha1" + }, + "autoload": { + "psr-4": { + "WooCommerce\\PayPalCommerce\\SavedPaymentChecker\\": "src" + } + }, + "minimum-stability": "dev", + "prefer-stable": true +} diff --git a/modules/ppcp-saved-payment-checked/extensions.php b/modules/ppcp-saved-payment-checked/extensions.php new file mode 100644 index 000000000..aa36cabb4 --- /dev/null +++ b/modules/ppcp-saved-payment-checked/extensions.php @@ -0,0 +1,14 @@ + Date: Tue, 19 Sep 2023 11:39:35 +0200 Subject: [PATCH 2/8] Add saved payment checked module --- modules.php | 8 +++++ .../src/SavedPaymentCheckerModule.php | 32 ++++++++++++------- 2 files changed, 28 insertions(+), 12 deletions(-) diff --git a/modules.php b/modules.php index 3e03e1c5e..cd8ff00fe 100644 --- a/modules.php +++ b/modules.php @@ -44,5 +44,13 @@ return function ( string $root_dir ): iterable { $modules[] = ( require "$modules_dir/ppcp-googlepay/module.php" )(); } + if ( apply_filters( + //phpcs:disable WordPress.NamingConventions.ValidHookName.UseUnderscores + 'woocommerce.deprecated-flags.woocommerce_paypal_payments.saved_payment_checker_enabled', + getenv( 'PCP_SAVED_PAYMENT_CHECKER_ENABLED' ) === '1' + ) ) { + $modules[] = ( require "$modules_dir/ppcp-saved-payment-checked/module.php" )(); + } + return $modules; }; diff --git a/modules/ppcp-saved-payment-checked/src/SavedPaymentCheckerModule.php b/modules/ppcp-saved-payment-checked/src/SavedPaymentCheckerModule.php index f8f1dbb22..0523fe0a7 100644 --- a/modules/ppcp-saved-payment-checked/src/SavedPaymentCheckerModule.php +++ b/modules/ppcp-saved-payment-checked/src/SavedPaymentCheckerModule.php @@ -1,28 +1,36 @@ Date: Tue, 19 Sep 2023 12:19:31 +0200 Subject: [PATCH 3/8] Move vaulted subscriptions intent logic to module --- .../src/Endpoint/OrderEndpoint.php | 2 +- .../ppcp-button/src/Assets/SmartButton.php | 8 +++---- .../src/SavedPaymentCheckerModule.php | 21 ++++++++++++++++++- 3 files changed, 24 insertions(+), 7 deletions(-) diff --git a/modules/ppcp-api-client/src/Endpoint/OrderEndpoint.php b/modules/ppcp-api-client/src/Endpoint/OrderEndpoint.php index 3b232c7f6..ad2bfea59 100644 --- a/modules/ppcp-api-client/src/Endpoint/OrderEndpoint.php +++ b/modules/ppcp-api-client/src/Endpoint/OrderEndpoint.php @@ -194,7 +194,7 @@ class OrderEndpoint { ): Order { $bearer = $this->bearer->bearer(); $data = array( - 'intent' => ( $this->subscription_helper->cart_contains_subscription() || $this->subscription_helper->current_product_is_subscription() ) ? 'AUTHORIZE' : $this->intent, + 'intent' => apply_filters( 'woocommerce_paypal_payments_saved_payment_subscription_intent', $this->intent ), 'purchase_units' => array_map( static function ( PurchaseUnit $item ) use ( $shipping_preference ): array { $data = $item->to_array(); diff --git a/modules/ppcp-button/src/Assets/SmartButton.php b/modules/ppcp-button/src/Assets/SmartButton.php index ce75d62d1..a0e0b4e32 100644 --- a/modules/ppcp-button/src/Assets/SmartButton.php +++ b/modules/ppcp-button/src/Assets/SmartButton.php @@ -1547,16 +1547,14 @@ class SmartButton implements SmartButtonInterface { * @throws NotFoundException If intent is not found. */ private function intent(): string { - $intent = ( $this->settings->has( 'intent' ) ) ? $this->settings->get( 'intent' ) : 'capture'; - $product_intent = $this->subscription_helper->current_product_is_subscription() ? 'authorize' : $intent; - $other_context_intent = $this->subscription_helper->cart_contains_subscription() ? 'authorize' : $intent; - $subscription_mode = $this->settings->has( 'subscriptions_mode' ) ? $this->settings->get( 'subscriptions_mode' ) : ''; if ( $this->subscription_helper->need_subscription_intent( $subscription_mode ) ) { return 'subscription'; } - return $this->context() === 'product' ? $product_intent : $other_context_intent; + $intent = $this->settings->has( 'intent' ) ? $this->settings->get( 'intent' ) : 'capture'; + + return strtolower( apply_filters( 'woocommerce_paypal_payments_saved_payment_subscription_intent', $intent ) ); } /** diff --git a/modules/ppcp-saved-payment-checked/src/SavedPaymentCheckerModule.php b/modules/ppcp-saved-payment-checked/src/SavedPaymentCheckerModule.php index 0523fe0a7..0d1cf52b4 100644 --- a/modules/ppcp-saved-payment-checked/src/SavedPaymentCheckerModule.php +++ b/modules/ppcp-saved-payment-checked/src/SavedPaymentCheckerModule.php @@ -9,6 +9,7 @@ declare(strict_types=1); namespace WooCommerce\PayPalCommerce\SavedPaymentChecker; +use WooCommerce\PayPalCommerce\Subscription\Helper\SubscriptionHelper; use WooCommerce\PayPalCommerce\Vendor\Dhii\Container\ServiceProvider; use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface; use WooCommerce\PayPalCommerce\Vendor\Interop\Container\ServiceProviderInterface; @@ -32,5 +33,23 @@ class SavedPaymentCheckerModule implements ModuleInterface { /** * {@inheritDoc} */ - public function run( ContainerInterface $c ): void {} + public function run( ContainerInterface $c ): void { + + /** + * Set authorize intent for vaulted subscriptions, so we can void if payment not saved. + */ + add_filter( + 'woocommerce_paypal_payments_saved_payment_subscription_intent', + function( string $intent ) use ( $c ) { + $subscription_helper = $c->get( 'subscription.helper' ); + assert( $subscription_helper instanceof SubscriptionHelper ); + + if ( $subscription_helper->cart_contains_subscription() || $subscription_helper->current_product_is_subscription() ) { + return 'AUTHORIZE'; + } + + return $intent; + } + ); + } } From 5f3dc3a64771a2ba23da0208864fb4305cbc96eb Mon Sep 17 00:00:00 2001 From: Emili Castells Guasch Date: Tue, 19 Sep 2023 15:16:22 +0200 Subject: [PATCH 4/8] Move payment checker scheduler to module --- modules.php | 2 +- .../ppcp-saved-payment-checked/services.php | 14 -- .../src/SavedPaymentCheckerModule.php | 55 ------- .../.gitignore | 0 .../composer.json | 2 +- .../extensions.php | 2 - .../module.php | 0 .../ppcp-saved-payment-checker/services.php | 26 ++++ .../src/PaymentTokenChecker.php | 30 +++- .../src/SavedPaymentCheckerModule.php | 142 ++++++++++++++++++ modules/ppcp-vaulting/services.php | 11 -- modules/ppcp-vaulting/src/VaultingModule.php | 104 +------------ .../src/Gateway/CardButtonGateway.php | 4 +- .../src/Gateway/CreditCardGateway.php | 4 +- .../src/Gateway/PayPalGateway.php | 4 +- .../src/Gateway/ProcessPaymentTrait.php | 26 ---- 16 files changed, 202 insertions(+), 224 deletions(-) delete mode 100644 modules/ppcp-saved-payment-checked/services.php delete mode 100644 modules/ppcp-saved-payment-checked/src/SavedPaymentCheckerModule.php rename modules/{ppcp-saved-payment-checked => ppcp-saved-payment-checker}/.gitignore (100%) rename modules/{ppcp-saved-payment-checked => ppcp-saved-payment-checker}/composer.json (86%) rename modules/{ppcp-saved-payment-checked => ppcp-saved-payment-checker}/extensions.php (75%) rename modules/{ppcp-saved-payment-checked => ppcp-saved-payment-checker}/module.php (100%) create mode 100644 modules/ppcp-saved-payment-checker/services.php rename modules/{ppcp-vaulting => ppcp-saved-payment-checker}/src/PaymentTokenChecker.php (90%) create mode 100644 modules/ppcp-saved-payment-checker/src/SavedPaymentCheckerModule.php diff --git a/modules.php b/modules.php index cd8ff00fe..d9b363081 100644 --- a/modules.php +++ b/modules.php @@ -49,7 +49,7 @@ return function ( string $root_dir ): iterable { 'woocommerce.deprecated-flags.woocommerce_paypal_payments.saved_payment_checker_enabled', getenv( 'PCP_SAVED_PAYMENT_CHECKER_ENABLED' ) === '1' ) ) { - $modules[] = ( require "$modules_dir/ppcp-saved-payment-checked/module.php" )(); + $modules[] = ( require "$modules_dir/ppcp-saved-payment-checker/module.php" )(); } return $modules; diff --git a/modules/ppcp-saved-payment-checked/services.php b/modules/ppcp-saved-payment-checked/services.php deleted file mode 100644 index 40c69a3af..000000000 --- a/modules/ppcp-saved-payment-checked/services.php +++ /dev/null @@ -1,14 +0,0 @@ -get( 'subscription.helper' ); - assert( $subscription_helper instanceof SubscriptionHelper ); - - if ( $subscription_helper->cart_contains_subscription() || $subscription_helper->current_product_is_subscription() ) { - return 'AUTHORIZE'; - } - - return $intent; - } - ); - } -} diff --git a/modules/ppcp-saved-payment-checked/.gitignore b/modules/ppcp-saved-payment-checker/.gitignore similarity index 100% rename from modules/ppcp-saved-payment-checked/.gitignore rename to modules/ppcp-saved-payment-checker/.gitignore diff --git a/modules/ppcp-saved-payment-checked/composer.json b/modules/ppcp-saved-payment-checker/composer.json similarity index 86% rename from modules/ppcp-saved-payment-checked/composer.json rename to modules/ppcp-saved-payment-checker/composer.json index e84d9213b..da4404469 100644 --- a/modules/ppcp-saved-payment-checked/composer.json +++ b/modules/ppcp-saved-payment-checker/composer.json @@ -1,7 +1,7 @@ { "name": "woocommerce/ppcp-saved-payment-checked", "type": "dhii-mod", - "description": "Saved payment checker module for PPCP", + "description": "Saved payments checker module", "license": "GPL-2.0", "require": { "php": "^7.2 | ^8.0", diff --git a/modules/ppcp-saved-payment-checked/extensions.php b/modules/ppcp-saved-payment-checker/extensions.php similarity index 75% rename from modules/ppcp-saved-payment-checked/extensions.php rename to modules/ppcp-saved-payment-checker/extensions.php index aa36cabb4..e1260787e 100644 --- a/modules/ppcp-saved-payment-checked/extensions.php +++ b/modules/ppcp-saved-payment-checker/extensions.php @@ -9,6 +9,4 @@ declare(strict_types=1); namespace WooCommerce\PayPalCommerce\SavedPaymentChecker; -use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface; - return array(); diff --git a/modules/ppcp-saved-payment-checked/module.php b/modules/ppcp-saved-payment-checker/module.php similarity index 100% rename from modules/ppcp-saved-payment-checked/module.php rename to modules/ppcp-saved-payment-checker/module.php diff --git a/modules/ppcp-saved-payment-checker/services.php b/modules/ppcp-saved-payment-checker/services.php new file mode 100644 index 000000000..bce19d1d9 --- /dev/null +++ b/modules/ppcp-saved-payment-checker/services.php @@ -0,0 +1,26 @@ + function( ContainerInterface $container ) : PaymentTokenChecker { + return new PaymentTokenChecker( + $container->get( 'vaulting.repository.payment-token' ), + $container->get( 'api.repository.order' ), + $container->get( 'wcgateway.settings' ), + $container->get( 'wcgateway.processor.authorized-payments' ), + $container->get( 'api.endpoint.payments' ), + $container->get( 'api.endpoint.payment-token' ), + $container->get( 'woocommerce.logger.woocommerce' ) + ); + }, +); diff --git a/modules/ppcp-vaulting/src/PaymentTokenChecker.php b/modules/ppcp-saved-payment-checker/src/PaymentTokenChecker.php similarity index 90% rename from modules/ppcp-vaulting/src/PaymentTokenChecker.php rename to modules/ppcp-saved-payment-checker/src/PaymentTokenChecker.php index e37dfd252..0da73b51b 100644 --- a/modules/ppcp-vaulting/src/PaymentTokenChecker.php +++ b/modules/ppcp-saved-payment-checker/src/PaymentTokenChecker.php @@ -7,17 +7,17 @@ declare(strict_types=1); -namespace WooCommerce\PayPalCommerce\Vaulting; +namespace WooCommerce\PayPalCommerce\SavedPaymentChecker; use Exception; use Psr\Log\LoggerInterface; -use RuntimeException; use WC_Order; use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PaymentsEndpoint; use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PaymentTokenEndpoint; use WooCommerce\PayPalCommerce\ApiClient\Entity\PaymentToken; use WooCommerce\PayPalCommerce\ApiClient\Repository\OrderRepository; use WooCommerce\PayPalCommerce\Subscription\FreeTrialHandlerTrait; +use WooCommerce\PayPalCommerce\Vaulting\PaymentTokenRepository; use WooCommerce\PayPalCommerce\WcGateway\Exception\NotFoundException; use WooCommerce\PayPalCommerce\WcGateway\Gateway\CardButtonGateway; use WooCommerce\PayPalCommerce\WcGateway\Gateway\CreditCardGateway; @@ -203,6 +203,32 @@ class PaymentTokenChecker { } } + /** + * Schedules the vaulted payment check. + * + * @param int $wc_order_id The WC order ID. + * @param int $customer_id The customer ID. + */ + public function schedule_saved_payment_check( int $wc_order_id, int $customer_id ): void { + $timestamp = 3 * MINUTE_IN_SECONDS; + if ( + $this->settings->has( 'subscription_behavior_when_vault_fails' ) + && $this->settings->get( 'subscription_behavior_when_vault_fails' ) === 'capture_auth' + ) { + $timestamp = 0; + } + + as_schedule_single_action( + time() + $timestamp, + 'woocommerce_paypal_payments_check_saved_payment', + array( + 'order_id' => $wc_order_id, + 'customer_id' => $customer_id, + 'intent' => $this->settings->has( 'intent' ) ? $this->settings->get( 'intent' ) : '', + ) + ); + } + /** * Captures authorized payments for the given WC order. * diff --git a/modules/ppcp-saved-payment-checker/src/SavedPaymentCheckerModule.php b/modules/ppcp-saved-payment-checker/src/SavedPaymentCheckerModule.php new file mode 100644 index 000000000..0055303f1 --- /dev/null +++ b/modules/ppcp-saved-payment-checker/src/SavedPaymentCheckerModule.php @@ -0,0 +1,142 @@ +get( 'subscription.helper' ); + assert( $subscription_helper instanceof SubscriptionHelper ); + + if ( $subscription_helper->cart_contains_subscription() || $subscription_helper->current_product_is_subscription() ) { + return 'AUTHORIZE'; + } + + return $intent; + } + ); + + /** + * Schedules saved payment checker before payment success handler. + */ + add_action( + 'woocommerce_paypal_payments_before_handle_payment_success', + function( WC_Order $wc_order ) use ( $c ) { + $subscription_helper = $c->get( 'subscription.helper' ); + assert( $subscription_helper instanceof SubscriptionHelper ); + + if ( $subscription_helper->has_subscription( $wc_order->get_id() ) ) { + $payment_token_checker = $c->get( 'saved-payment-checker.payment-token-checker' ); + assert( $payment_token_checker instanceof PaymentTokenChecker ); + + $payment_token_checker->schedule_saved_payment_check( $wc_order->get_id(), $wc_order->get_customer_id() ); + } + } + ); + + /** + * Triggers a payment token check for the given order and customer id. + */ + add_action( + 'woocommerce_paypal_payments_check_saved_payment', + function ( int $order_id, int $customer_id, string $intent ) use ( $c ) { + $payment_token_checker = $c->get( 'vaulting.payment-token-checker' ); + assert( $payment_token_checker instanceof PaymentTokenChecker ); + + $payment_token_checker->check_and_update( $order_id, $customer_id, $intent ); + }, + 10, + 3 + ); + + /** + * Adds email content for vaulting failure. + */ + add_action( + 'woocommerce_email_before_order_table', + function( WC_Order $order ) use ( $c ) { + $subscription_helper = $c->get( 'subscription.helper' ); + assert( $subscription_helper instanceof SubscriptionHelper ); + $logger = $c->get( 'woocommerce.logger.woocommerce' ); + assert( $logger instanceof LoggerInterface ); + + $vault_failed = $order->get_meta( PaymentTokenChecker::VAULTING_FAILED_META_KEY ); + if ( $subscription_helper->has_subscription( $order->get_id() ) && ! empty( $vault_failed ) ) { + $logger->info( "Adding vaulting failure info to email for order #{$order->get_id()}." ); + + if ( $vault_failed === 'void_auth' ) { + echo wp_kses_post( '

' . __( 'The subscription payment failed because the payment method could not be saved. Please try again with a different payment method.', 'woocommerce-paypal-payments' ) . '

' ); + } + + if ( $vault_failed === 'capture_auth' ) { + echo wp_kses_post( '

' . __( 'The subscription has been activated, but the payment method could not be saved. Please contact the merchant to save a payment method for automatic subscription renewal payments.', 'woocommerce-paypal-payments' ) . '

' ); + } + } + } + ); + + /** + * Adds email content for vaulting changing manual renewal order. + */ + add_action( + 'woocommerce_email_after_order_table', + function( WC_Order $order ) use ( $c ) { + $subscription_helper = $c->get( 'subscription.helper' ); + assert( $subscription_helper instanceof SubscriptionHelper ); + $logger = $c->get( 'woocommerce.logger.woocommerce' ); + assert( $logger instanceof LoggerInterface ); + + $vault_failed = $order->get_meta( PaymentTokenChecker::VAULTING_FAILED_META_KEY ); + if ( $subscription_helper->has_subscription( $order->get_id() ) && ! empty( $vault_failed ) ) { + $logger->info( "Changing subscription auto-renewal status for order #{$order->get_id()}." ); + + if ( $vault_failed === 'capture_auth' ) { + $subscriptions = function_exists( 'wcs_get_subscriptions_for_order' ) ? wcs_get_subscriptions_for_order( $order->get_id() ) : array(); + foreach ( $subscriptions as $subscription ) { + $subscription->set_requires_manual_renewal( true ); + $subscription->save(); + } + } + } + } + ); + } +} diff --git a/modules/ppcp-vaulting/services.php b/modules/ppcp-vaulting/services.php index d18768ea2..101e0bb4c 100644 --- a/modules/ppcp-vaulting/services.php +++ b/modules/ppcp-vaulting/services.php @@ -23,17 +23,6 @@ return array( $endpoint = $container->get( 'api.endpoint.payment-token' ); return new PaymentTokenRepository( $factory, $endpoint ); }, - 'vaulting.payment-token-checker' => function( ContainerInterface $container ) : PaymentTokenChecker { - return new PaymentTokenChecker( - $container->get( 'vaulting.repository.payment-token' ), - $container->get( 'api.repository.order' ), - $container->get( 'wcgateway.settings' ), - $container->get( 'wcgateway.processor.authorized-payments' ), - $container->get( 'api.endpoint.payments' ), - $container->get( 'api.endpoint.payment-token' ), - $container->get( 'woocommerce.logger.woocommerce' ) - ); - }, 'vaulting.customer-approval-listener' => function( ContainerInterface $container ) : CustomerApprovalListener { return new CustomerApprovalListener( $container->get( 'api.endpoint.payment-token' ), diff --git a/modules/ppcp-vaulting/src/VaultingModule.php b/modules/ppcp-vaulting/src/VaultingModule.php index 7386dae42..4da9a32bb 100644 --- a/modules/ppcp-vaulting/src/VaultingModule.php +++ b/modules/ppcp-vaulting/src/VaultingModule.php @@ -9,6 +9,7 @@ declare(strict_types=1); namespace WooCommerce\PayPalCommerce\Vaulting; +use Psr\Log\LoggerInterface; use RuntimeException; use WC_Payment_Token; use WC_Payment_Tokens; @@ -16,9 +17,6 @@ use WooCommerce\PayPalCommerce\Vendor\Dhii\Container\ServiceProvider; use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface; use WooCommerce\PayPalCommerce\Vendor\Interop\Container\ServiceProviderInterface; use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface; -use Psr\Log\LoggerInterface; -use WC_Order; -use WooCommerce\PayPalCommerce\Subscription\Helper\SubscriptionHelper; use WooCommerce\PayPalCommerce\WcGateway\Exception\NotFoundException; use WooCommerce\PayPalCommerce\WcGateway\Gateway\CreditCardGateway; use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway; @@ -68,19 +66,6 @@ class VaultingModule implements ModuleInterface { } ); - add_action( - 'woocommerce_paypal_payments_check_saved_payment', - function ( int $order_id, int $customer_id, string $intent ) use ( $container ) { - $payment_token_checker = $container->get( 'vaulting.payment-token-checker' ); - assert( $payment_token_checker instanceof PaymentTokenChecker ); - $payment_token_checker->check_and_update( $order_id, $customer_id, $intent ); - }, - 10, - 3 - ); - - $this->filterFailedVaultingEmailsForSubscriptionOrders( $container ); - add_filter( 'woocommerce_payment_token_class', /** @@ -271,95 +256,8 @@ class VaultingModule implements ModuleInterface { } } - /** - * Filters the emails when vaulting is failed for subscription orders. - * - * @param ContainerInterface $container A services container instance. - * @throws NotFoundException When service could not be found. - */ - protected function filterFailedVaultingEmailsForSubscriptionOrders( ContainerInterface $container ):void { - add_action( - 'woocommerce_email_before_order_table', - function( WC_Order $order ) use ( $container ) { - /** - * The SubscriptionHelper. - * - * @var SubscriptionHelper $subscription_helper - */ - $subscription_helper = $container->get( 'subscription.helper' ); - - /** - * The logger. - * - * @var LoggerInterface $logger - */ - $logger = $container->get( 'woocommerce.logger.woocommerce' ); - - $vault_failed = $order->get_meta( PaymentTokenChecker::VAULTING_FAILED_META_KEY ); - if ( $subscription_helper->has_subscription( $order->get_id() ) && ! empty( $vault_failed ) ) { - $logger->info( "Adding vaulting failure info to email for order #{$order->get_id()}." ); - - if ( $vault_failed === 'void_auth' ) { - echo wp_kses_post( '

' . __( 'The subscription payment failed because the payment method could not be saved. Please try again with a different payment method.', 'woocommerce-paypal-payments' ) . '

' ); - } - - if ( $vault_failed === 'capture_auth' ) { - echo wp_kses_post( '

' . __( 'The subscription has been activated, but the payment method could not be saved. Please contact the merchant to save a payment method for automatic subscription renewal payments.', 'woocommerce-paypal-payments' ) . '

' ); - } - } - } - ); - - add_action( - 'woocommerce_email_after_order_table', - function( WC_Order $order ) use ( $container ) { - /** - * The SubscriptionHelper. - * - * @var SubscriptionHelper $subscription_helper - */ - $subscription_helper = $container->get( 'subscription.helper' ); - - /** - * The logger. - * - * @var LoggerInterface $logger - */ - $logger = $container->get( 'woocommerce.logger.woocommerce' ); - - $vault_failed = $order->get_meta( PaymentTokenChecker::VAULTING_FAILED_META_KEY ); - if ( $subscription_helper->has_subscription( $order->get_id() ) && ! empty( $vault_failed ) ) { - $logger->info( "Changing subscription auto-renewal status for order #{$order->get_id()}." ); - - if ( $vault_failed === 'capture_auth' ) { - $subscriptions = function_exists( 'wcs_get_subscriptions_for_order' ) ? wcs_get_subscriptions_for_order( $order->get_id() ) : array(); - foreach ( $subscriptions as $subscription ) { - $subscription->set_requires_manual_renewal( true ); - $subscription->save(); - } - } - } - } - ); - } - /** * {@inheritDoc} */ public function getKey() { } - - /** - * Check if is payments page. - * - * @return bool Whethen page is payments or not. - */ - private function is_payments_page(): bool { - global $wp; - $request = explode( '/', wp_parse_url( $wp->request, PHP_URL_PATH ) ); - if ( end( $request ) === 'ppcp-paypal-payment-tokens' ) { - return true; - } - - return false; - } } diff --git a/modules/ppcp-wc-gateway/src/Gateway/CardButtonGateway.php b/modules/ppcp-wc-gateway/src/Gateway/CardButtonGateway.php index 2f994bf46..fecb495b6 100644 --- a/modules/ppcp-wc-gateway/src/Gateway/CardButtonGateway.php +++ b/modules/ppcp-wc-gateway/src/Gateway/CardButtonGateway.php @@ -299,9 +299,7 @@ class CardButtonGateway extends \WC_Payment_Gateway { ); } - if ( $this->subscription_helper->has_subscription( $order_id ) ) { - $this->schedule_saved_payment_check( $order_id, $wc_order->get_customer_id() ); - } + do_action( 'woocommerce_paypal_payments_before_handle_payment_success', $wc_order ); return $this->handle_payment_success( $wc_order ); } catch ( PayPalApiException $error ) { diff --git a/modules/ppcp-wc-gateway/src/Gateway/CreditCardGateway.php b/modules/ppcp-wc-gateway/src/Gateway/CreditCardGateway.php index 6d152eb33..1b99b9d05 100644 --- a/modules/ppcp-wc-gateway/src/Gateway/CreditCardGateway.php +++ b/modules/ppcp-wc-gateway/src/Gateway/CreditCardGateway.php @@ -396,9 +396,7 @@ class CreditCardGateway extends \WC_Payment_Gateway_CC { ); } - if ( $this->subscription_helper->has_subscription( $order_id ) ) { - $this->schedule_saved_payment_check( $order_id, $wc_order->get_customer_id() ); - } + do_action( 'woocommerce_paypal_payments_before_handle_payment_success', $wc_order ); return $this->handle_payment_success( $wc_order ); } catch ( PayPalApiException $error ) { diff --git a/modules/ppcp-wc-gateway/src/Gateway/PayPalGateway.php b/modules/ppcp-wc-gateway/src/Gateway/PayPalGateway.php index a2a42a589..b17e48a7a 100644 --- a/modules/ppcp-wc-gateway/src/Gateway/PayPalGateway.php +++ b/modules/ppcp-wc-gateway/src/Gateway/PayPalGateway.php @@ -556,9 +556,7 @@ class PayPalGateway extends \WC_Payment_Gateway { ); } - if ( $this->subscription_helper->has_subscription( $order_id ) ) { - $this->schedule_saved_payment_check( $order_id, $wc_order->get_customer_id() ); - } + do_action( 'woocommerce_paypal_payments_before_handle_payment_success', $wc_order ); return $this->handle_payment_success( $wc_order ); } catch ( PayPalApiException $error ) { diff --git a/modules/ppcp-wc-gateway/src/Gateway/ProcessPaymentTrait.php b/modules/ppcp-wc-gateway/src/Gateway/ProcessPaymentTrait.php index d330a11a6..7f752ef18 100644 --- a/modules/ppcp-wc-gateway/src/Gateway/ProcessPaymentTrait.php +++ b/modules/ppcp-wc-gateway/src/Gateway/ProcessPaymentTrait.php @@ -33,32 +33,6 @@ trait ProcessPaymentTrait { return false; } - /** - * Scheduled the vaulted payment check. - * - * @param int $wc_order_id The WC order ID. - * @param int $customer_id The customer ID. - */ - protected function schedule_saved_payment_check( int $wc_order_id, int $customer_id ): void { - $timestamp = 3 * MINUTE_IN_SECONDS; - if ( - $this->config->has( 'subscription_behavior_when_vault_fails' ) - && $this->config->get( 'subscription_behavior_when_vault_fails' ) === 'capture_auth' - ) { - $timestamp = 0; - } - - as_schedule_single_action( - time() + $timestamp, - 'woocommerce_paypal_payments_check_saved_payment', - array( - 'order_id' => $wc_order_id, - 'customer_id' => $customer_id, - 'intent' => $this->config->has( 'intent' ) ? $this->config->get( 'intent' ) : '', - ) - ); - } - /** * Handles the payment failure. * From 7cfc644379946720ad3c58c0de13bf1f53de8ac6 Mon Sep 17 00:00:00 2001 From: Emili Castells Guasch Date: Tue, 19 Sep 2023 15:49:29 +0200 Subject: [PATCH 5/8] Remove non used assets --- .../ppcp-saved-payment-checker/extensions.php | 46 +- .../assets/js/myaccount-payments.js | 3 - .../js/myaccount-payments.js.LICENSE.txt | 1 - .../assets/js/myaccount-payments.js.map | 1 - modules/ppcp-vaulting/package.json | 32 - modules/ppcp-vaulting/yarn.lock | 2260 ----------------- modules/ppcp-wc-gateway/services.php | 20 - 7 files changed, 45 insertions(+), 2318 deletions(-) delete mode 100644 modules/ppcp-vaulting/assets/js/myaccount-payments.js delete mode 100644 modules/ppcp-vaulting/assets/js/myaccount-payments.js.LICENSE.txt delete mode 100644 modules/ppcp-vaulting/assets/js/myaccount-payments.js.map delete mode 100644 modules/ppcp-vaulting/package.json delete mode 100644 modules/ppcp-vaulting/yarn.lock diff --git a/modules/ppcp-saved-payment-checker/extensions.php b/modules/ppcp-saved-payment-checker/extensions.php index e1260787e..341775c19 100644 --- a/modules/ppcp-saved-payment-checker/extensions.php +++ b/modules/ppcp-saved-payment-checker/extensions.php @@ -9,4 +9,48 @@ declare(strict_types=1); namespace WooCommerce\PayPalCommerce\SavedPaymentChecker; -return array(); +use WooCommerce\PayPalCommerce\Onboarding\State; +use WooCommerce\PayPalCommerce\Subscription\Helper\SubscriptionHelper; +use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface; + +return array( + 'wcgateway.settings.fields' => function ( ContainerInterface $container, array $fields ): array { + $subscription_helper = $container->get('subscription.helper'); + assert($subscription_helper instanceof SubscriptionHelper); + + $insert_after = function( array $array, string $key, array $new ): array { + $keys = array_keys( $array ); + $index = array_search( $key, $keys, true ); + $pos = false === $index ? count( $array ) : $index + 1; + + return array_merge( array_slice( $array, 0, $pos ), $new, array_slice( $array, $pos ) ); + }; + + return $insert_after( + $fields, + 'vault_enabled', + array( + 'subscription_behavior_when_vault_fails' => array( + 'title' => __( 'Subscription capture behavior if Vault fails', 'woocommerce-paypal-payments' ), + 'type' => 'select', + 'classes' => $subscription_helper->plugin_is_active() ? array() : array( 'hide' ), + 'input_class' => array( 'wc-enhanced-select' ), + 'default' => 'void_auth', + 'desc_tip' => true, + 'description' => __( 'By default, subscription payments are captured only when saving the payment method was successful. Without a saved payment method, automatic renewal payments are not possible.', 'woocommerce-paypal-payments' ), + 'description_with_tip' => __( 'Determines whether authorized payments for subscription orders are captured or voided if there is no saved payment method. This only applies when the intent Capture is used for the subscription order.', 'woocommerce-paypal-payments' ), + 'options' => array( + 'void_auth' => __( 'Void authorization & fail the order/subscription', 'woocommerce-paypal-payments' ), + 'capture_auth' => __( 'Capture authorized payment & set subscription to Manual Renewal', 'woocommerce-paypal-payments' ), + 'capture_auth_ignore' => __( 'Capture authorized payment & disregard missing payment method', 'woocommerce-paypal-payments' ), + ), + 'screens' => array( + State::STATE_ONBOARDED, + ), + 'requirements' => array(), + 'gateway' => array( 'paypal' ), + ), + ) + ); + } +); diff --git a/modules/ppcp-vaulting/assets/js/myaccount-payments.js b/modules/ppcp-vaulting/assets/js/myaccount-payments.js deleted file mode 100644 index f03455c7b..000000000 --- a/modules/ppcp-vaulting/assets/js/myaccount-payments.js +++ /dev/null @@ -1,3 +0,0 @@ -/*! For license information please see myaccount-payments.js.LICENSE.txt */ -(()=>{var t={9662:(t,r,e)=>{var n=e(614),o=e(6330),i=TypeError;t.exports=function(t){if(n(t))return t;throw i(o(t)+" is not a function")}},9483:(t,r,e)=>{var n=e(4411),o=e(6330),i=TypeError;t.exports=function(t){if(n(t))return t;throw i(o(t)+" is not a constructor")}},6077:(t,r,e)=>{var n=e(614),o=String,i=TypeError;t.exports=function(t){if("object"==typeof t||n(t))return t;throw i("Can't set "+o(t)+" as a prototype")}},1223:(t,r,e)=>{var n=e(5112),o=e(30),i=e(3070).f,a=n("unscopables"),c=Array.prototype;null==c[a]&&i(c,a,{configurable:!0,value:o(null)}),t.exports=function(t){c[a][t]=!0}},5787:(t,r,e)=>{var n=e(7976),o=TypeError;t.exports=function(t,r){if(n(r,t))return t;throw o("Incorrect invocation")}},9670:(t,r,e)=>{var n=e(111),o=String,i=TypeError;t.exports=function(t){if(n(t))return t;throw i(o(t)+" is not an object")}},8533:(t,r,e)=>{"use strict";var n=e(2092).forEach,o=e(2133)("forEach");t.exports=o?[].forEach:function(t){return n(this,t,arguments.length>1?arguments[1]:void 0)}},1318:(t,r,e)=>{var n=e(5656),o=e(1400),i=e(6244),a=function(t){return function(r,e,a){var c,u=n(r),s=i(u),f=o(a,s);if(t&&e!=e){for(;s>f;)if((c=u[f++])!=c)return!0}else for(;s>f;f++)if((t||f in u)&&u[f]===e)return t||f||0;return!t&&-1}};t.exports={includes:a(!0),indexOf:a(!1)}},2092:(t,r,e)=>{var n=e(9974),o=e(1702),i=e(8361),a=e(7908),c=e(6244),u=e(5417),s=o([].push),f=function(t){var r=1==t,e=2==t,o=3==t,f=4==t,p=6==t,l=7==t,v=5==t||p;return function(h,y,d,g){for(var m,b,x=a(h),w=i(x),S=n(y,d),O=c(w),j=0,E=g||u,P=r?E(h,O):e||l?E(h,0):void 0;O>j;j++)if((v||j in w)&&(b=S(m=w[j],j,x),t))if(r)P[j]=b;else if(b)switch(t){case 3:return!0;case 5:return m;case 6:return j;case 2:s(P,m)}else switch(t){case 4:return!1;case 7:s(P,m)}return p?-1:o||f?f:P}};t.exports={forEach:f(0),map:f(1),filter:f(2),some:f(3),every:f(4),find:f(5),findIndex:f(6),filterReject:f(7)}},1194:(t,r,e)=>{var n=e(7293),o=e(5112),i=e(7392),a=o("species");t.exports=function(t){return i>=51||!n((function(){var r=[];return(r.constructor={})[a]=function(){return{foo:1}},1!==r[t](Boolean).foo}))}},2133:(t,r,e)=>{"use strict";var n=e(7293);t.exports=function(t,r){var e=[][t];return!!e&&n((function(){e.call(null,r||function(){return 1},1)}))}},1589:(t,r,e)=>{var n=e(1400),o=e(6244),i=e(6135),a=Array,c=Math.max;t.exports=function(t,r,e){for(var u=o(t),s=n(r,u),f=n(void 0===e?u:e,u),p=a(c(f-s,0)),l=0;s{var n=e(1702);t.exports=n([].slice)},7475:(t,r,e)=>{var n=e(3157),o=e(4411),i=e(111),a=e(5112)("species"),c=Array;t.exports=function(t){var r;return n(t)&&(r=t.constructor,(o(r)&&(r===c||n(r.prototype))||i(r)&&null===(r=r[a]))&&(r=void 0)),void 0===r?c:r}},5417:(t,r,e)=>{var n=e(7475);t.exports=function(t,r){return new(n(t))(0===r?0:r)}},7072:(t,r,e)=>{var n=e(5112)("iterator"),o=!1;try{var i=0,a={next:function(){return{done:!!i++}},return:function(){o=!0}};a[n]=function(){return this},Array.from(a,(function(){throw 2}))}catch(t){}t.exports=function(t,r){if(!r&&!o)return!1;var e=!1;try{var i={};i[n]=function(){return{next:function(){return{done:e=!0}}}},t(i)}catch(t){}return e}},4326:(t,r,e)=>{var n=e(1702),o=n({}.toString),i=n("".slice);t.exports=function(t){return i(o(t),8,-1)}},648:(t,r,e)=>{var n=e(1694),o=e(614),i=e(4326),a=e(5112)("toStringTag"),c=Object,u="Arguments"==i(function(){return arguments}());t.exports=n?i:function(t){var r,e,n;return void 0===t?"Undefined":null===t?"Null":"string"==typeof(e=function(t,r){try{return t[r]}catch(t){}}(r=c(t),a))?e:u?i(r):"Object"==(n=i(r))&&o(r.callee)?"Arguments":n}},9920:(t,r,e)=>{var n=e(2597),o=e(3887),i=e(1236),a=e(3070);t.exports=function(t,r,e){for(var c=o(r),u=a.f,s=i.f,f=0;f{var n=e(7293);t.exports=!n((function(){function t(){}return t.prototype.constructor=null,Object.getPrototypeOf(new t)!==t.prototype}))},6178:t=>{t.exports=function(t,r){return{value:t,done:r}}},8880:(t,r,e)=>{var n=e(9781),o=e(3070),i=e(9114);t.exports=n?function(t,r,e){return o.f(t,r,i(1,e))}:function(t,r,e){return t[r]=e,t}},9114:t=>{t.exports=function(t,r){return{enumerable:!(1&t),configurable:!(2&t),writable:!(4&t),value:r}}},6135:(t,r,e)=>{"use strict";var n=e(4948),o=e(3070),i=e(9114);t.exports=function(t,r,e){var a=n(r);a in t?o.f(t,a,i(0,e)):t[a]=e}},8052:(t,r,e)=>{var n=e(614),o=e(3070),i=e(6339),a=e(3072);t.exports=function(t,r,e,c){c||(c={});var u=c.enumerable,s=void 0!==c.name?c.name:r;if(n(e)&&i(e,s,c),c.global)u?t[r]=e:a(r,e);else{try{c.unsafe?t[r]&&(u=!0):delete t[r]}catch(t){}u?t[r]=e:o.f(t,r,{value:e,enumerable:!1,configurable:!c.nonConfigurable,writable:!c.nonWritable})}return t}},3072:(t,r,e)=>{var n=e(7854),o=Object.defineProperty;t.exports=function(t,r){try{o(n,t,{value:r,configurable:!0,writable:!0})}catch(e){n[t]=r}return r}},9781:(t,r,e)=>{var n=e(7293);t.exports=!n((function(){return 7!=Object.defineProperty({},1,{get:function(){return 7}})[1]}))},317:(t,r,e)=>{var n=e(7854),o=e(111),i=n.document,a=o(i)&&o(i.createElement);t.exports=function(t){return a?i.createElement(t):{}}},8324:t=>{t.exports={CSSRuleList:0,CSSStyleDeclaration:0,CSSValueList:0,ClientRectList:0,DOMRectList:0,DOMStringList:0,DOMTokenList:1,DataTransferItemList:0,FileList:0,HTMLAllCollection:0,HTMLCollection:0,HTMLFormElement:0,HTMLSelectElement:0,MediaList:0,MimeTypeArray:0,NamedNodeMap:0,NodeList:1,PaintRequestList:0,Plugin:0,PluginArray:0,SVGLengthList:0,SVGNumberList:0,SVGPathSegList:0,SVGPointList:0,SVGStringList:0,SVGTransformList:0,SourceBufferList:0,StyleSheetList:0,TextTrackCueList:0,TextTrackList:0,TouchList:0}},8509:(t,r,e)=>{var n=e(317)("span").classList,o=n&&n.constructor&&n.constructor.prototype;t.exports=o===Object.prototype?void 0:o},7871:(t,r,e)=>{var n=e(3823),o=e(5268);t.exports=!n&&!o&&"object"==typeof window&&"object"==typeof document},3823:t=>{t.exports="object"==typeof Deno&&Deno&&"object"==typeof Deno.version},1528:(t,r,e)=>{var n=e(8113),o=e(7854);t.exports=/ipad|iphone|ipod/i.test(n)&&void 0!==o.Pebble},6833:(t,r,e)=>{var n=e(8113);t.exports=/(?:ipad|iphone|ipod).*applewebkit/i.test(n)},5268:(t,r,e)=>{var n=e(4326),o=e(7854);t.exports="process"==n(o.process)},1036:(t,r,e)=>{var n=e(8113);t.exports=/web0s(?!.*chrome)/i.test(n)},8113:(t,r,e)=>{var n=e(5005);t.exports=n("navigator","userAgent")||""},7392:(t,r,e)=>{var n,o,i=e(7854),a=e(8113),c=i.process,u=i.Deno,s=c&&c.versions||u&&u.version,f=s&&s.v8;f&&(o=(n=f.split("."))[0]>0&&n[0]<4?1:+(n[0]+n[1])),!o&&a&&(!(n=a.match(/Edge\/(\d+)/))||n[1]>=74)&&(n=a.match(/Chrome\/(\d+)/))&&(o=+n[1]),t.exports=o},748:t=>{t.exports=["constructor","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","toLocaleString","toString","valueOf"]},1060:(t,r,e)=>{var n=e(1702),o=Error,i=n("".replace),a=String(o("zxcasd").stack),c=/\n\s*at [^:]*:[^\n]*/,u=c.test(a);t.exports=function(t,r){if(u&&"string"==typeof t&&!o.prepareStackTrace)for(;r--;)t=i(t,c,"");return t}},2914:(t,r,e)=>{var n=e(7293),o=e(9114);t.exports=!n((function(){var t=Error("a");return!("stack"in t)||(Object.defineProperty(t,"stack",o(1,7)),7!==t.stack)}))},2109:(t,r,e)=>{var n=e(7854),o=e(1236).f,i=e(8880),a=e(8052),c=e(3072),u=e(9920),s=e(4705);t.exports=function(t,r){var e,f,p,l,v,h=t.target,y=t.global,d=t.stat;if(e=y?n:d?n[h]||c(h,{}):(n[h]||{}).prototype)for(f in r){if(l=r[f],p=t.dontCallGetSet?(v=o(e,f))&&v.value:e[f],!s(y?f:h+(d?".":"#")+f,t.forced)&&void 0!==p){if(typeof l==typeof p)continue;u(l,p)}(t.sham||p&&p.sham)&&i(l,"sham",!0),a(e,f,l,t)}}},7293:t=>{t.exports=function(t){try{return!!t()}catch(t){return!0}}},2104:(t,r,e)=>{var n=e(4374),o=Function.prototype,i=o.apply,a=o.call;t.exports="object"==typeof Reflect&&Reflect.apply||(n?a.bind(i):function(){return a.apply(i,arguments)})},9974:(t,r,e)=>{var n=e(1702),o=e(9662),i=e(4374),a=n(n.bind);t.exports=function(t,r){return o(t),void 0===r?t:i?a(t,r):function(){return t.apply(r,arguments)}}},4374:(t,r,e)=>{var n=e(7293);t.exports=!n((function(){var t=function(){}.bind();return"function"!=typeof t||t.hasOwnProperty("prototype")}))},6916:(t,r,e)=>{var n=e(4374),o=Function.prototype.call;t.exports=n?o.bind(o):function(){return o.apply(o,arguments)}},6530:(t,r,e)=>{var n=e(9781),o=e(2597),i=Function.prototype,a=n&&Object.getOwnPropertyDescriptor,c=o(i,"name"),u=c&&"something"===function(){}.name,s=c&&(!n||n&&a(i,"name").configurable);t.exports={EXISTS:c,PROPER:u,CONFIGURABLE:s}},1702:(t,r,e)=>{var n=e(4374),o=Function.prototype,i=o.bind,a=o.call,c=n&&i.bind(a,a);t.exports=n?function(t){return t&&c(t)}:function(t){return t&&function(){return a.apply(t,arguments)}}},5005:(t,r,e)=>{var n=e(7854),o=e(614),i=function(t){return o(t)?t:void 0};t.exports=function(t,r){return arguments.length<2?i(n[t]):n[t]&&n[t][r]}},1246:(t,r,e)=>{var n=e(648),o=e(8173),i=e(8554),a=e(7497),c=e(5112)("iterator");t.exports=function(t){if(!i(t))return o(t,c)||o(t,"@@iterator")||a[n(t)]}},4121:(t,r,e)=>{var n=e(6916),o=e(9662),i=e(9670),a=e(6330),c=e(1246),u=TypeError;t.exports=function(t,r){var e=arguments.length<2?c(t):r;if(o(e))return i(n(e,t));throw u(a(t)+" is not iterable")}},8173:(t,r,e)=>{var n=e(9662),o=e(8554);t.exports=function(t,r){var e=t[r];return o(e)?void 0:n(e)}},7854:(t,r,e)=>{var n=function(t){return t&&t.Math==Math&&t};t.exports=n("object"==typeof globalThis&&globalThis)||n("object"==typeof window&&window)||n("object"==typeof self&&self)||n("object"==typeof e.g&&e.g)||function(){return this}()||Function("return this")()},2597:(t,r,e)=>{var n=e(1702),o=e(7908),i=n({}.hasOwnProperty);t.exports=Object.hasOwn||function(t,r){return i(o(t),r)}},3501:t=>{t.exports={}},842:(t,r,e)=>{var n=e(7854);t.exports=function(t,r){var e=n.console;e&&e.error&&(1==arguments.length?e.error(t):e.error(t,r))}},490:(t,r,e)=>{var n=e(5005);t.exports=n("document","documentElement")},4664:(t,r,e)=>{var n=e(9781),o=e(7293),i=e(317);t.exports=!n&&!o((function(){return 7!=Object.defineProperty(i("div"),"a",{get:function(){return 7}}).a}))},8361:(t,r,e)=>{var n=e(1702),o=e(7293),i=e(4326),a=Object,c=n("".split);t.exports=o((function(){return!a("z").propertyIsEnumerable(0)}))?function(t){return"String"==i(t)?c(t,""):a(t)}:a},9587:(t,r,e)=>{var n=e(614),o=e(111),i=e(7674);t.exports=function(t,r,e){var a,c;return i&&n(a=r.constructor)&&a!==e&&o(c=a.prototype)&&c!==e.prototype&&i(t,c),t}},2788:(t,r,e)=>{var n=e(1702),o=e(614),i=e(5465),a=n(Function.toString);o(i.inspectSource)||(i.inspectSource=function(t){return a(t)}),t.exports=i.inspectSource},8340:(t,r,e)=>{var n=e(111),o=e(8880);t.exports=function(t,r){n(r)&&"cause"in r&&o(t,"cause",r.cause)}},9909:(t,r,e)=>{var n,o,i,a=e(4811),c=e(7854),u=e(1702),s=e(111),f=e(8880),p=e(2597),l=e(5465),v=e(6200),h=e(3501),y="Object already initialized",d=c.TypeError,g=c.WeakMap;if(a||l.state){var m=l.state||(l.state=new g),b=u(m.get),x=u(m.has),w=u(m.set);n=function(t,r){if(x(m,t))throw d(y);return r.facade=t,w(m,t,r),r},o=function(t){return b(m,t)||{}},i=function(t){return x(m,t)}}else{var S=v("state");h[S]=!0,n=function(t,r){if(p(t,S))throw d(y);return r.facade=t,f(t,S,r),r},o=function(t){return p(t,S)?t[S]:{}},i=function(t){return p(t,S)}}t.exports={set:n,get:o,has:i,enforce:function(t){return i(t)?o(t):n(t,{})},getterFor:function(t){return function(r){var e;if(!s(r)||(e=o(r)).type!==t)throw d("Incompatible receiver, "+t+" required");return e}}}},7659:(t,r,e)=>{var n=e(5112),o=e(7497),i=n("iterator"),a=Array.prototype;t.exports=function(t){return void 0!==t&&(o.Array===t||a[i]===t)}},3157:(t,r,e)=>{var n=e(4326);t.exports=Array.isArray||function(t){return"Array"==n(t)}},614:t=>{t.exports=function(t){return"function"==typeof t}},4411:(t,r,e)=>{var n=e(1702),o=e(7293),i=e(614),a=e(648),c=e(5005),u=e(2788),s=function(){},f=[],p=c("Reflect","construct"),l=/^\s*(?:class|function)\b/,v=n(l.exec),h=!l.exec(s),y=function(t){if(!i(t))return!1;try{return p(s,f,t),!0}catch(t){return!1}},d=function(t){if(!i(t))return!1;switch(a(t)){case"AsyncFunction":case"GeneratorFunction":case"AsyncGeneratorFunction":return!1}try{return h||!!v(l,u(t))}catch(t){return!0}};d.sham=!0,t.exports=!p||o((function(){var t;return y(y.call)||!y(Object)||!y((function(){t=!0}))||t}))?d:y},4705:(t,r,e)=>{var n=e(7293),o=e(614),i=/#|\.prototype\./,a=function(t,r){var e=u[c(t)];return e==f||e!=s&&(o(r)?n(r):!!r)},c=a.normalize=function(t){return String(t).replace(i,".").toLowerCase()},u=a.data={},s=a.NATIVE="N",f=a.POLYFILL="P";t.exports=a},8554:t=>{t.exports=function(t){return null==t}},111:(t,r,e)=>{var n=e(614),o="object"==typeof document&&document.all,i=void 0===o&&void 0!==o;t.exports=i?function(t){return"object"==typeof t?null!==t:n(t)||t===o}:function(t){return"object"==typeof t?null!==t:n(t)}},1913:t=>{t.exports=!1},2190:(t,r,e)=>{var n=e(5005),o=e(614),i=e(7976),a=e(3307),c=Object;t.exports=a?function(t){return"symbol"==typeof t}:function(t){var r=n("Symbol");return o(r)&&i(r.prototype,c(t))}},408:(t,r,e)=>{var n=e(9974),o=e(6916),i=e(9670),a=e(6330),c=e(7659),u=e(6244),s=e(7976),f=e(4121),p=e(1246),l=e(9212),v=TypeError,h=function(t,r){this.stopped=t,this.result=r},y=h.prototype;t.exports=function(t,r,e){var d,g,m,b,x,w,S,O=e&&e.that,j=!(!e||!e.AS_ENTRIES),E=!(!e||!e.IS_RECORD),P=!(!e||!e.IS_ITERATOR),T=!(!e||!e.INTERRUPTED),L=n(r,O),A=function(t){return d&&l(d,"normal",t),new h(!0,t)},k=function(t){return j?(i(t),T?L(t[0],t[1],A):L(t[0],t[1])):T?L(t,A):L(t)};if(E)d=t.iterator;else if(P)d=t;else{if(!(g=p(t)))throw v(a(t)+" is not iterable");if(c(g)){for(m=0,b=u(t);b>m;m++)if((x=k(t[m]))&&s(y,x))return x;return new h(!1)}d=f(t,g)}for(w=E?t.next:d.next;!(S=o(w,d)).done;){try{x=k(S.value)}catch(t){l(d,"throw",t)}if("object"==typeof x&&x&&s(y,x))return x}return new h(!1)}},9212:(t,r,e)=>{var n=e(6916),o=e(9670),i=e(8173);t.exports=function(t,r,e){var a,c;o(t);try{if(!(a=i(t,"return"))){if("throw"===r)throw e;return e}a=n(a,t)}catch(t){c=!0,a=t}if("throw"===r)throw e;if(c)throw a;return o(a),e}},3061:(t,r,e)=>{"use strict";var n=e(3383).IteratorPrototype,o=e(30),i=e(9114),a=e(8003),c=e(7497),u=function(){return this};t.exports=function(t,r,e,s){var f=r+" Iterator";return t.prototype=o(n,{next:i(+!s,e)}),a(t,f,!1,!0),c[f]=u,t}},1656:(t,r,e)=>{"use strict";var n=e(2109),o=e(6916),i=e(1913),a=e(6530),c=e(614),u=e(3061),s=e(9518),f=e(7674),p=e(8003),l=e(8880),v=e(8052),h=e(5112),y=e(7497),d=e(3383),g=a.PROPER,m=a.CONFIGURABLE,b=d.IteratorPrototype,x=d.BUGGY_SAFARI_ITERATORS,w=h("iterator"),S="keys",O="values",j="entries",E=function(){return this};t.exports=function(t,r,e,a,h,d,P){u(e,r,a);var T,L,A,k=function(t){if(t===h&&N)return N;if(!x&&t in _)return _[t];switch(t){case S:case O:case j:return function(){return new e(this,t)}}return function(){return new e(this)}},R=r+" Iterator",C=!1,_=t.prototype,I=_[w]||_["@@iterator"]||h&&_[h],N=!x&&I||k(h),F="Array"==r&&_.entries||I;if(F&&(T=s(F.call(new t)))!==Object.prototype&&T.next&&(i||s(T)===b||(f?f(T,b):c(T[w])||v(T,w,E)),p(T,R,!0,!0),i&&(y[R]=E)),g&&h==O&&I&&I.name!==O&&(!i&&m?l(_,"name",O):(C=!0,N=function(){return o(I,this)})),h)if(L={values:k(O),keys:d?N:k(S),entries:k(j)},P)for(A in L)(x||C||!(A in _))&&v(_,A,L[A]);else n({target:r,proto:!0,forced:x||C},L);return i&&!P||_[w]===N||v(_,w,N,{name:h}),y[r]=N,L}},3383:(t,r,e)=>{"use strict";var n,o,i,a=e(7293),c=e(614),u=e(111),s=e(30),f=e(9518),p=e(8052),l=e(5112),v=e(1913),h=l("iterator"),y=!1;[].keys&&("next"in(i=[].keys())?(o=f(f(i)))!==Object.prototype&&(n=o):y=!0),!u(n)||a((function(){var t={};return n[h].call(t)!==t}))?n={}:v&&(n=s(n)),c(n[h])||p(n,h,(function(){return this})),t.exports={IteratorPrototype:n,BUGGY_SAFARI_ITERATORS:y}},7497:t=>{t.exports={}},6244:(t,r,e)=>{var n=e(7466);t.exports=function(t){return n(t.length)}},6339:(t,r,e)=>{var n=e(7293),o=e(614),i=e(2597),a=e(9781),c=e(6530).CONFIGURABLE,u=e(2788),s=e(9909),f=s.enforce,p=s.get,l=Object.defineProperty,v=a&&!n((function(){return 8!==l((function(){}),"length",{value:8}).length})),h=String(String).split("String"),y=t.exports=function(t,r,e){"Symbol("===String(r).slice(0,7)&&(r="["+String(r).replace(/^Symbol\(([^)]*)\)/,"$1")+"]"),e&&e.getter&&(r="get "+r),e&&e.setter&&(r="set "+r),(!i(t,"name")||c&&t.name!==r)&&(a?l(t,"name",{value:r,configurable:!0}):t.name=r),v&&e&&i(e,"arity")&&t.length!==e.arity&&l(t,"length",{value:e.arity});try{e&&i(e,"constructor")&&e.constructor?a&&l(t,"prototype",{writable:!1}):t.prototype&&(t.prototype=void 0)}catch(t){}var n=f(t);return i(n,"source")||(n.source=h.join("string"==typeof r?r:"")),t};Function.prototype.toString=y((function(){return o(this)&&p(this).source||u(this)}),"toString")},4758:t=>{var r=Math.ceil,e=Math.floor;t.exports=Math.trunc||function(t){var n=+t;return(n>0?e:r)(n)}},5948:(t,r,e)=>{var n,o,i,a,c,u,s,f,p=e(7854),l=e(9974),v=e(1236).f,h=e(261).set,y=e(6833),d=e(1528),g=e(1036),m=e(5268),b=p.MutationObserver||p.WebKitMutationObserver,x=p.document,w=p.process,S=p.Promise,O=v(p,"queueMicrotask"),j=O&&O.value;j||(n=function(){var t,r;for(m&&(t=w.domain)&&t.exit();o;){r=o.fn,o=o.next;try{r()}catch(t){throw o?a():i=void 0,t}}i=void 0,t&&t.enter()},y||m||g||!b||!x?!d&&S&&S.resolve?((s=S.resolve(void 0)).constructor=S,f=l(s.then,s),a=function(){f(n)}):m?a=function(){w.nextTick(n)}:(h=l(h,p),a=function(){h(n)}):(c=!0,u=x.createTextNode(""),new b(n).observe(u,{characterData:!0}),a=function(){u.data=c=!c})),t.exports=j||function(t){var r={fn:t,next:void 0};i&&(i.next=r),o||(o=r,a()),i=r}},8523:(t,r,e)=>{"use strict";var n=e(9662),o=TypeError,i=function(t){var r,e;this.promise=new t((function(t,n){if(void 0!==r||void 0!==e)throw o("Bad Promise constructor");r=t,e=n})),this.resolve=n(r),this.reject=n(e)};t.exports.f=function(t){return new i(t)}},6277:(t,r,e)=>{var n=e(1340);t.exports=function(t,r){return void 0===t?arguments.length<2?"":r:n(t)}},30:(t,r,e)=>{var n,o=e(9670),i=e(6048),a=e(748),c=e(3501),u=e(490),s=e(317),f=e(6200)("IE_PROTO"),p=function(){},l=function(t){return"