From 038ee9821bcf47dd8098b128cd20603f8fce7688 Mon Sep 17 00:00:00 2001 From: Emili Castells Guasch Date: Mon, 21 Jul 2025 14:04:23 +0200 Subject: [PATCH 1/3] Ensure billing agreement is used as payment token for ppec orders --- modules/ppcp-compat/src/CompatModule.php | 25 ++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/modules/ppcp-compat/src/CompatModule.php b/modules/ppcp-compat/src/CompatModule.php index aec79f6a3..35a3de160 100644 --- a/modules/ppcp-compat/src/CompatModule.php +++ b/modules/ppcp-compat/src/CompatModule.php @@ -10,9 +10,12 @@ declare(strict_types=1); namespace WooCommerce\PayPalCommerce\Compat; use Exception; +use stdClass; use WC_Cart; use WC_Order; use WC_Order_Item_Product; +use WooCommerce\PayPalCommerce\ApiClient\Entity\PaymentToken; +use WooCommerce\PayPalCommerce\Compat\PPEC\PPECHelper; use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ExecutableModule; use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ExtendingModule; use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ModuleClassNameIdTrait; @@ -91,6 +94,28 @@ class CompatModule implements ServiceModule, ExtendingModule, ExecutableModule { $this->legacy_ui_card_payment_mapping( $c ); + // Short-circuit RenewalHandler::get_token_for_customer() to use a Billing Agreement ID for PPEC orders. + add_filter('woocommerce_paypal_payments_subscriptions_get_token_for_customer', function ($token, $customer, $order ) { + if ( PPECHelper::PPEC_GATEWAY_ID === $order->get_payment_method() && wcs_order_contains_renewal( $order ) ) { + $subscriptions = wcs_get_subscriptions_for_renewal_order($order); + + if (!empty($subscriptions)) { + $subscription = reset($subscriptions); // Get first subscription. + $parent_order = $subscription->get_parent(); + + if ($parent_order) { + $billing_agreement_id = $parent_order->get_meta('_ppec_billing_agreement_id', true); + + if ($billing_agreement_id) { + $token = new PaymentToken($billing_agreement_id, new stdClass(), 'BILLING_AGREEMENT'); + } + } + } + } + + return $token; + }, 10, 3); + return true; } From 521099b16d2c8d5a4bb9aba809e54240ef5bd5a9 Mon Sep 17 00:00:00 2001 From: Emili Castells Guasch Date: Mon, 21 Jul 2025 15:27:26 +0200 Subject: [PATCH 2/3] Add billing agreements fallback to existing method instead of new filter --- modules/ppcp-compat/src/CompatModule.php | 22 ------------------- .../src/PPEC/SubscriptionsHandler.php | 17 ++++++++++++-- 2 files changed, 15 insertions(+), 24 deletions(-) diff --git a/modules/ppcp-compat/src/CompatModule.php b/modules/ppcp-compat/src/CompatModule.php index 35a3de160..c0c3db330 100644 --- a/modules/ppcp-compat/src/CompatModule.php +++ b/modules/ppcp-compat/src/CompatModule.php @@ -94,28 +94,6 @@ class CompatModule implements ServiceModule, ExtendingModule, ExecutableModule { $this->legacy_ui_card_payment_mapping( $c ); - // Short-circuit RenewalHandler::get_token_for_customer() to use a Billing Agreement ID for PPEC orders. - add_filter('woocommerce_paypal_payments_subscriptions_get_token_for_customer', function ($token, $customer, $order ) { - if ( PPECHelper::PPEC_GATEWAY_ID === $order->get_payment_method() && wcs_order_contains_renewal( $order ) ) { - $subscriptions = wcs_get_subscriptions_for_renewal_order($order); - - if (!empty($subscriptions)) { - $subscription = reset($subscriptions); // Get first subscription. - $parent_order = $subscription->get_parent(); - - if ($parent_order) { - $billing_agreement_id = $parent_order->get_meta('_ppec_billing_agreement_id', true); - - if ($billing_agreement_id) { - $token = new PaymentToken($billing_agreement_id, new stdClass(), 'BILLING_AGREEMENT'); - } - } - } - } - - return $token; - }, 10, 3); - return true; } diff --git a/modules/ppcp-compat/src/PPEC/SubscriptionsHandler.php b/modules/ppcp-compat/src/PPEC/SubscriptionsHandler.php index 640ab607f..c93293cdd 100644 --- a/modules/ppcp-compat/src/PPEC/SubscriptionsHandler.php +++ b/modules/ppcp-compat/src/PPEC/SubscriptionsHandler.php @@ -125,9 +125,22 @@ class SubscriptionsHandler { public function use_billing_agreement_as_token( $token, $customer, $order ) { if ( PPECHelper::PPEC_GATEWAY_ID === $order->get_payment_method() && wcs_order_contains_renewal( $order ) ) { $billing_agreement_id = $order->get_meta( '_ppec_billing_agreement_id', true ); - if ( $billing_agreement_id ) { - $token = new PaymentToken( $billing_agreement_id, new stdClass(), 'BILLING_AGREEMENT' ); + return new PaymentToken( $billing_agreement_id, new stdClass(), 'BILLING_AGREEMENT' ); + } + + $subscriptions = wcs_get_subscriptions_for_renewal_order( $order ); + if ( ! empty( $subscriptions ) ) { + $subscription = reset( $subscriptions ); // Get first subscription. + $parent_order = $subscription->get_parent(); + + if ( $parent_order ) { + $billing_agreement_id = $parent_order->get_meta( '_ppec_billing_agreement_id', true ); + + if ( $billing_agreement_id ) { + return new PaymentToken( $billing_agreement_id, new stdClass(), 'BILLING_AGREEMENT' ); + } + } } } From 546a775c497b5bfe447ccbdf988fe41cce7ef0c9 Mon Sep 17 00:00:00 2001 From: Emili Castells Guasch Date: Wed, 23 Jul 2025 12:42:44 +0200 Subject: [PATCH 3/3] Remove should_mock_ppec_gateway logic --- modules/ppcp-compat/src/CompatModule.php | 3 - .../src/PPEC/SubscriptionsHandler.php | 77 +------------------ 2 files changed, 1 insertion(+), 79 deletions(-) diff --git a/modules/ppcp-compat/src/CompatModule.php b/modules/ppcp-compat/src/CompatModule.php index c0c3db330..aec79f6a3 100644 --- a/modules/ppcp-compat/src/CompatModule.php +++ b/modules/ppcp-compat/src/CompatModule.php @@ -10,12 +10,9 @@ declare(strict_types=1); namespace WooCommerce\PayPalCommerce\Compat; use Exception; -use stdClass; use WC_Cart; use WC_Order; use WC_Order_Item_Product; -use WooCommerce\PayPalCommerce\ApiClient\Entity\PaymentToken; -use WooCommerce\PayPalCommerce\Compat\PPEC\PPECHelper; use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ExecutableModule; use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ExtendingModule; use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ModuleClassNameIdTrait; diff --git a/modules/ppcp-compat/src/PPEC/SubscriptionsHandler.php b/modules/ppcp-compat/src/PPEC/SubscriptionsHandler.php index c93293cdd..de3ea2cb4 100644 --- a/modules/ppcp-compat/src/PPEC/SubscriptionsHandler.php +++ b/modules/ppcp-compat/src/PPEC/SubscriptionsHandler.php @@ -76,7 +76,7 @@ class SubscriptionsHandler { * @return array */ public function add_mock_ppec_gateway( $gateways ) { - if ( ! isset( $gateways[ PPECHelper::PPEC_GATEWAY_ID ] ) && $this->should_mock_ppec_gateway() ) { + if ( ! isset( $gateways[ PPECHelper::PPEC_GATEWAY_ID ] ) ) { $gateways[ PPECHelper::PPEC_GATEWAY_ID ] = $this->mock_gateway; } @@ -146,79 +146,4 @@ class SubscriptionsHandler { return $token; } - - /** - * Checks whether the mock PPEC gateway should be used or not. - * - * @return bool - */ - private function should_mock_ppec_gateway() { - // Are we processing a renewal? - if ( doing_action( 'woocommerce_scheduled_subscription_payment' ) ) { - return true; - } - - // My Account > Subscriptions. - if ( is_wc_endpoint_url( 'subscriptions' ) ) { - return true; - } - - // phpcs:disable WordPress.Security.NonceVerification - - // Checks that require Subscriptions. - if ( class_exists( \WC_Subscriptions::class ) ) { - // My Account > Subscriptions > (Subscription). - if ( wcs_is_view_subscription_page() ) { - $subscription = wcs_get_subscription( absint( get_query_var( 'view-subscription' ) ) ); - - return ( $subscription && PPECHelper::PPEC_GATEWAY_ID === $subscription->get_payment_method() ); - } - - // Changing payment method? - if ( is_wc_endpoint_url( 'order-pay' ) && isset( $_GET['change_payment_method'] ) ) { - $subscription = wcs_get_subscription( absint( get_query_var( 'order-pay' ) ) ); - - return ( $subscription && PPECHelper::PPEC_GATEWAY_ID === $subscription->get_payment_method() ); - } - - // Early renew (via modal). - if ( isset( $_GET['process_early_renewal'], $_GET['subscription_id'] ) ) { - $subscription = wcs_get_subscription( absint( $_GET['subscription_id'] ) ); - - return ( $subscription && PPECHelper::PPEC_GATEWAY_ID === $subscription->get_payment_method() ); - } - } - - // Admin-only from here onwards. - if ( ! is_admin() ) { - return false; - } - - // Are we saving metadata for a subscription? - if ( doing_action( 'woocommerce_process_shop_order_meta' ) ) { - return true; - } - - // Are we editing an order or subscription tied to PPEC? - $order_id = wc_clean( wp_unslash( $_GET['id'] ?? $_GET['post'] ?? $_POST['post_ID'] ?? '' ) ); - if ( $order_id ) { - $order = wc_get_order( $order_id ); - return ( $order && PPECHelper::PPEC_GATEWAY_ID === $order->get_payment_method() ); - } - - // Are we on the WC > Subscriptions screen? - /** - * Class exist in WooCommerce. - * - * @psalm-suppress UndefinedClass - */ - $post_type_or_page = class_exists( OrderUtil::class ) && OrderUtil::custom_orders_table_usage_is_enabled() - ? wc_clean( wp_unslash( $_GET['page'] ?? '' ) ) - : wc_clean( wp_unslash( $_GET['post_type'] ?? $_POST['post_type'] ?? '' ) ); - if ( $post_type_or_page === 'shop_subscription' || $post_type_or_page === 'wc-orders--shop_subscription' ) { - return true; - } - - return false; - } }