diff --git a/.psalm/stubs.php b/.psalm/stubs.php index 00ece2e4e..863e769e7 100644 --- a/.psalm/stubs.php +++ b/.psalm/stubs.php @@ -5,3 +5,6 @@ if (!defined('EP_PAGES')) { if (!defined('MONTH_IN_SECONDS')) { define('MONTH_IN_SECONDS', 30 * DAY_IN_SECONDS); } +if (!defined('HOUR_IN_SECONDS')) { + define('HOUR_IN_SECONDS', 60 * MINUTE_IN_SECONDS); +} diff --git a/changelog.txt b/changelog.txt index b60c7a0c5..ddf414ea9 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,17 @@ *** Changelog *** += 1.9.4 - TBD = +* Add - Create new connection tab #801 +* Add - Functionality to choose subscription failure behavior #728 +* Fix - Virtual-only orders always move order status to completed #868 +* Fix - PayPal order created twice when context is checkout #832 +* Enhancement - Handle unsupported browsers better #843 +* Enhancement - Combine the Webhooks Status page into a new Connection tab (891) #827 +* Enhancement - Hide PayPal Card Processing tab if not available in country or for merchant #870 +* Enhancement - Resubscribe webhooks on plugin upgrades #838 +* Enhancement - PUI-relevant webhook not subscribed to #842 +* Enhancement - Remove WC logo during onboarding #881 + = 1.9.3 - 2022-08-31 = * Add - Tracking API #792 * Fix - Improve compatibility with Siteground Optimizer plugin #797 diff --git a/modules/ppcp-api-client/src/Repository/PartnerReferralsData.php b/modules/ppcp-api-client/src/Repository/PartnerReferralsData.php index d1ea64f64..a955dcf23 100644 --- a/modules/ppcp-api-client/src/Repository/PartnerReferralsData.php +++ b/modules/ppcp-api-client/src/Repository/PartnerReferralsData.php @@ -79,7 +79,6 @@ class PartnerReferralsData { 'ppcp_partner_referrals_data', array( 'partner_config_override' => array( - 'partner_logo_url' => 'https://connect.woocommerce.com/images/woocommerce_logo.png', /** * Returns the URL which will be opened at the end of onboarding. */ diff --git a/modules/ppcp-onboarding/resources/js/settings.js b/modules/ppcp-onboarding/resources/js/settings.js index 1c55c491c..b6f6080e7 100644 --- a/modules/ppcp-onboarding/resources/js/settings.js +++ b/modules/ppcp-onboarding/resources/js/settings.js @@ -311,6 +311,13 @@ document.addEventListener( ] ); + groupToggle( + '#ppcp-vault_enabled', + [ + '#field-subscription_behavior_when_vault_fails', + ] + ); + groupToggleSelect( '#ppcp-intent', diff --git a/modules/ppcp-order-tracking/.gitignore b/modules/ppcp-order-tracking/.gitignore index f69a89f4b..265c2208c 100644 --- a/modules/ppcp-order-tracking/.gitignore +++ b/modules/ppcp-order-tracking/.gitignore @@ -1,2 +1,2 @@ node_modules -/assets +assets diff --git a/modules/ppcp-order-tracking/src/Endpoint/OrderTrackingEndpoint.php b/modules/ppcp-order-tracking/src/Endpoint/OrderTrackingEndpoint.php index c4e80bb02..5eb7df17f 100644 --- a/modules/ppcp-order-tracking/src/Endpoint/OrderTrackingEndpoint.php +++ b/modules/ppcp-order-tracking/src/Endpoint/OrderTrackingEndpoint.php @@ -117,14 +117,17 @@ class OrderTrackingEndpoint { $url = trailingslashit( $this->host ) . 'v1/shipping/trackers-batch'; $body = array( - 'trackers' => array( $data ), + 'trackers' => array( (array) apply_filters( 'woocommerce_paypal_payments_tracking_data_before_sending', $data, $order_id ) ), ); - $args = array( + $args = array( 'method' => 'POST', 'headers' => $this->request_headers(), 'body' => wp_json_encode( $body ), ); + + do_action( 'woocommerce_paypal_payments_before_tracking_is_added', $order_id, $data ); + $response = $this->request( $url, $args ); if ( is_wp_error( $response ) ) { @@ -169,6 +172,8 @@ class OrderTrackingEndpoint { } update_post_meta( $order_id, '_ppcp_paypal_tracking_number', $data['tracking_number'] ?? '' ); + + do_action( 'woocommerce_paypal_payments_after_tracking_is_added', $order_id, $response ); } /** @@ -243,9 +248,11 @@ class OrderTrackingEndpoint { $args = array( 'method' => 'PUT', 'headers' => $this->request_headers(), - 'body' => wp_json_encode( $data ), + 'body' => wp_json_encode( (array) apply_filters( 'woocommerce_paypal_payments_tracking_data_before_update', $data, $order_id ) ), ); + do_action( 'woocommerce_paypal_payments_before_tracking_is_updated', $order_id, $data ); + $response = $this->request( $url, $args ); if ( is_wp_error( $response ) ) { @@ -290,6 +297,8 @@ class OrderTrackingEndpoint { } update_post_meta( $order_id, '_ppcp_paypal_tracking_number', $data['tracking_number'] ?? '' ); + + do_action( 'woocommerce_paypal_payments_after_tracking_is_updated', $order_id, $response ); } /** diff --git a/modules/ppcp-subscription/src/RenewalHandler.php b/modules/ppcp-subscription/src/RenewalHandler.php index 771a57c9d..2b96b2f34 100644 --- a/modules/ppcp-subscription/src/RenewalHandler.php +++ b/modules/ppcp-subscription/src/RenewalHandler.php @@ -203,12 +203,8 @@ class RenewalHandler { $this->handle_new_order_status( $order, $wc_order ); - if ( $this->capture_authorized_downloads( $order ) && AuthorizedPaymentsProcessor::SUCCESSFUL === $this->authorized_payments_processor->process( $wc_order ) ) { - $wc_order->add_order_note( - __( 'Payment successfully captured.', 'woocommerce-paypal-payments' ) - ); - $wc_order->update_meta_data( AuthorizedPaymentsProcessor::CAPTURED_META_KEY, 'true' ); - $wc_order->update_status( 'completed' ); + if ( $this->capture_authorized_downloads( $order ) ) { + $this->authorized_payments_processor->capture_authorized_payment( $wc_order ); } } diff --git a/modules/ppcp-vaulting/src/PaymentTokenChecker.php b/modules/ppcp-vaulting/src/PaymentTokenChecker.php index 849c7a08f..e798ec139 100644 --- a/modules/ppcp-vaulting/src/PaymentTokenChecker.php +++ b/modules/ppcp-vaulting/src/PaymentTokenChecker.php @@ -16,6 +16,7 @@ use WC_Order; use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PaymentsEndpoint; use WooCommerce\PayPalCommerce\ApiClient\Repository\OrderRepository; use WooCommerce\PayPalCommerce\Subscription\FreeTrialHandlerTrait; +use WooCommerce\PayPalCommerce\WcGateway\Exception\NotFoundException; use WooCommerce\PayPalCommerce\WcGateway\Gateway\CardButtonGateway; use WooCommerce\PayPalCommerce\WcGateway\Gateway\CreditCardGateway; use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway; @@ -29,6 +30,8 @@ class PaymentTokenChecker { use FreeTrialHandlerTrait; + const VAULTING_FAILED_META_KEY = '_ppcp_vaulting_failed'; + /** * The payment token repository. * @@ -115,39 +118,74 @@ class PaymentTokenChecker { return; } - $tokens = $this->payment_token_repository->all_for_user_id( $customer_id ); - if ( $tokens ) { - try { - if ( $this->is_free_trial_order( $wc_order ) ) { - if ( in_array( $wc_order->get_payment_method(), array( CreditCardGateway::ID, CardButtonGateway::ID ), true ) - || ( PayPalGateway::ID === $wc_order->get_payment_method() && 'card' === $wc_order->get_meta( PayPalGateway::ORDER_PAYMENT_SOURCE_META_KEY ) ) - ) { - $order = $this->order_repository->for_wc_order( $wc_order ); - $this->authorized_payments_processor->void_authorizations( $order ); - $wc_order->payment_complete(); - } - - return; - } - - $this->capture_authorized_payment( $wc_order ); - } catch ( Exception $exception ) { - $this->logger->error( $exception->getMessage() ); + if ( $this->is_free_trial_order( $wc_order ) ) { + if ( in_array( $wc_order->get_payment_method(), array( CreditCardGateway::ID, CardButtonGateway::ID ), true ) + || ( PayPalGateway::ID === $wc_order->get_payment_method() && 'card' === $wc_order->get_meta( PayPalGateway::ORDER_PAYMENT_SOURCE_META_KEY ) ) + ) { + $order = $this->order_repository->for_wc_order( $wc_order ); + $this->authorized_payments_processor->void_authorizations( $order ); + $wc_order->payment_complete(); } return; } - $this->logger->error( "Payment for subscription parent order #{$order_id} was not saved on PayPal." ); + $tokens = $this->payment_token_repository->all_for_user_id( $customer_id ); + if ( $tokens ) { + try { + $this->capture_authorized_payment( $wc_order ); + } catch ( Exception $exception ) { + $this->logger->warning( $exception->getMessage() ); + } - try { - $order = $this->order_repository->for_wc_order( $wc_order ); - $this->authorized_payments_processor->void_authorizations( $order ); - } catch ( RuntimeException $exception ) { - $this->logger->warning( $exception->getMessage() ); + return; } - $this->update_failed_status( $wc_order ); + try { + $subscription_behavior_when_fails = $this->settings->get( 'subscription_behavior_when_vault_fails' ); + } catch ( NotFoundException $exception ) { + return; + } + + switch ( $subscription_behavior_when_fails ) { + case 'void_auth': + $order = $this->order_repository->for_wc_order( $wc_order ); + $this->authorized_payments_processor->void_authorizations( $order ); + $this->logger->warning( "Payment for subscription parent order #{$order_id} was not saved at PayPal." ); + $this->update_failed_status( $wc_order ); + break; + case 'capture_auth': + try { + $this->capture_authorized_payment( $wc_order ); + } catch ( Exception $exception ) { + $this->logger->warning( $exception->getMessage() ); + return; + } + + $subscriptions = function_exists( 'wcs_get_subscriptions_for_order' ) ? wcs_get_subscriptions_for_order( $wc_order ) : array(); + foreach ( $subscriptions as $subscription ) { + try { + $subscription->set_requires_manual_renewal( true ); + $subscription->save(); + + $message = __( 'Subscription set to Manual Renewal because payment method was not saved at PayPal.', 'woocommerce-paypal-payments' ); + $wc_order->add_order_note( $message ); + + } catch ( Exception $exception ) { + $this->logger->warning( "Could not update payment method on subscription #{$subscription->get_id()} " . $exception->getMessage() ); + } + } + break; + case 'capture_auth_ignore': + try { + $this->capture_authorized_payment( $wc_order ); + } catch ( Exception $exception ) { + $this->logger->warning( $exception->getMessage() ); + return; + } + + break; + } } /** @@ -170,7 +208,7 @@ class PaymentTokenChecker { * @param WC_Order $wc_order The WC order. */ private function update_failed_status( WC_Order $wc_order ): void { - $error_message = __( 'Could not process order because it was not possible to save the payment on PayPal.', 'woocommerce-paypal-payments' ); + $error_message = __( 'Subscription payment failed. Payment method was not saved at PayPal.', 'woocommerce-paypal-payments' ); $wc_order->update_status( 'failed', $error_message ); /** diff --git a/modules/ppcp-vaulting/src/VaultingModule.php b/modules/ppcp-vaulting/src/VaultingModule.php index 99184f096..a680d580c 100644 --- a/modules/ppcp-vaulting/src/VaultingModule.php +++ b/modules/ppcp-vaulting/src/VaultingModule.php @@ -13,7 +13,12 @@ use Dhii\Container\ServiceProvider; use Dhii\Modular\Module\ModuleInterface; use Interop\Container\ServiceProviderInterface; use Psr\Container\ContainerInterface; +use Psr\Log\LoggerInterface; +use WC_Order; +use WooCommerce\PayPalCommerce\Subscription\Helper\SubscriptionHelper; use WooCommerce\PayPalCommerce\Vaulting\Endpoint\DeletePaymentTokenEndpoint; +use WooCommerce\PayPalCommerce\WcGateway\Exception\NotFoundException; +use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings; /** * Class StatusReportModule @@ -35,6 +40,7 @@ class VaultingModule implements ModuleInterface { * {@inheritDoc} * * @param ContainerInterface $container A services container instance. + * @throws NotFoundException When service could not be found. */ public function run( ContainerInterface $container ): void { @@ -144,6 +150,100 @@ class VaultingModule implements ModuleInterface { 10, 3 ); + + $this->filterFailedVaultingEmailsForSubscriptionOrders( $container ); + } + + /** + * 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' ); + + /** + * The Gateway settings. + * + * @var Settings $settings + */ + $settings = $container->get( 'wcgateway.settings' ); + + $vault_failed = get_post_meta( $order->get_id(), PaymentTokenChecker::VAULTING_FAILED_META_KEY ); + if ( $subscription_helper->has_subscription( $order->get_id() ) && ! empty( $vault_failed ) ) { + $subscription_behavior_when_vault_fails_setting_name = 'subscription_behavior_when_vault_fails'; + $subscription_behavior_when_vault_fails = $settings->get( $subscription_behavior_when_vault_fails_setting_name ); + + $logger->info( "Adding vaulting failure info to email for order #{$order->get_id()}." ); + + if ( $subscription_behavior_when_vault_fails === '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 ( $subscription_behavior_when_vault_fails === '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' ); + + /** + * The Gateway settings. + * + * @var Settings $settings + */ + $settings = $container->get( 'wcgateway.settings' ); + + $vault_failed = get_post_meta( $order->get_id(), PaymentTokenChecker::VAULTING_FAILED_META_KEY ); + if ( $subscription_helper->has_subscription( $order->get_id() ) && ! empty( $vault_failed ) ) { + $subscription_behavior_when_vault_fails_setting_name = 'subscription_behavior_when_vault_fails'; + $subscription_behavior_when_vault_fails = $settings->get( $subscription_behavior_when_vault_fails_setting_name ); + + $logger->info( "Changing subscription auto-renewal status for order #{$order->get_id()}." ); + + if ( $subscription_behavior_when_vault_fails === '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-wc-gateway/resources/js/gateway-settings.js b/modules/ppcp-wc-gateway/resources/js/gateway-settings.js index 8e8cfe21b..cf9ee45bd 100644 --- a/modules/ppcp-wc-gateway/resources/js/gateway-settings.js +++ b/modules/ppcp-wc-gateway/resources/js/gateway-settings.js @@ -69,5 +69,9 @@ togglePayLater() vaultingCheckboxes.forEach(node => node.addEventListener('change', togglePayLater)); + + if(PayPalCommerceGatewaySettings.is_subscriptions_plugin_active !== '1') { + document.getElementById('field-subscription_behavior_when_vault_fails').style.display = 'none'; + } } ); diff --git a/modules/ppcp-wc-gateway/services.php b/modules/ppcp-wc-gateway/services.php index 62590006a..bc94103cc 100644 --- a/modules/ppcp-wc-gateway/services.php +++ b/modules/ppcp-wc-gateway/services.php @@ -243,6 +243,14 @@ return array( } } + $dcc_product_status = $container->get( 'wcgateway.helper.dcc-product-status' ); + assert( $dcc_product_status instanceof DCCProductStatus ); + $dcc_applies = $container->get( 'api.helpers.dccapplies' ); + assert( $dcc_applies instanceof DccApplies ); + if ( ! $dcc_product_status->dcc_is_active() || ! $dcc_applies->for_country_currency() ) { + unset( $sections['ppcp-credit-card-gateway'] ); + } + return $sections; }, 'wcgateway.settings.status' => static function ( ContainerInterface $container ): SettingsStatus { @@ -394,7 +402,7 @@ return array( assert( $onboarding_options_renderer instanceof OnboardingOptionsRenderer ); $fields = array( - 'checkout_settings_heading' => array( + 'checkout_settings_heading' => array( 'heading' => __( 'PayPal Checkout Settings', 'woocommerce-paypal-payments' ), 'type' => 'ppcp-heading', 'screens' => array( @@ -404,7 +412,7 @@ return array( 'requirements' => array(), 'gateway' => 'paypal', ), - 'title' => array( + 'title' => array( 'title' => __( 'Title', 'woocommerce-paypal-payments' ), 'type' => 'text', 'description' => __( @@ -420,7 +428,7 @@ return array( 'requirements' => array(), 'gateway' => 'paypal', ), - 'dcc_enabled' => array( + 'dcc_enabled' => array( 'title' => __( 'Enable/Disable', 'woocommerce-paypal-payments' ), 'desc_tip' => true, 'description' => __( 'Once enabled, the Credit Card option will show up in the checkout.', 'woocommerce-paypal-payments' ), @@ -435,7 +443,7 @@ return array( State::STATE_ONBOARDED, ), ), - 'dcc_gateway_title' => array( + 'dcc_gateway_title' => array( 'title' => __( 'Title', 'woocommerce-paypal-payments' ), 'type' => 'text', 'description' => __( @@ -452,7 +460,7 @@ return array( ), 'gateway' => 'dcc', ), - 'description' => array( + 'description' => array( 'title' => __( 'Description', 'woocommerce-paypal-payments' ), 'type' => 'text', 'desc_tip' => true, @@ -471,7 +479,7 @@ return array( 'requirements' => array(), 'gateway' => 'paypal', ), - 'intent' => array( + 'intent' => array( 'title' => __( 'Intent', 'woocommerce-paypal-payments' ), 'type' => 'select', 'class' => array(), @@ -493,7 +501,7 @@ return array( 'requirements' => array(), 'gateway' => 'paypal', ), - 'capture_for_virtual_only' => array( + 'capture_for_virtual_only' => array( 'title' => __( 'Capture Virtual-Only Orders ', 'woocommerce-paypal-payments' ), 'type' => 'checkbox', 'default' => false, @@ -510,7 +518,7 @@ return array( 'requirements' => array(), 'gateway' => 'paypal', ), - 'payee_preferred' => array( + 'payee_preferred' => array( 'title' => __( 'Instant Payments ', 'woocommerce-paypal-payments' ), 'type' => 'checkbox', 'default' => false, @@ -527,7 +535,7 @@ return array( 'requirements' => array(), 'gateway' => 'paypal', ), - 'brand_name' => array( + 'brand_name' => array( 'title' => __( 'Brand Name', 'woocommerce-paypal-payments' ), 'type' => 'text', 'default' => get_bloginfo( 'name' ), @@ -543,7 +551,7 @@ return array( 'requirements' => array(), 'gateway' => 'paypal', ), - 'landing_page' => array( + 'landing_page' => array( 'title' => __( 'Landing Page', 'woocommerce-paypal-payments' ), 'type' => 'select', 'class' => array(), @@ -565,7 +573,7 @@ return array( 'requirements' => array(), 'gateway' => 'paypal', ), - 'disable_funding' => array( + 'disable_funding' => array( 'title' => __( 'Hide Funding Source(s)', 'woocommerce-paypal-payments' ), 'type' => 'ppcp-multiselect', 'class' => array(), @@ -589,7 +597,7 @@ return array( 'requirements' => array(), 'gateway' => 'paypal', ), - 'vault_enabled' => array( + 'vault_enabled' => array( 'title' => __( 'Vaulting', 'woocommerce-paypal-payments' ), 'type' => 'checkbox', 'desc_tip' => true, @@ -603,7 +611,27 @@ return array( 'gateway' => array( 'paypal', 'dcc' ), 'input_class' => $container->get( 'wcgateway.helper.vaulting-scope' ) ? array() : array( 'ppcp-disabled-checkbox' ), ), - 'card_billing_data_mode' => array( + 'subscription_behavior_when_vault_fails' => array( + 'title' => __( 'Subscription capture behavior if Vault fails', 'woocommerce-paypal-payments' ), + 'type' => 'select', + 'class' => array(), + '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', 'dcc' ), + ), + 'card_billing_data_mode' => array( 'title' => __( 'Card billing data handling', 'woocommerce-paypal-payments' ), 'type' => 'select', 'class' => array(), @@ -623,7 +651,7 @@ return array( 'requirements' => array(), 'gateway' => array( 'paypal', CardButtonGateway::ID ), ), - 'allow_card_button_gateway' => array( + 'allow_card_button_gateway' => array( 'title' => __( 'Separate Card Button from PayPal gateway', 'woocommerce-paypal-payments' ), 'type' => 'checkbox', 'desc_tip' => true, @@ -639,7 +667,7 @@ return array( ), // General button styles. - 'button_style_heading' => array( + 'button_style_heading' => array( 'heading' => __( 'Checkout', 'woocommerce-paypal-payments' ), 'type' => 'ppcp-heading', 'screens' => array( @@ -650,7 +678,7 @@ return array( 'gateway' => 'paypal', 'description' => __( 'Customize the appearance of PayPal Checkout on the checkout page.', 'woocommerce-paypal-payments' ), ), - 'button_enabled' => array( + 'button_enabled' => array( 'title' => __( 'Enable buttons on Checkout', 'woocommerce-paypal-payments' ), 'type' => 'checkbox', 'label' => __( 'Enable on Checkout', 'woocommerce-paypal-payments' ), @@ -662,7 +690,7 @@ return array( 'requirements' => array(), 'gateway' => 'paypal', ), - 'button_layout' => array( + 'button_layout' => array( 'title' => __( 'Button Layout', 'woocommerce-paypal-payments' ), 'type' => 'select', 'class' => array(), @@ -684,7 +712,7 @@ return array( 'requirements' => array(), 'gateway' => 'paypal', ), - 'button_tagline' => array( + 'button_tagline' => array( 'title' => __( 'Tagline', 'woocommerce-paypal-payments' ), 'type' => 'checkbox', 'default' => true, @@ -701,7 +729,7 @@ return array( 'requirements' => array(), 'gateway' => 'paypal', ), - 'button_label' => array( + 'button_label' => array( 'title' => __( 'Button Label', 'woocommerce-paypal-payments' ), 'type' => 'select', 'class' => array(), @@ -728,7 +756,7 @@ return array( 'requirements' => array(), 'gateway' => 'paypal', ), - 'button_color' => array( + 'button_color' => array( 'title' => __( 'Color', 'woocommerce-paypal-payments' ), 'type' => 'select', 'class' => array(), @@ -752,7 +780,7 @@ return array( 'requirements' => array(), 'gateway' => 'paypal', ), - 'button_shape' => array( + 'button_shape' => array( 'title' => __( 'Shape', 'woocommerce-paypal-payments' ), 'type' => 'select', 'class' => array(), @@ -774,7 +802,7 @@ return array( 'requirements' => array(), 'gateway' => 'paypal', ), - 'message_heading' => array( + 'message_heading' => array( 'heading' => __( 'Pay Later on Checkout', 'woocommerce-paypal-payments' ), 'type' => 'ppcp-heading', 'screens' => array( @@ -786,7 +814,7 @@ return array( 'description' => str_replace( '', '', __( 'Displays Pay Later messaging for available offers. Restrictions apply. Click here to learn more. Pay Later button will show for eligible buyers and PayPal determines eligibility.', 'woocommerce-paypal-payments' ) ), 'class' => array( 'ppcp-subheading' ), ), - 'message_enabled' => array( + 'message_enabled' => array( 'title' => __( 'Enable message on Checkout', 'woocommerce-paypal-payments' ), 'type' => 'checkbox', 'label' => sprintf( $container->get( 'wcgateway.settings.fields.pay-later-label' ), __( 'Enable on Checkout', 'woocommerce-paypal-payments' ) ), @@ -798,7 +826,7 @@ return array( 'requirements' => array( 'messages' ), 'gateway' => 'paypal', ), - 'message_layout' => array( + 'message_layout' => array( 'title' => __( 'Pay Later Messaging layout', 'woocommerce-paypal-payments' ), 'type' => 'select', 'class' => array(), @@ -820,7 +848,7 @@ return array( 'requirements' => array( 'messages' ), 'gateway' => 'paypal', ), - 'message_logo' => array( + 'message_logo' => array( 'title' => __( 'Pay Later Messaging logo', 'woocommerce-paypal-payments' ), 'type' => 'select', 'class' => array(), @@ -844,7 +872,7 @@ return array( 'requirements' => array( 'messages' ), 'gateway' => 'paypal', ), - 'message_position' => array( + 'message_position' => array( 'title' => __( 'Pay Later Messaging logo position', 'woocommerce-paypal-payments' ), 'type' => 'select', 'class' => array(), @@ -867,7 +895,7 @@ return array( 'requirements' => array( 'messages' ), 'gateway' => 'paypal', ), - 'message_color' => array( + 'message_color' => array( 'title' => __( 'Pay Later Messaging text color', 'woocommerce-paypal-payments' ), 'type' => 'select', 'class' => array(), @@ -891,7 +919,7 @@ return array( 'requirements' => array( 'messages' ), 'gateway' => 'paypal', ), - 'message_flex_color' => array( + 'message_flex_color' => array( 'title' => __( 'Pay Later Messaging color', 'woocommerce-paypal-payments' ), 'type' => 'select', 'class' => array(), @@ -918,7 +946,7 @@ return array( 'requirements' => array( 'messages' ), 'gateway' => 'paypal', ), - 'message_flex_ratio' => array( + 'message_flex_ratio' => array( 'title' => __( 'Pay Later Messaging ratio', 'woocommerce-paypal-payments' ), 'type' => 'select', 'class' => array(), @@ -944,7 +972,7 @@ return array( ), // Single product page. - 'button_product_heading' => array( + 'button_product_heading' => array( 'heading' => __( 'Single Product Page', 'woocommerce-paypal-payments' ), 'type' => 'ppcp-heading', 'screens' => array( @@ -955,7 +983,7 @@ return array( 'gateway' => 'paypal', 'description' => __( 'Customize the appearance of PayPal Checkout on the single product page.', 'woocommerce-paypal-payments' ), ), - 'button_product_enabled' => array( + 'button_product_enabled' => array( 'title' => __( 'Enable buttons on Single Product', 'woocommerce-paypal-payments' ), 'type' => 'checkbox', 'label' => __( 'Enable on Single Product', 'woocommerce-paypal-payments' ), @@ -967,7 +995,7 @@ return array( 'requirements' => array(), 'gateway' => 'paypal', ), - 'button_product_layout' => array( + 'button_product_layout' => array( 'title' => __( 'Button Layout', 'woocommerce-paypal-payments' ), 'type' => 'select', 'class' => array(), @@ -989,7 +1017,7 @@ return array( 'requirements' => array(), 'gateway' => 'paypal', ), - 'button_product_tagline' => array( + 'button_product_tagline' => array( 'title' => __( 'Tagline', 'woocommerce-paypal-payments' ), 'type' => 'checkbox', 'label' => __( 'Enable tagline', 'woocommerce-paypal-payments' ), @@ -1006,7 +1034,7 @@ return array( 'requirements' => array(), 'gateway' => 'paypal', ), - 'button_product_label' => array( + 'button_product_label' => array( 'title' => __( 'Button Label', 'woocommerce-paypal-payments' ), 'type' => 'select', 'class' => array(), @@ -1033,7 +1061,7 @@ return array( 'requirements' => array(), 'gateway' => 'paypal', ), - 'button_product_color' => array( + 'button_product_color' => array( 'title' => __( 'Color', 'woocommerce-paypal-payments' ), 'type' => 'select', 'class' => array(), @@ -1057,7 +1085,7 @@ return array( 'requirements' => array(), 'gateway' => 'paypal', ), - 'button_product_shape' => array( + 'button_product_shape' => array( 'title' => __( 'Shape', 'woocommerce-paypal-payments' ), 'type' => 'select', 'class' => array(), @@ -1080,7 +1108,7 @@ return array( 'gateway' => 'paypal', ), - 'message_product_heading' => array( + 'message_product_heading' => array( 'heading' => __( 'Pay Later on Single Product Page', 'woocommerce-paypal-payments' ), 'type' => 'ppcp-heading', 'screens' => array( @@ -1092,7 +1120,7 @@ return array( 'description' => str_replace( '', '', __( 'Displays Pay Later messaging for available offers. Restrictions apply. Click here to learn more. Pay Later button will show for eligible buyers and PayPal determines eligibility.', 'woocommerce-paypal-payments' ) ), 'class' => array( 'ppcp-subheading' ), ), - 'message_product_enabled' => array( + 'message_product_enabled' => array( 'title' => __( 'Enable message on Single Product', 'woocommerce-paypal-payments' ), 'type' => 'checkbox', 'label' => sprintf( $container->get( 'wcgateway.settings.fields.pay-later-label' ), __( 'Enable on Single Product', 'woocommerce-paypal-payments' ) ), @@ -1104,7 +1132,7 @@ return array( 'requirements' => array( 'messages' ), 'gateway' => 'paypal', ), - 'message_product_layout' => array( + 'message_product_layout' => array( 'title' => __( 'Pay Later Messaging layout', 'woocommerce-paypal-payments' ), 'type' => 'select', 'class' => array(), @@ -1126,7 +1154,7 @@ return array( 'requirements' => array( 'messages' ), 'gateway' => 'paypal', ), - 'message_product_logo' => array( + 'message_product_logo' => array( 'title' => __( 'Pay Later Messaging logo', 'woocommerce-paypal-payments' ), 'type' => 'select', 'class' => array(), @@ -1150,7 +1178,7 @@ return array( 'requirements' => array( 'messages' ), 'gateway' => 'paypal', ), - 'message_product_position' => array( + 'message_product_position' => array( 'title' => __( 'Pay Later Messaging logo position', 'woocommerce-paypal-payments' ), 'type' => 'select', 'class' => array(), @@ -1173,7 +1201,7 @@ return array( 'requirements' => array( 'messages' ), 'gateway' => 'paypal', ), - 'message_product_color' => array( + 'message_product_color' => array( 'title' => __( 'Pay Later Messaging text color', 'woocommerce-paypal-payments' ), 'type' => 'select', 'class' => array(), @@ -1197,7 +1225,7 @@ return array( 'requirements' => array( 'messages' ), 'gateway' => 'paypal', ), - 'message_product_flex_color' => array( + 'message_product_flex_color' => array( 'title' => __( 'Pay Later Messaging color', 'woocommerce-paypal-payments' ), 'type' => 'select', 'class' => array(), @@ -1224,7 +1252,7 @@ return array( 'requirements' => array( 'messages' ), 'gateway' => 'paypal', ), - 'message_product_flex_ratio' => array( + 'message_product_flex_ratio' => array( 'title' => __( 'Pay Later Messaging ratio', 'woocommerce-paypal-payments' ), 'type' => 'select', 'class' => array(), @@ -1250,7 +1278,7 @@ return array( ), // Cart settings. - 'button_cart_heading' => array( + 'button_cart_heading' => array( 'heading' => __( 'Cart', 'woocommerce-paypal-payments' ), 'type' => 'ppcp-heading', 'screens' => array( @@ -1261,7 +1289,7 @@ return array( 'gateway' => 'paypal', 'description' => __( 'Customize the appearance of PayPal Checkout on the cart page.', 'woocommerce-paypal-payments' ), ), - 'button_cart_enabled' => array( + 'button_cart_enabled' => array( 'title' => __( 'Buttons on Cart', 'woocommerce-paypal-payments' ), 'type' => 'checkbox', 'label' => __( 'Enable on Cart', 'woocommerce-paypal-payments' ), @@ -1273,7 +1301,7 @@ return array( 'requirements' => array(), 'gateway' => 'paypal', ), - 'button_cart_layout' => array( + 'button_cart_layout' => array( 'title' => __( 'Button Layout', 'woocommerce-paypal-payments' ), 'type' => 'select', 'class' => array(), @@ -1295,7 +1323,7 @@ return array( 'requirements' => array(), 'gateway' => 'paypal', ), - 'button_cart_tagline' => array( + 'button_cart_tagline' => array( 'title' => __( 'Tagline', 'woocommerce-paypal-payments' ), 'type' => 'checkbox', 'label' => __( 'Enable tagline', 'woocommerce-paypal-payments' ), @@ -1312,7 +1340,7 @@ return array( 'requirements' => array(), 'gateway' => 'paypal', ), - 'button_cart_label' => array( + 'button_cart_label' => array( 'title' => __( 'Button Label', 'woocommerce-paypal-payments' ), 'type' => 'select', 'class' => array(), @@ -1339,7 +1367,7 @@ return array( 'requirements' => array(), 'gateway' => 'paypal', ), - 'button_cart_color' => array( + 'button_cart_color' => array( 'title' => __( 'Color', 'woocommerce-paypal-payments' ), 'type' => 'select', 'class' => array(), @@ -1363,7 +1391,7 @@ return array( 'requirements' => array(), 'gateway' => 'paypal', ), - 'button_cart_shape' => array( + 'button_cart_shape' => array( 'title' => __( 'Shape', 'woocommerce-paypal-payments' ), 'type' => 'select', 'class' => array(), @@ -1386,7 +1414,7 @@ return array( 'gateway' => 'paypal', ), - 'message_cart_heading' => array( + 'message_cart_heading' => array( 'heading' => __( 'Pay Later on Cart', 'woocommerce-paypal-payments' ), 'type' => 'ppcp-heading', 'screens' => array( @@ -1398,7 +1426,7 @@ return array( 'description' => str_replace( '', '', __( 'Displays Pay Later messaging for available offers. Restrictions apply. Click here to learn more. Pay Later button will show for eligible buyers and PayPal determines eligibility.', 'woocommerce-paypal-payments' ) ), 'class' => array( 'ppcp-subheading' ), ), - 'message_cart_enabled' => array( + 'message_cart_enabled' => array( 'title' => __( 'Enable message on Cart', 'woocommerce-paypal-payments' ), 'type' => 'checkbox', 'label' => sprintf( $container->get( 'wcgateway.settings.fields.pay-later-label' ), __( 'Enable on Cart', 'woocommerce-paypal-payments' ) ), @@ -1410,7 +1438,7 @@ return array( 'requirements' => array( 'messages' ), 'gateway' => 'paypal', ), - 'message_cart_layout' => array( + 'message_cart_layout' => array( 'title' => __( 'Pay Later Messaging layout', 'woocommerce-paypal-payments' ), 'type' => 'select', 'class' => array(), @@ -1432,7 +1460,7 @@ return array( 'requirements' => array( 'messages' ), 'gateway' => 'paypal', ), - 'message_cart_logo' => array( + 'message_cart_logo' => array( 'title' => __( 'Pay Later Messaging logo', 'woocommerce-paypal-payments' ), 'type' => 'select', 'class' => array(), @@ -1456,7 +1484,7 @@ return array( 'requirements' => array( 'messages' ), 'gateway' => 'paypal', ), - 'message_cart_position' => array( + 'message_cart_position' => array( 'title' => __( 'Pay Later Messaging logo position', 'woocommerce-paypal-payments' ), 'type' => 'select', 'class' => array(), @@ -1479,7 +1507,7 @@ return array( 'requirements' => array( 'messages' ), 'gateway' => 'paypal', ), - 'message_cart_color' => array( + 'message_cart_color' => array( 'title' => __( 'Pay Later Messaging text color', 'woocommerce-paypal-payments' ), 'type' => 'select', 'class' => array(), @@ -1503,7 +1531,7 @@ return array( 'requirements' => array( 'messages' ), 'gateway' => 'paypal', ), - 'message_cart_flex_color' => array( + 'message_cart_flex_color' => array( 'title' => __( 'Pay Later Messaging color', 'woocommerce-paypal-payments' ), 'type' => 'select', 'class' => array(), @@ -1530,7 +1558,7 @@ return array( 'requirements' => array( 'messages' ), 'gateway' => 'paypal', ), - 'message_cart_flex_ratio' => array( + 'message_cart_flex_ratio' => array( 'title' => __( 'Pay Later Messaging ratio', 'woocommerce-paypal-payments' ), 'type' => 'select', 'class' => array(), @@ -1556,7 +1584,7 @@ return array( ), // Mini cart settings. - 'button_mini-cart_heading' => array( + 'button_mini-cart_heading' => array( 'heading' => __( 'Mini Cart', 'woocommerce-paypal-payments' ), 'type' => 'ppcp-heading', 'screens' => array( @@ -1567,7 +1595,7 @@ return array( 'gateway' => 'paypal', 'description' => __( 'Customize the appearance of PayPal Checkout on the Mini Cart.', 'woocommerce-paypal-payments' ), ), - 'button_mini-cart_enabled' => array( + 'button_mini-cart_enabled' => array( 'title' => __( 'Buttons on Mini Cart', 'woocommerce-paypal-payments' ), 'type' => 'checkbox', 'label' => __( 'Enable on Mini Cart', 'woocommerce-paypal-payments' ), @@ -1579,7 +1607,7 @@ return array( 'requirements' => array(), 'gateway' => 'paypal', ), - 'button_mini-cart_layout' => array( + 'button_mini-cart_layout' => array( 'title' => __( 'Button Layout', 'woocommerce-paypal-payments' ), 'type' => 'select', 'class' => array(), @@ -1601,7 +1629,7 @@ return array( 'requirements' => array(), 'gateway' => 'paypal', ), - 'button_mini-cart_tagline' => array( + 'button_mini-cart_tagline' => array( 'title' => __( 'Tagline', 'woocommerce-paypal-payments' ), 'type' => 'checkbox', 'label' => __( 'Enable tagline', 'woocommerce-paypal-payments' ), @@ -1618,7 +1646,7 @@ return array( 'requirements' => array(), 'gateway' => 'paypal', ), - 'button_mini-cart_label' => array( + 'button_mini-cart_label' => array( 'title' => __( 'Button Label', 'woocommerce-paypal-payments' ), 'type' => 'select', 'class' => array(), @@ -1645,7 +1673,7 @@ return array( 'requirements' => array(), 'gateway' => 'paypal', ), - 'button_mini-cart_color' => array( + 'button_mini-cart_color' => array( 'title' => __( 'Color', 'woocommerce-paypal-payments' ), 'type' => 'select', 'class' => array(), @@ -1669,7 +1697,7 @@ return array( 'requirements' => array(), 'gateway' => 'paypal', ), - 'button_mini-cart_shape' => array( + 'button_mini-cart_shape' => array( 'title' => __( 'Shape', 'woocommerce-paypal-payments' ), 'type' => 'select', 'class' => array(), @@ -1691,7 +1719,7 @@ return array( 'requirements' => array(), 'gateway' => 'paypal', ), - 'button_mini-cart_height' => array( + 'button_mini-cart_height' => array( 'title' => __( 'Button Height', 'woocommerce-paypal-payments' ), 'type' => 'number', 'default' => '35', @@ -1705,7 +1733,7 @@ return array( 'gateway' => 'paypal', ), - 'disable_cards' => array( + 'disable_cards' => array( 'title' => __( 'Disable specific credit cards', 'woocommerce-paypal-payments' ), 'type' => 'ppcp-multiselect', 'class' => array(), @@ -1733,7 +1761,7 @@ return array( ), 'gateway' => 'dcc', ), - 'card_icons' => array( + 'card_icons' => array( 'title' => __( 'Show logo of the following credit cards', 'woocommerce-paypal-payments' ), 'type' => 'ppcp-multiselect', 'class' => array(), @@ -1763,7 +1791,7 @@ return array( ), 'gateway' => 'dcc', ), - '3d_secure_heading' => array( + '3d_secure_heading' => array( 'heading' => __( '3D Secure', 'woocommerce-paypal-payments' ), 'type' => 'ppcp-heading', 'description' => wp_kses_post( @@ -1791,7 +1819,7 @@ return array( ), 'gateway' => 'dcc', ), - '3d_secure_contingency' => array( + '3d_secure_contingency' => array( 'title' => __( 'Contingency for 3D Secure', 'woocommerce-paypal-payments' ), 'type' => 'select', 'description' => sprintf( @@ -1923,7 +1951,12 @@ return array( $settings = $container->get( 'wcgateway.settings' ); $partner_endpoint = $container->get( 'api.endpoint.partners' ); - return new DCCProductStatus( $settings, $partner_endpoint, $container->get( 'dcc.status-cache' ) ); + return new DCCProductStatus( + $settings, + $partner_endpoint, + $container->get( 'dcc.status-cache' ), + $container->get( 'api.helpers.dccapplies' ) + ); }, 'button.helper.messages-disclaimers' => static function ( ContainerInterface $container ): MessagesDisclaimers { @@ -2056,7 +2089,12 @@ return array( }, 'button.helper.vaulting-label' => static function ( ContainerInterface $container ): string { - $vaulting_label = __( 'Enable saved cards and subscription features on your store.', 'woocommerce-paypal-payments' ); + $vaulting_label = sprintf( + // translators: %1$s and %2$s are the opening and closing of HTML tag. + __( 'Enable saved cards, PayPal accounts, and subscription features on your store. Payment methods are saved in the secure %1$sPayPal Vault%2$s.', 'woocommerce-paypal-payments' ), + '', + '' + ); if ( ! $container->get( 'wcgateway.helper.vaulting-scope' ) ) { $vaulting_label .= sprintf( @@ -2071,7 +2109,20 @@ return array( } $vaulting_label .= ''; - $vaulting_label .= __( 'This will disable all Pay Later messaging on your site.', 'woocommerce-paypal-payments' ); + $vaulting_label .= sprintf( + // translators: %1$s, %2$s, %3$s and %4$s are the opening and closing of HTML tag. + __( 'This will disable all %1$sPay Later%2$s features and %3$sAlternative Payment Methods%4$s on your site.', 'woocommerce-paypal-payments' ), + '', + '', + '', + '' + ); $vaulting_label .= '
'; return $vaulting_label; diff --git a/modules/ppcp-wc-gateway/src/Assets/SettingsPageAssets.php b/modules/ppcp-wc-gateway/src/Assets/SettingsPageAssets.php index 7a61aee9d..5926580ff 100644 --- a/modules/ppcp-wc-gateway/src/Assets/SettingsPageAssets.php +++ b/modules/ppcp-wc-gateway/src/Assets/SettingsPageAssets.php @@ -9,7 +9,7 @@ declare(strict_types=1); namespace WooCommerce\PayPalCommerce\WcGateway\Assets; -use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException; +use WooCommerce\PayPalCommerce\Subscription\Helper\SubscriptionHelper; /** * Class SettingsPageAssets @@ -30,15 +30,24 @@ class SettingsPageAssets { */ private $version; + /** + * The subscription helper. + * + * @var SubscriptionHelper + */ + protected $subscription_helper; + /** * Assets constructor. * - * @param string $module_url The url of this module. - * @param string $version The assets version. + * @param string $module_url The url of this module. + * @param string $version The assets version. + * @param SubscriptionHelper $subscription_helper The subscription helper. */ - public function __construct( string $module_url, string $version ) { - $this->module_url = $module_url; - $this->version = $version; + public function __construct( string $module_url, string $version, SubscriptionHelper $subscription_helper ) { + $this->module_url = $module_url; + $this->version = $version; + $this->subscription_helper = $subscription_helper; } /** @@ -96,5 +105,14 @@ class SettingsPageAssets { $this->version, true ); + + // Intent is configured with Authorize and Capture Virtual-Only Orders is not set. + wp_localize_script( + 'ppcp-gateway-settings', + 'PayPalCommerceGatewaySettings', + array( + 'is_subscriptions_plugin_active' => $this->subscription_helper->plugin_is_active(), + ) + ); } } diff --git a/modules/ppcp-wc-gateway/src/Gateway/ProcessPaymentTrait.php b/modules/ppcp-wc-gateway/src/Gateway/ProcessPaymentTrait.php index 25902e227..da17f822b 100644 --- a/modules/ppcp-wc-gateway/src/Gateway/ProcessPaymentTrait.php +++ b/modules/ppcp-wc-gateway/src/Gateway/ProcessPaymentTrait.php @@ -53,8 +53,16 @@ trait ProcessPaymentTrait { * @param int $customer_id The customer ID. */ protected function schedule_saved_payment_check( int $wc_order_id, int $customer_id ): void { + $timestamp = 1 * 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() + ( 1 * MINUTE_IN_SECONDS ), + time() + $timestamp, 'woocommerce_paypal_payments_check_saved_payment', array( 'order_id' => $wc_order_id, diff --git a/modules/ppcp-wc-gateway/src/Helper/DCCProductStatus.php b/modules/ppcp-wc-gateway/src/Helper/DCCProductStatus.php index bd55cfbff..3c60fea55 100644 --- a/modules/ppcp-wc-gateway/src/Helper/DCCProductStatus.php +++ b/modules/ppcp-wc-gateway/src/Helper/DCCProductStatus.php @@ -13,6 +13,7 @@ use Throwable; use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PartnersEndpoint; use WooCommerce\PayPalCommerce\ApiClient\Entity\SellerStatusProduct; use WooCommerce\PayPalCommerce\ApiClient\Helper\Cache; +use WooCommerce\PayPalCommerce\ApiClient\Helper\DccApplies; use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings; /** @@ -49,21 +50,31 @@ class DCCProductStatus { */ private $partners_endpoint; + /** + * The dcc applies helper. + * + * @var DccApplies + */ + protected $dcc_applies; + /** * DccProductStatus constructor. * * @param Settings $settings The Settings. * @param PartnersEndpoint $partners_endpoint The Partner Endpoint. * @param Cache $cache The cache. + * @param DccApplies $dcc_applies The dcc applies helper. */ public function __construct( Settings $settings, PartnersEndpoint $partners_endpoint, - Cache $cache + Cache $cache, + DccApplies $dcc_applies ) { $this->settings = $settings; $this->partners_endpoint = $partners_endpoint; $this->cache = $cache; + $this->dcc_applies = $dcc_applies; } /** @@ -113,7 +124,12 @@ class DCCProductStatus { return true; } } - $this->cache->set( self::DCC_STATUS_CACHE_KEY, false, 3 * MONTH_IN_SECONDS ); + + $expiration = 3 * MONTH_IN_SECONDS; + if ( $this->dcc_applies->for_country_currency() ) { + $expiration = 3 * HOUR_IN_SECONDS; + } + $this->cache->set( self::DCC_STATUS_CACHE_KEY, false, $expiration ); $this->current_status_cache = false; return false; diff --git a/modules/ppcp-wc-gateway/src/Processor/OrderProcessor.php b/modules/ppcp-wc-gateway/src/Processor/OrderProcessor.php index a621e88b5..7b9b80c55 100644 --- a/modules/ppcp-wc-gateway/src/Processor/OrderProcessor.php +++ b/modules/ppcp-wc-gateway/src/Processor/OrderProcessor.php @@ -210,12 +210,8 @@ class OrderProcessor { $this->handle_new_order_status( $order, $wc_order ); - if ( $this->capture_authorized_downloads( $order ) && AuthorizedPaymentsProcessor::SUCCESSFUL === $this->authorized_payments_processor->process( $wc_order ) ) { - $wc_order->add_order_note( - __( 'Payment successfully captured.', 'woocommerce-paypal-payments' ) - ); - $wc_order->update_meta_data( AuthorizedPaymentsProcessor::CAPTURED_META_KEY, 'true' ); - $wc_order->update_status( 'completed' ); + if ( $this->capture_authorized_downloads( $order ) ) { + $this->authorized_payments_processor->capture_authorized_payment( $wc_order ); } $this->last_error = ''; return true; diff --git a/modules/ppcp-wc-gateway/src/Settings/SettingsListener.php b/modules/ppcp-wc-gateway/src/Settings/SettingsListener.php index 936c30633..0b4ff2274 100644 --- a/modules/ppcp-wc-gateway/src/Settings/SettingsListener.php +++ b/modules/ppcp-wc-gateway/src/Settings/SettingsListener.php @@ -281,12 +281,15 @@ class SettingsListener { $credentials_change_status = null; // Cannot detect on Card Processing page. - if ( PayPalGateway::ID === $this->page_id || Settings::CONNECTION_TAB_ID === $this->page_id ) { - $settings['enabled'] = isset( $_POST['woocommerce_ppcp-gateway_enabled'] ) - && 1 === absint( $_POST['woocommerce_ppcp-gateway_enabled'] ); - + if ( Settings::CONNECTION_TAB_ID === $this->page_id ) { $credentials_change_status = $this->determine_credentials_change_status( $settings ); } + + if ( PayPalGateway::ID === $this->page_id ) { + $settings['enabled'] = isset( $_POST['woocommerce_ppcp-gateway_enabled'] ) + && 1 === absint( $_POST['woocommerce_ppcp-gateway_enabled'] ); + } + // phpcs:enable phpcs:disable WordPress.Security.NonceVerification.Missing // phpcs:enable phpcs:disable WordPress.Security.NonceVerification.Missing if ( $credentials_change_status ) { diff --git a/modules/ppcp-wc-gateway/src/Settings/SettingsRenderer.php b/modules/ppcp-wc-gateway/src/Settings/SettingsRenderer.php index 9f98742a4..a14f1828c 100644 --- a/modules/ppcp-wc-gateway/src/Settings/SettingsRenderer.php +++ b/modules/ppcp-wc-gateway/src/Settings/SettingsRenderer.php @@ -443,6 +443,10 @@ $data_rows_html + + + + has( 'wcgateway.url' ) ) { $assets = new SettingsPageAssets( $c->get( 'wcgateway.url' ), - $c->get( 'ppcp.asset-version' ) + $c->get( 'ppcp.asset-version' ), + $c->get( 'subscription.helper' ) ); $assets->register_assets(); } diff --git a/modules/ppcp-webhooks/src/WebhookModule.php b/modules/ppcp-webhooks/src/WebhookModule.php index 11adb289a..bcfa321c1 100644 --- a/modules/ppcp-webhooks/src/WebhookModule.php +++ b/modules/ppcp-webhooks/src/WebhookModule.php @@ -143,6 +143,21 @@ class WebhookModule implements ModuleInterface { $logger->error( 'Failed to load webhooks list: ' . $exception->getMessage() ); } } + + add_action( + 'woocommerce_paypal_payments_gateway_migrate', + static function () use ( $container ) { + $registrar = $container->get( 'webhook.registrar' ); + assert( $registrar instanceof WebhookRegistrar ); + add_action( + 'init', + function () use ( $registrar ) { + $registrar->unregister(); + $registrar->register(); + } + ); + } + ); } /** diff --git a/package.json b/package.json index f249ad618..d7254e1e7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "woocommerce-paypal-payments", - "version": "1.9.3", + "version": "1.9.4", "description": "WooCommerce PayPal Payments", "repository": "https://github.com/woocommerce/woocommerce-paypal-payments", "license": "GPL-2.0", diff --git a/readme.txt b/readme.txt index 2e2fbed94..84132db07 100644 --- a/readme.txt +++ b/readme.txt @@ -4,7 +4,7 @@ Tags: woocommerce, paypal, payments, ecommerce, e-commerce, store, sales, sell, Requires at least: 5.3 Tested up to: 6.0 Requires PHP: 7.1 -Stable tag: 1.9.3 +Stable tag: 1.9.4 License: GPLv2 License URI: http://www.gnu.org/licenses/gpl-2.0.html @@ -81,6 +81,18 @@ Follow the steps below to connect the plugin to your PayPal account: == Changelog == += 1.9.4 = +* Add - Create new connection tab #801 +* Add - Functionality to choose subscription failure behavior #728 +* Fix - Virtual-only orders always move order status to completed #868 +* Fix - PayPal order created twice when context is checkout #832 +* Enhancement - Handle unsupported browsers better #843 +* Enhancement - Combine the Webhooks Status page into a new Connection tab (891) #827 +* Enhancement - Hide PayPal Card Processing tab if not available in country or for merchant #870 +* Enhancement - Resubscribe webhooks on plugin upgrades #838 +* Enhancement - PUI-relevant webhook not subscribed to #842 +* Enhancement - Remove WC logo during onboarding #881 + = 1.9.3 = * Add - Tracking API #792 * Fix - Improve compatibility with Siteground Optimizer plugin #797 diff --git a/tests/PHPUnit/WcGateway/Assets/SettingsPagesAssetsTest.php b/tests/PHPUnit/WcGateway/Assets/SettingsPagesAssetsTest.php index 1827e02cc..23f32d100 100644 --- a/tests/PHPUnit/WcGateway/Assets/SettingsPagesAssetsTest.php +++ b/tests/PHPUnit/WcGateway/Assets/SettingsPagesAssetsTest.php @@ -3,6 +3,7 @@ namespace WooCommerce\PayPalCommerce\WcGateway\Assets; use WooCommerce\PayPalCommerce\ApiClient\Authentication\Bearer; +use WooCommerce\PayPalCommerce\Subscription\Helper\SubscriptionHelper; use WooCommerce\PayPalCommerce\TestCase; use function Brain\Monkey\Functions\when; use Mockery; @@ -13,8 +14,9 @@ class SettingsPagesAssetsTest extends TestCase { $moduleUrl = 'http://example.com/wp-content/plugins/woocommerce-paypal-payments/modules/ppcp-wc-gateway'; $modulePath = '/var/www/html/wp-content/plugins/woocommerce-paypal-payments/modules/ppcp-wc-gateway'; + $subscriptionsHelper = Mockery::mock(SubscriptionHelper::class); - $testee = new SettingsPageAssets($moduleUrl, $modulePath); + $testee = new SettingsPageAssets($moduleUrl, $modulePath, $subscriptionsHelper); when('is_admin') ->justReturn(true); diff --git a/woocommerce-paypal-payments.php b/woocommerce-paypal-payments.php index f4ddc2404..96d2c7336 100644 --- a/woocommerce-paypal-payments.php +++ b/woocommerce-paypal-payments.php @@ -3,13 +3,13 @@ * Plugin Name: WooCommerce PayPal Payments * Plugin URI: https://woocommerce.com/products/woocommerce-paypal-payments/ * Description: PayPal's latest complete payments processing solution. Accept PayPal, Pay Later, credit/debit cards, alternative digital wallets local payment types and bank accounts. Turn on only PayPal options or process a full suite of payment methods. Enable global transaction with extensive currency and country coverage. - * Version: 1.9.3 + * Version: 1.9.4 * Author: WooCommerce * Author URI: https://woocommerce.com/ * License: GPL-2.0 * Requires PHP: 7.1 * WC requires at least: 3.9 - * WC tested up to: 6.8 + * WC tested up to: 6.9 * Text Domain: woocommerce-paypal-payments * * @package WooCommerce\PayPalCommerce