From c3f7e48d465a21e890f3a509b8fbbae71f3c943e Mon Sep 17 00:00:00 2001
From: Pedro Silva
Date: Tue, 15 Aug 2023 11:49:54 +0100
Subject: [PATCH 01/17] Add gateway validation for
woocommerce_order_status_changed filter.
---
modules/ppcp-subscription/src/RenewalHandler.php | 2 +-
.../ppcp-wc-gateway/src/Gateway/GatewayRepository.php | 10 ++++++++++
modules/ppcp-wc-gateway/src/WCGatewayModule.php | 9 +++++++++
3 files changed, 20 insertions(+), 1 deletion(-)
diff --git a/modules/ppcp-subscription/src/RenewalHandler.php b/modules/ppcp-subscription/src/RenewalHandler.php
index cd2385499..1364fa365 100644
--- a/modules/ppcp-subscription/src/RenewalHandler.php
+++ b/modules/ppcp-subscription/src/RenewalHandler.php
@@ -226,7 +226,7 @@ class RenewalHandler {
* @param \WC_Customer $customer The customer.
* @param \WC_Order $wc_order The current WooCommerce order we want to process.
*
- * @return PaymentToken|null
+ * @return PaymentToken|null|false
*/
private function get_token_for_customer( \WC_Customer $customer, \WC_Order $wc_order ) {
/**
diff --git a/modules/ppcp-wc-gateway/src/Gateway/GatewayRepository.php b/modules/ppcp-wc-gateway/src/Gateway/GatewayRepository.php
index 250b1143f..6362fa260 100644
--- a/modules/ppcp-wc-gateway/src/Gateway/GatewayRepository.php
+++ b/modules/ppcp-wc-gateway/src/Gateway/GatewayRepository.php
@@ -44,4 +44,14 @@ class GatewayRepository {
}
);
}
+
+ /**
+ * Indicates if a given gateway ID is registered.
+ *
+ * @param string $gateway_id The gateway ID.
+ * @return bool
+ */
+ public function exists( string $gateway_id ): bool {
+ return in_array( $gateway_id, $this->ppcp_gateway_ids, true );
+ }
}
diff --git a/modules/ppcp-wc-gateway/src/WCGatewayModule.php b/modules/ppcp-wc-gateway/src/WCGatewayModule.php
index 28c610b7e..0e89cbfd4 100644
--- a/modules/ppcp-wc-gateway/src/WCGatewayModule.php
+++ b/modules/ppcp-wc-gateway/src/WCGatewayModule.php
@@ -33,6 +33,7 @@ use WooCommerce\PayPalCommerce\WcGateway\Checkout\DisableGateways;
use WooCommerce\PayPalCommerce\WcGateway\Endpoint\ReturnUrlEndpoint;
use WooCommerce\PayPalCommerce\WcGateway\Exception\NotFoundException;
use WooCommerce\PayPalCommerce\WcGateway\Gateway\CreditCardGateway;
+use WooCommerce\PayPalCommerce\WcGateway\Gateway\GatewayRepository;
use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway;
use WooCommerce\PayPalCommerce\WcGateway\Helper\DCCProductStatus;
use WooCommerce\PayPalCommerce\WcGateway\Helper\PayUponInvoiceProductStatus;
@@ -355,6 +356,14 @@ class WCGatewayModule implements ModuleInterface {
return;
}
+ $gateway_repository = $c->get( 'wcgateway.gateway-repository' );
+ assert( $gateway_repository instanceof GatewayRepository );
+
+ // Only allow to proceed if the payment method is one of our Gateways.
+ if ( ! $gateway_repository->exists( $wc_order->get_payment_method() ) ) {
+ return;
+ }
+
$intent = strtoupper( (string) $wc_order->get_meta( PayPalGateway::INTENT_META_KEY ) );
$captured = wc_string_to_bool( $wc_order->get_meta( AuthorizedPaymentsProcessor::CAPTURED_META_KEY ) );
if ( $intent !== 'AUTHORIZE' || $captured ) {
From 6692c4f2db87e80ba71c2b40c25bbc18e74e23b9 Mon Sep 17 00:00:00 2001
From: Pedro Silva
Date: Tue, 15 Aug 2023 11:52:47 +0100
Subject: [PATCH 02/17] Removed satackey/action-docker-layer-caching from e2e
testing
---
.github/workflows/e2e.yml | 3 ---
1 file changed, 3 deletions(-)
diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml
index 3731a1de4..0bf80c13b 100644
--- a/.github/workflows/e2e.yml
+++ b/.github/workflows/e2e.yml
@@ -12,9 +12,6 @@ jobs:
name: PHP ${{ matrix.php-versions }} WC ${{ matrix.wc-versions }}
steps:
- - uses: satackey/action-docker-layer-caching@v0.0.11
- continue-on-error: true
-
- uses: ddev/github-action-setup-ddev@v1
with:
autostart: false
From b8eed0f324d77116c304d1b1c4085aafb5f17254 Mon Sep 17 00:00:00 2001
From: Pedro Silva
Date: Wed, 16 Aug 2023 11:48:56 +0100
Subject: [PATCH 03/17] Add filters
woocommerce_paypal_payments_cart_line_item_name and
woocommerce_paypal_payments_order_line_item_name.
---
modules/ppcp-api-client/src/ApiModule.php | 15 +++++
.../src/Endpoint/WebhookEndpoint.php | 5 ++
.../src/Processor/OrderProcessor.php | 57 ++++++++++++++++++-
.../src/Handler/PaymentCaptureRefunded.php | 5 ++
.../Processor/OrderProcessorTest.php | 4 +-
5 files changed, 84 insertions(+), 2 deletions(-)
diff --git a/modules/ppcp-api-client/src/ApiModule.php b/modules/ppcp-api-client/src/ApiModule.php
index 95a0efd14..35ae4cc7c 100644
--- a/modules/ppcp-api-client/src/ApiModule.php
+++ b/modules/ppcp-api-client/src/ApiModule.php
@@ -40,6 +40,21 @@ class ApiModule implements ModuleInterface {
WC()->session->set( 'ppcp_fees', $fees );
}
);
+
+ add_filter(
+ 'ppcp_create_order_request_body_data',
+ function( array $data ) use ( $c ) {
+
+ foreach ( $data['purchase_units'] as $purchase_unit_index => $purchase_unit ) {
+ foreach ( $purchase_unit['items'] as $item_index => $item ) {
+ $data['purchase_units'][ $purchase_unit_index ]['items'][ $item_index ]['name'] =
+ apply_filters( 'woocommerce_paypal_payments_cart_line_item_name', $item['name'], $item['cart_item_key'] );
+ }
+ }
+
+ return $data;
+ }
+ );
}
/**
diff --git a/modules/ppcp-api-client/src/Endpoint/WebhookEndpoint.php b/modules/ppcp-api-client/src/Endpoint/WebhookEndpoint.php
index d8cc06dca..68f433a41 100644
--- a/modules/ppcp-api-client/src/Endpoint/WebhookEndpoint.php
+++ b/modules/ppcp-api-client/src/Endpoint/WebhookEndpoint.php
@@ -202,6 +202,11 @@ class WebhookEndpoint {
$status_code = (int) wp_remote_retrieve_response_code( $response );
if ( 204 !== $status_code ) {
$json = null;
+ /**
+ * Use in array as consistency check.
+ *
+ * @psalm-suppress RedundantConditionGivenDocblockType
+ */
if ( is_array( $response ) ) {
$json = json_decode( $response['body'] );
}
diff --git a/modules/ppcp-wc-gateway/src/Processor/OrderProcessor.php b/modules/ppcp-wc-gateway/src/Processor/OrderProcessor.php
index 443fd1cbd..fcb74f4ef 100644
--- a/modules/ppcp-wc-gateway/src/Processor/OrderProcessor.php
+++ b/modules/ppcp-wc-gateway/src/Processor/OrderProcessor.php
@@ -116,6 +116,13 @@ class OrderProcessor {
*/
private $order_helper;
+ /**
+ * Array to store temporary order data changes to restore after processing.
+ *
+ * @var array
+ */
+ private $restore_order_data = array();
+
/**
* OrderProcessor constructor.
*
@@ -292,8 +299,12 @@ class OrderProcessor {
* @return Order
*/
public function patch_order( \WC_Order $wc_order, Order $order ): Order {
+ $this->apply_outbound_order_filters( $wc_order );
$updated_order = $this->order_factory->from_wc_order( $wc_order, $order );
- $order = $this->order_endpoint->patch_order_with( $order, $updated_order );
+ $this->restore_order_from_filters( $wc_order );
+
+ $order = $this->order_endpoint->patch_order_with( $order, $updated_order );
+
return $order;
}
@@ -323,4 +334,48 @@ class OrderProcessor {
true
);
}
+
+ /**
+ * Applies filters to the WC_Order, so they are reflected only on PayPal Order.
+ *
+ * @param WC_Order $wc_order The WoocOmmerce Order.
+ * @return void
+ */
+ private function apply_outbound_order_filters( WC_Order $wc_order ): void {
+ $items = $wc_order->get_items();
+
+ $this->restore_order_data['names'] = array();
+
+ foreach ( $items as $item ) {
+ if ( ! $item instanceof \WC_Order_Item ) {
+ continue;
+ }
+
+ $original_name = $item->get_name();
+ $new_name = apply_filters( 'woocommerce_paypal_payments_order_line_item_name', $original_name, $item->get_id(), $wc_order->get_id() );
+
+ if ( $new_name !== $original_name ) {
+ $this->restore_order_data['names'][ $item->get_id() ] = $original_name;
+ $item->set_name( $new_name );
+ }
+ }
+ }
+
+ /**
+ * Restores the WC_Order to it's state before filters.
+ *
+ * @param WC_Order $wc_order The WooCommerce Order.
+ * @return void
+ */
+ private function restore_order_from_filters( WC_Order $wc_order ): void {
+ if ( is_array( $this->restore_order_data['names'] ) ) {
+ foreach ( $this->restore_order_data['names'] as $wc_item_id => $original_name ) {
+ $wc_item = $wc_order->get_item( $wc_item_id, false );
+
+ if ( $wc_item ) {
+ $wc_item->set_name( $original_name );
+ }
+ }
+ }
+ }
}
diff --git a/modules/ppcp-webhooks/src/Handler/PaymentCaptureRefunded.php b/modules/ppcp-webhooks/src/Handler/PaymentCaptureRefunded.php
index ede513aa2..366fe8d48 100644
--- a/modules/ppcp-webhooks/src/Handler/PaymentCaptureRefunded.php
+++ b/modules/ppcp-webhooks/src/Handler/PaymentCaptureRefunded.php
@@ -101,6 +101,11 @@ class PaymentCaptureRefunded implements RequestHandler {
)
);
if ( is_wp_error( $refund ) ) {
+ /**
+ * Helps to asset type.
+ *
+ * @psalm-suppress RedundantCondition
+ */
assert( $refund instanceof WP_Error );
$message = sprintf(
'Order %1$s could not be refunded. %2$s',
diff --git a/tests/PHPUnit/WcGateway/Processor/OrderProcessorTest.php b/tests/PHPUnit/WcGateway/Processor/OrderProcessorTest.php
index 32a2366ca..97ceca9b5 100644
--- a/tests/PHPUnit/WcGateway/Processor/OrderProcessorTest.php
+++ b/tests/PHPUnit/WcGateway/Processor/OrderProcessorTest.php
@@ -57,6 +57,7 @@ class OrderProcessorTest extends TestCase
->andReturn($payments);
$wcOrder = Mockery::mock(\WC_Order::class);
+ $wcOrder->expects('get_items')->andReturn([]);
$wcOrder->expects('update_meta_data')
->with(PayPalGateway::ORDER_PAYMENT_MODE_META_KEY, 'live');
$wcOrder->shouldReceive('get_id')->andReturn(1);
@@ -193,7 +194,8 @@ class OrderProcessorTest extends TestCase
->andReturn($payments);
$wcOrder = Mockery::mock(\WC_Order::class);
- $orderStatus = Mockery::mock(OrderStatus::class);
+ $wcOrder->expects('get_items')->andReturn([]);
+ $orderStatus = Mockery::mock(OrderStatus::class);
$orderStatus
->shouldReceive('is')
->with(OrderStatus::APPROVED)
From 6e21d965d0ff888bc14fa436932f7292cfaab870 Mon Sep 17 00:00:00 2001
From: Pedro Silva
Date: Wed, 16 Aug 2023 11:54:44 +0100
Subject: [PATCH 04/17] Removed satackey/action-docker-layer-caching from e2e
testing
---
.github/workflows/e2e.yml | 3 ---
1 file changed, 3 deletions(-)
diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml
index 3731a1de4..0bf80c13b 100644
--- a/.github/workflows/e2e.yml
+++ b/.github/workflows/e2e.yml
@@ -12,9 +12,6 @@ jobs:
name: PHP ${{ matrix.php-versions }} WC ${{ matrix.wc-versions }}
steps:
- - uses: satackey/action-docker-layer-caching@v0.0.11
- continue-on-error: true
-
- uses: ddev/github-action-setup-ddev@v1
with:
autostart: false
From 23c524538109603643a501415e858f409d574242 Mon Sep 17 00:00:00 2001
From: Pedro Silva
Date: Wed, 16 Aug 2023 14:07:01 +0100
Subject: [PATCH 05/17] Fix potential notice.
---
modules/ppcp-wc-gateway/src/Processor/OrderProcessor.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/modules/ppcp-wc-gateway/src/Processor/OrderProcessor.php b/modules/ppcp-wc-gateway/src/Processor/OrderProcessor.php
index fcb74f4ef..1fb10ed8c 100644
--- a/modules/ppcp-wc-gateway/src/Processor/OrderProcessor.php
+++ b/modules/ppcp-wc-gateway/src/Processor/OrderProcessor.php
@@ -368,7 +368,7 @@ class OrderProcessor {
* @return void
*/
private function restore_order_from_filters( WC_Order $wc_order ): void {
- if ( is_array( $this->restore_order_data['names'] ) ) {
+ if ( is_array( $this->restore_order_data['names'] ?? null ) ) {
foreach ( $this->restore_order_data['names'] as $wc_item_id => $original_name ) {
$wc_item = $wc_order->get_item( $wc_item_id, false );
From e16a8c4ff300b62053b1b839881cfa58d71ccd79 Mon Sep 17 00:00:00 2001
From: Alex P
Date: Thu, 24 Aug 2023 18:14:23 +0300
Subject: [PATCH 06/17] Do not use transient expiration longer than month to
support memcached
---
.../src/Endpoint/BillingAgreementsEndpoint.php | 2 +-
modules/ppcp-compat/src/PPEC/PPECHelper.php | 2 +-
modules/ppcp-onboarding/src/Helper/OnboardingUrl.php | 2 +-
modules/ppcp-wc-gateway/src/Helper/DCCProductStatus.php | 4 ++--
.../src/Helper/PayUponInvoiceProductStatus.php | 4 ++--
5 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/modules/ppcp-api-client/src/Endpoint/BillingAgreementsEndpoint.php b/modules/ppcp-api-client/src/Endpoint/BillingAgreementsEndpoint.php
index 233c41fe2..5ad4665ca 100644
--- a/modules/ppcp-api-client/src/Endpoint/BillingAgreementsEndpoint.php
+++ b/modules/ppcp-api-client/src/Endpoint/BillingAgreementsEndpoint.php
@@ -135,7 +135,7 @@ class BillingAgreementsEndpoint {
);
} finally {
$this->is_request_logging_enabled = true;
- set_transient( 'ppcp_reference_transaction_enabled', true, 3 * MONTH_IN_SECONDS );
+ set_transient( 'ppcp_reference_transaction_enabled', true, MONTH_IN_SECONDS );
}
return true;
diff --git a/modules/ppcp-compat/src/PPEC/PPECHelper.php b/modules/ppcp-compat/src/PPEC/PPECHelper.php
index 0c175979d..791cb7a22 100644
--- a/modules/ppcp-compat/src/PPEC/PPECHelper.php
+++ b/modules/ppcp-compat/src/PPEC/PPECHelper.php
@@ -98,7 +98,7 @@ class PPECHelper {
set_transient(
'ppcp_has_ppec_subscriptions',
! empty( $result ) ? 'true' : 'false',
- 3 * MONTH_IN_SECONDS
+ MONTH_IN_SECONDS
);
return ! empty( $result );
diff --git a/modules/ppcp-onboarding/src/Helper/OnboardingUrl.php b/modules/ppcp-onboarding/src/Helper/OnboardingUrl.php
index 881d4295f..b00c9b250 100644
--- a/modules/ppcp-onboarding/src/Helper/OnboardingUrl.php
+++ b/modules/ppcp-onboarding/src/Helper/OnboardingUrl.php
@@ -64,7 +64,7 @@ class OnboardingUrl {
*
* @var int
*/
- private $cache_ttl = 3 * MONTH_IN_SECONDS;
+ private $cache_ttl = MONTH_IN_SECONDS;
/**
* The TTL for the previous token cache.
diff --git a/modules/ppcp-wc-gateway/src/Helper/DCCProductStatus.php b/modules/ppcp-wc-gateway/src/Helper/DCCProductStatus.php
index 065f486be..f8d717f08 100644
--- a/modules/ppcp-wc-gateway/src/Helper/DCCProductStatus.php
+++ b/modules/ppcp-wc-gateway/src/Helper/DCCProductStatus.php
@@ -135,12 +135,12 @@ class DCCProductStatus {
$this->settings->set( 'products_dcc_enabled', true );
$this->settings->persist();
$this->current_status_cache = true;
- $this->cache->set( self::DCC_STATUS_CACHE_KEY, 'true', 3 * MONTH_IN_SECONDS );
+ $this->cache->set( self::DCC_STATUS_CACHE_KEY, 'true', MONTH_IN_SECONDS );
return true;
}
}
- $expiration = 3 * MONTH_IN_SECONDS;
+ $expiration = MONTH_IN_SECONDS;
if ( $this->dcc_applies->for_country_currency() ) {
$expiration = 3 * HOUR_IN_SECONDS;
}
diff --git a/modules/ppcp-wc-gateway/src/Helper/PayUponInvoiceProductStatus.php b/modules/ppcp-wc-gateway/src/Helper/PayUponInvoiceProductStatus.php
index 4f0e4ba6c..df70c0779 100644
--- a/modules/ppcp-wc-gateway/src/Helper/PayUponInvoiceProductStatus.php
+++ b/modules/ppcp-wc-gateway/src/Helper/PayUponInvoiceProductStatus.php
@@ -127,11 +127,11 @@ class PayUponInvoiceProductStatus {
$this->settings->set( 'products_pui_enabled', true );
$this->settings->persist();
$this->current_status_cache = true;
- $this->cache->set( self::PUI_STATUS_CACHE_KEY, 'true', 3 * MONTH_IN_SECONDS );
+ $this->cache->set( self::PUI_STATUS_CACHE_KEY, 'true', MONTH_IN_SECONDS );
return true;
}
}
- $this->cache->set( self::PUI_STATUS_CACHE_KEY, 'false', 3 * MONTH_IN_SECONDS );
+ $this->cache->set( self::PUI_STATUS_CACHE_KEY, 'false', MONTH_IN_SECONDS );
$this->current_status_cache = false;
return false;
From c8e1b3cd7f548e49fbf1e95f08bcd11e06c25315 Mon Sep 17 00:00:00 2001
From: Emili Castells Guasch
Date: Wed, 30 Aug 2023 16:58:30 +0200
Subject: [PATCH 07/17] Check for string instead of boolean
---
.../ppcp-api-client/src/Endpoint/BillingAgreementsEndpoint.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/modules/ppcp-api-client/src/Endpoint/BillingAgreementsEndpoint.php b/modules/ppcp-api-client/src/Endpoint/BillingAgreementsEndpoint.php
index 233c41fe2..fb6827e6e 100644
--- a/modules/ppcp-api-client/src/Endpoint/BillingAgreementsEndpoint.php
+++ b/modules/ppcp-api-client/src/Endpoint/BillingAgreementsEndpoint.php
@@ -121,7 +121,7 @@ class BillingAgreementsEndpoint {
*/
public function reference_transaction_enabled(): bool {
try {
- if ( get_transient( 'ppcp_reference_transaction_enabled' ) === true ) {
+ if ( get_transient( 'ppcp_reference_transaction_enabled' ) === '1' ) {
return true;
}
From c38906da9b544eaa8795b3703964c8d853173004 Mon Sep 17 00:00:00 2001
From: Emili Castells Guasch
Date: Fri, 1 Sep 2023 09:48:11 +0200
Subject: [PATCH 08/17] Convert transient vaule to boolean
---
.../ppcp-api-client/src/Endpoint/BillingAgreementsEndpoint.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/modules/ppcp-api-client/src/Endpoint/BillingAgreementsEndpoint.php b/modules/ppcp-api-client/src/Endpoint/BillingAgreementsEndpoint.php
index fb6827e6e..271efc28a 100644
--- a/modules/ppcp-api-client/src/Endpoint/BillingAgreementsEndpoint.php
+++ b/modules/ppcp-api-client/src/Endpoint/BillingAgreementsEndpoint.php
@@ -121,7 +121,7 @@ class BillingAgreementsEndpoint {
*/
public function reference_transaction_enabled(): bool {
try {
- if ( get_transient( 'ppcp_reference_transaction_enabled' ) === '1' ) {
+ if ( wc_string_to_bool( get_transient( 'ppcp_reference_transaction_enabled' ) ) === true ) {
return true;
}
From e819dc68dfa5a1dacfec5d835dced9b32a94c4cc Mon Sep 17 00:00:00 2001
From: Emili Castells Guasch
Date: Mon, 4 Sep 2023 16:33:04 +0200
Subject: [PATCH 09/17] Ensure WC payment token does not exist before creating
it
---
modules/ppcp-vaulting/services.php | 4 ++
.../ppcp-vaulting/src/PaymentTokenHelper.php | 33 +++++++++
.../src/PaymentTokensMigration.php | 31 ++++-----
modules/ppcp-webhooks/services.php | 3 +-
.../src/Handler/VaultPaymentTokenCreated.php | 67 ++++++++++++-------
5 files changed, 93 insertions(+), 45 deletions(-)
create mode 100644 modules/ppcp-vaulting/src/PaymentTokenHelper.php
diff --git a/modules/ppcp-vaulting/services.php b/modules/ppcp-vaulting/services.php
index c274c4549..d18768ea2 100644
--- a/modules/ppcp-vaulting/services.php
+++ b/modules/ppcp-vaulting/services.php
@@ -56,10 +56,14 @@ return array(
'vaulting.payment-token-factory' => function( ContainerInterface $container ): PaymentTokenFactory {
return new PaymentTokenFactory();
},
+ 'vaulting.payment-token-helper' => function( ContainerInterface $container ): PaymentTokenHelper {
+ return new PaymentTokenHelper();
+ },
'vaulting.payment-tokens-migration' => function( ContainerInterface $container ): PaymentTokensMigration {
return new PaymentTokensMigration(
$container->get( 'vaulting.payment-token-factory' ),
$container->get( 'vaulting.repository.payment-token' ),
+ $container->get( 'vaulting.payment-token-helper' ),
$container->get( 'woocommerce.logger.woocommerce' )
);
},
diff --git a/modules/ppcp-vaulting/src/PaymentTokenHelper.php b/modules/ppcp-vaulting/src/PaymentTokenHelper.php
new file mode 100644
index 000000000..22d973a3b
--- /dev/null
+++ b/modules/ppcp-vaulting/src/PaymentTokenHelper.php
@@ -0,0 +1,33 @@
+get_token() === $token_id ) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+}
diff --git a/modules/ppcp-vaulting/src/PaymentTokensMigration.php b/modules/ppcp-vaulting/src/PaymentTokensMigration.php
index 69b6c6fda..a7d3511cc 100644
--- a/modules/ppcp-vaulting/src/PaymentTokensMigration.php
+++ b/modules/ppcp-vaulting/src/PaymentTokensMigration.php
@@ -35,6 +35,13 @@ class PaymentTokensMigration {
*/
private $payment_token_repository;
+ /**
+ * The payment token helper.
+ *
+ * @var PaymentTokenHelper
+ */
+ private $payment_token_helper;
+
/**
* The logger.
*
@@ -47,16 +54,19 @@ class PaymentTokensMigration {
*
* @param PaymentTokenFactory $payment_token_factory The payment token factory.
* @param PaymentTokenRepository $payment_token_repository The payment token repository.
+ * @param PaymentTokenHelper $payment_token_helper The payment token helper.
* @param LoggerInterface $logger The logger.
*/
public function __construct(
PaymentTokenFactory $payment_token_factory,
PaymentTokenRepository $payment_token_repository,
+ PaymentTokenHelper $payment_token_helper,
LoggerInterface $logger
) {
$this->payment_token_factory = $payment_token_factory;
$this->payment_token_repository = $payment_token_repository;
$this->logger = $logger;
+ $this->payment_token_helper = $payment_token_helper;
}
/**
@@ -72,7 +82,7 @@ class PaymentTokensMigration {
foreach ( $tokens as $token ) {
if ( isset( $token->source()->card ) ) {
$wc_tokens = WC_Payment_Tokens::get_customer_tokens( $id, CreditCardGateway::ID );
- if ( $this->token_exist( $wc_tokens, $token ) ) {
+ if ( $this->payment_token_helper->token_exist( $wc_tokens, $token->id() ) ) {
$this->logger->info( 'Token already exist for user ' . (string) $id );
continue;
}
@@ -97,7 +107,7 @@ class PaymentTokensMigration {
}
} elseif ( $token->source()->paypal ) {
$wc_tokens = WC_Payment_Tokens::get_customer_tokens( $id, PayPalGateway::ID );
- if ( $this->token_exist( $wc_tokens, $token ) ) {
+ if ( $this->payment_token_helper->token_exist( $wc_tokens, $token->id() ) ) {
$this->logger->info( 'Token already exist for user ' . (string) $id );
continue;
}
@@ -126,21 +136,4 @@ class PaymentTokensMigration {
}
}
}
-
- /**
- * Checks if given PayPal token exist as WC Payment Token.
- *
- * @param array $wc_tokens WC Payment Tokens.
- * @param PaymentToken $token PayPal Token ID.
- * @return bool
- */
- private function token_exist( array $wc_tokens, PaymentToken $token ): bool {
- foreach ( $wc_tokens as $wc_token ) {
- if ( $wc_token->get_token() === $token->id() ) {
- return true;
- }
- }
-
- return false;
- }
}
diff --git a/modules/ppcp-webhooks/services.php b/modules/ppcp-webhooks/services.php
index 9223a7348..4d585206a 100644
--- a/modules/ppcp-webhooks/services.php
+++ b/modules/ppcp-webhooks/services.php
@@ -80,6 +80,7 @@ return array(
$order_endpoint = $container->get( 'api.endpoint.order' );
$authorized_payments_processor = $container->get( 'wcgateway.processor.authorized-payments' );
$payment_token_factory = $container->get( 'vaulting.payment-token-factory' );
+ $payment_token_helper = $container->get( 'vaulting.payment-token-helper' );
$refund_fees_updater = $container->get( 'wcgateway.helper.refund-fees-updater' );
return array(
@@ -95,7 +96,7 @@ return array(
new PaymentCaptureRefunded( $logger, $refund_fees_updater ),
new PaymentCaptureReversed( $logger ),
new PaymentCaptureCompleted( $logger, $order_endpoint ),
- new VaultPaymentTokenCreated( $logger, $prefix, $authorized_payments_processor, $payment_token_factory ),
+ new VaultPaymentTokenCreated( $logger, $prefix, $authorized_payments_processor, $payment_token_factory, $payment_token_helper ),
new VaultPaymentTokenDeleted( $logger ),
new PaymentCapturePending( $logger ),
new PaymentSaleCompleted( $logger ),
diff --git a/modules/ppcp-webhooks/src/Handler/VaultPaymentTokenCreated.php b/modules/ppcp-webhooks/src/Handler/VaultPaymentTokenCreated.php
index 152932556..893305c75 100644
--- a/modules/ppcp-webhooks/src/Handler/VaultPaymentTokenCreated.php
+++ b/modules/ppcp-webhooks/src/Handler/VaultPaymentTokenCreated.php
@@ -13,6 +13,7 @@ use Psr\Log\LoggerInterface;
use WC_Payment_Token_CC;
use WC_Payment_Tokens;
use WooCommerce\PayPalCommerce\Vaulting\PaymentTokenFactory;
+use WooCommerce\PayPalCommerce\Vaulting\PaymentTokenHelper;
use WooCommerce\PayPalCommerce\Vaulting\PaymentTokenPayPal;
use WooCommerce\PayPalCommerce\WcGateway\Gateway\CreditCardGateway;
use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway;
@@ -54,6 +55,13 @@ class VaultPaymentTokenCreated implements RequestHandler {
*/
protected $payment_token_factory;
+ /**
+ * The payment token helper.
+ *
+ * @var PaymentTokenHelper
+ */
+ private $payment_token_helper;
+
/**
* VaultPaymentTokenCreated constructor.
*
@@ -61,17 +69,20 @@ class VaultPaymentTokenCreated implements RequestHandler {
* @param string $prefix The prefix.
* @param AuthorizedPaymentsProcessor $authorized_payments_processor The authorized payment processor.
* @param PaymentTokenFactory $payment_token_factory The payment token factory.
+ * @param PaymentTokenHelper $payment_token_helper The payment token helper.
*/
public function __construct(
LoggerInterface $logger,
string $prefix,
AuthorizedPaymentsProcessor $authorized_payments_processor,
- PaymentTokenFactory $payment_token_factory
+ PaymentTokenFactory $payment_token_factory,
+ PaymentTokenHelper $payment_token_helper
) {
$this->logger = $logger;
$this->prefix = $prefix;
$this->authorized_payments_processor = $authorized_payments_processor;
$this->payment_token_factory = $payment_token_factory;
+ $this->payment_token_helper = $payment_token_helper;
}
/**
@@ -123,33 +134,39 @@ class VaultPaymentTokenCreated implements RequestHandler {
if ( ! is_null( $request['resource'] ) && isset( $request['resource']['id'] ) ) {
if ( ! is_null( $request['resource']['source'] ) && isset( $request['resource']['source']['card'] ) ) {
- $token = new WC_Payment_Token_CC();
- $token->set_token( $request['resource']['id'] );
- $token->set_user_id( $wc_customer_id );
- $token->set_gateway_id( CreditCardGateway::ID );
+ $wc_tokens = WC_Payment_Tokens::get_customer_tokens( $wc_customer_id, CreditCardGateway::ID );
+ if ( ! $this->payment_token_helper->token_exist( $wc_tokens, $request['resource']['id'] ) ) {
+ $token = new WC_Payment_Token_CC();
+ $token->set_token( $request['resource']['id'] );
+ $token->set_user_id( $wc_customer_id );
+ $token->set_gateway_id( CreditCardGateway::ID );
- $token->set_last4( $request['resource']['source']['card']['last_digits'] ?? '' );
- $expiry = explode( '-', $request['resource']['source']['card']['expiry'] ?? '' );
- $token->set_expiry_year( $expiry[0] ?? '' );
- $token->set_expiry_month( $expiry[1] ?? '' );
- $token->set_card_type( $request['resource']['source']['card']['brand'] ?? '' );
- $token->save();
- WC_Payment_Tokens::set_users_default( $wc_customer_id, $token->get_id() );
- } elseif ( isset( $request['resource']['source']['paypal'] ) ) {
- $payment_token_paypal = $this->payment_token_factory->create( 'paypal' );
- assert( $payment_token_paypal instanceof PaymentTokenPayPal );
-
- $payment_token_paypal->set_token( $request['resource']['id'] );
- $payment_token_paypal->set_user_id( $wc_customer_id );
- $payment_token_paypal->set_gateway_id( PayPalGateway::ID );
-
- $email = $request['resource']['source']['paypal']['payer']['email_address'] ?? '';
- if ( $email && is_email( $email ) ) {
- $payment_token_paypal->set_email( $email );
+ $token->set_last4( $request['resource']['source']['card']['last_digits'] ?? '' );
+ $expiry = explode( '-', $request['resource']['source']['card']['expiry'] ?? '' );
+ $token->set_expiry_year( $expiry[0] ?? '' );
+ $token->set_expiry_month( $expiry[1] ?? '' );
+ $token->set_card_type( $request['resource']['source']['card']['brand'] ?? '' );
+ $token->save();
+ WC_Payment_Tokens::set_users_default( $wc_customer_id, $token->get_id() );
}
+ } elseif ( isset( $request['resource']['source']['paypal'] ) ) {
+ $wc_tokens = WC_Payment_Tokens::get_customer_tokens( $wc_customer_id, PayPalGateway::ID );
+ if ( ! $this->payment_token_helper->token_exist( $wc_tokens, $request['resource']['id'] ) ) {
+ $payment_token_paypal = $this->payment_token_factory->create( 'paypal' );
+ assert( $payment_token_paypal instanceof PaymentTokenPayPal );
- $payment_token_paypal->save();
- WC_Payment_Tokens::set_users_default( $wc_customer_id, $payment_token_paypal->get_id() );
+ $payment_token_paypal->set_token( $request['resource']['id'] );
+ $payment_token_paypal->set_user_id( $wc_customer_id );
+ $payment_token_paypal->set_gateway_id( PayPalGateway::ID );
+
+ $email = $request['resource']['source']['paypal']['payer']['email_address'] ?? '';
+ if ( $email && is_email( $email ) ) {
+ $payment_token_paypal->set_email( $email );
+ }
+
+ $payment_token_paypal->save();
+ WC_Payment_Tokens::set_users_default( $wc_customer_id, $payment_token_paypal->get_id() );
+ }
}
}
From 4482809c182a482bd6c929827ec59b397531b5f2 Mon Sep 17 00:00:00 2001
From: Pedro Silva
Date: Tue, 5 Sep 2023 10:40:50 +0100
Subject: [PATCH 10/17] Fix clearing onboarding links cache on disconnect Add
clearing onboarding links cache on uninstall
---
.../ppcp-onboarding/src/Helper/OnboardingUrl.php | 5 ++++-
modules/ppcp-uninstall/services.php | 6 ++++++
modules/ppcp-uninstall/src/ClearDatabase.php | 9 +++++++++
.../ppcp-uninstall/src/ClearDatabaseInterface.php | 8 ++++++++
modules/ppcp-uninstall/src/UninstallModule.php | 10 +++++++---
.../src/Settings/SettingsListener.php | 15 ++++++++++++---
modules/ppcp-wc-gateway/src/WCGatewayModule.php | 10 ++++++++++
7 files changed, 56 insertions(+), 7 deletions(-)
diff --git a/modules/ppcp-onboarding/src/Helper/OnboardingUrl.php b/modules/ppcp-onboarding/src/Helper/OnboardingUrl.php
index 881d4295f..9d4c9aa74 100644
--- a/modules/ppcp-onboarding/src/Helper/OnboardingUrl.php
+++ b/modules/ppcp-onboarding/src/Helper/OnboardingUrl.php
@@ -346,7 +346,10 @@ class OnboardingUrl {
* @return void
*/
public function delete(): void {
- $this->cache->delete( $this->cache_key() );
+ $cache_key = $this->cache_key();
+ if ( $this->cache->has( $cache_key ) ) {
+ $this->cache->delete( $cache_key );
+ }
}
/**
diff --git a/modules/ppcp-uninstall/services.php b/modules/ppcp-uninstall/services.php
index 6f7cda722..ca67dc71b 100644
--- a/modules/ppcp-uninstall/services.php
+++ b/modules/ppcp-uninstall/services.php
@@ -45,6 +45,12 @@ return array(
);
},
+ 'uninstall.ppcp-all-action-names' => function( ContainerInterface $container ) : array {
+ return array(
+ 'woocommerce_paypal_payments_uninstall',
+ );
+ },
+
'uninstall.clear-db-endpoint' => function( ContainerInterface $container ) : string {
return 'ppcp-clear-db';
},
diff --git a/modules/ppcp-uninstall/src/ClearDatabase.php b/modules/ppcp-uninstall/src/ClearDatabase.php
index fc09519a5..ed5d73bb6 100644
--- a/modules/ppcp-uninstall/src/ClearDatabase.php
+++ b/modules/ppcp-uninstall/src/ClearDatabase.php
@@ -31,4 +31,13 @@ class ClearDatabase implements ClearDatabaseInterface {
as_unschedule_action( $action_name );
}
}
+
+ /**
+ * {@inheritDoc}
+ */
+ public function clear_actions( array $action_names ): void {
+ foreach ( $action_names as $action_name ) {
+ do_action( $action_name );
+ }
+ }
}
diff --git a/modules/ppcp-uninstall/src/ClearDatabaseInterface.php b/modules/ppcp-uninstall/src/ClearDatabaseInterface.php
index 6d6aedb77..34d9b1469 100644
--- a/modules/ppcp-uninstall/src/ClearDatabaseInterface.php
+++ b/modules/ppcp-uninstall/src/ClearDatabaseInterface.php
@@ -29,4 +29,12 @@ interface ClearDatabaseInterface {
*/
public function clear_scheduled_actions( array $action_names ): void;
+ /**
+ * Clears the given actions.
+ *
+ * @param string[] $action_names The list of action names.
+ * @throws RuntimeException If problem clearing.
+ */
+ public function clear_actions( array $action_names ): void;
+
}
diff --git a/modules/ppcp-uninstall/src/UninstallModule.php b/modules/ppcp-uninstall/src/UninstallModule.php
index 649be5c49..25d65ae0f 100644
--- a/modules/ppcp-uninstall/src/UninstallModule.php
+++ b/modules/ppcp-uninstall/src/UninstallModule.php
@@ -47,8 +47,9 @@ class UninstallModule implements ModuleInterface {
$clear_db_endpoint = $container->get( 'uninstall.clear-db-endpoint' );
$option_names = $container->get( 'uninstall.ppcp-all-option-names' );
$scheduled_action_names = $container->get( 'uninstall.ppcp-all-scheduled-action-names' );
+ $action_names = $container->get( 'uninstall.ppcp-all-action-names' );
- $this->handleClearDbAjaxRequest( $request_data, $clear_db, $clear_db_endpoint, $option_names, $scheduled_action_names );
+ $this->handleClearDbAjaxRequest( $request_data, $clear_db, $clear_db_endpoint, $option_names, $scheduled_action_names, $action_names );
}
/**
@@ -69,17 +70,19 @@ class UninstallModule implements ModuleInterface {
* @param string $nonce The nonce.
* @param string[] $option_names The list of option names.
* @param string[] $scheduled_action_names The list of scheduled action names.
+ * @param string[] $action_names The list of action names.
*/
protected function handleClearDbAjaxRequest(
RequestData $request_data,
ClearDatabaseInterface $clear_db,
string $nonce,
array $option_names,
- array $scheduled_action_names
+ array $scheduled_action_names,
+ array $action_names
): void {
add_action(
"wc_ajax_{$nonce}",
- static function () use ( $request_data, $clear_db, $nonce, $option_names, $scheduled_action_names ) {
+ static function () use ( $request_data, $clear_db, $nonce, $option_names, $scheduled_action_names, $action_names ) {
try {
if ( ! current_user_can( 'manage_woocommerce' ) ) {
wp_send_json_error( 'Not admin.', 403 );
@@ -91,6 +94,7 @@ class UninstallModule implements ModuleInterface {
$clear_db->delete_options( $option_names );
$clear_db->clear_scheduled_actions( $scheduled_action_names );
+ $clear_db->clear_actions( $action_names );
wp_send_json_success();
return true;
diff --git a/modules/ppcp-wc-gateway/src/Settings/SettingsListener.php b/modules/ppcp-wc-gateway/src/Settings/SettingsListener.php
index b1d057537..6ebda496a 100644
--- a/modules/ppcp-wc-gateway/src/Settings/SettingsListener.php
+++ b/modules/ppcp-wc-gateway/src/Settings/SettingsListener.php
@@ -401,9 +401,7 @@ class SettingsListener {
$this->webhook_registrar->unregister();
foreach ( $this->signup_link_ids as $key ) {
- if ( $this->signup_link_cache->has( $key ) ) {
- $this->signup_link_cache->delete( $key );
- }
+ ( new OnboardingUrl( $this->signup_link_cache, $key, get_current_user_id() ) )->delete();
}
}
}
@@ -638,4 +636,15 @@ class SettingsListener {
throw $exception;
}
}
+
+ /**
+ * Handles onboarding URLs deletion
+ */
+ public function listen_for_uninstall() {
+ // Clear onboarding links from cache.
+ foreach ( $this->signup_link_ids as $key ) {
+ ( new OnboardingUrl( $this->signup_link_cache, $key, get_current_user_id() ) )->delete();
+ }
+ }
+
}
diff --git a/modules/ppcp-wc-gateway/src/WCGatewayModule.php b/modules/ppcp-wc-gateway/src/WCGatewayModule.php
index 477ce303f..7e728f0ec 100644
--- a/modules/ppcp-wc-gateway/src/WCGatewayModule.php
+++ b/modules/ppcp-wc-gateway/src/WCGatewayModule.php
@@ -392,6 +392,16 @@ class WCGatewayModule implements ModuleInterface {
3
);
+ add_action(
+ 'woocommerce_paypal_payments_uninstall',
+ static function () use ( $c ) {
+ $listener = $c->get( 'wcgateway.settings.listener' );
+ assert( $listener instanceof SettingsListener );
+
+ $listener->listen_for_uninstall();
+ }
+ );
+
if ( defined( 'WP_CLI' ) && WP_CLI ) {
\WP_CLI::add_command(
'pcp settings',
From 9960134933b6395acfef182c51a3482896b3fc1a Mon Sep 17 00:00:00 2001
From: Pedro Silva
Date: Tue, 5 Sep 2023 11:25:49 +0100
Subject: [PATCH 11/17] Fix lint
---
modules/ppcp-wc-gateway/src/Settings/SettingsListener.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/modules/ppcp-wc-gateway/src/Settings/SettingsListener.php b/modules/ppcp-wc-gateway/src/Settings/SettingsListener.php
index 6ebda496a..bd36ca5d4 100644
--- a/modules/ppcp-wc-gateway/src/Settings/SettingsListener.php
+++ b/modules/ppcp-wc-gateway/src/Settings/SettingsListener.php
@@ -640,7 +640,7 @@ class SettingsListener {
/**
* Handles onboarding URLs deletion
*/
- public function listen_for_uninstall() {
+ public function listen_for_uninstall(): void {
// Clear onboarding links from cache.
foreach ( $this->signup_link_ids as $key ) {
( new OnboardingUrl( $this->signup_link_cache, $key, get_current_user_id() ) )->delete();
From 5b7eed750ff3061f4e7242f99cc9e357a0a096cd Mon Sep 17 00:00:00 2001
From: Pedro Silva
Date: Tue, 5 Sep 2023 11:53:23 +0100
Subject: [PATCH 12/17] Fix test
---
tests/PHPUnit/Onboarding/Helper/OnboardingUrlTest.php | 1 +
1 file changed, 1 insertion(+)
diff --git a/tests/PHPUnit/Onboarding/Helper/OnboardingUrlTest.php b/tests/PHPUnit/Onboarding/Helper/OnboardingUrlTest.php
index db50265d5..8967e9a56 100644
--- a/tests/PHPUnit/Onboarding/Helper/OnboardingUrlTest.php
+++ b/tests/PHPUnit/Onboarding/Helper/OnboardingUrlTest.php
@@ -118,6 +118,7 @@ class OnboardingUrlTest extends TestCase
public function test_delete()
{
// Expectations
+ $this->cache->shouldReceive('has')->once();
$this->cache->shouldReceive('delete')->once();
$this->onboardingUrl->delete();
From ca9fd29884aaf90aaf4865532252d82ff4da5178 Mon Sep 17 00:00:00 2001
From: Pedro Silva
Date: Tue, 5 Sep 2023 12:20:45 +0100
Subject: [PATCH 13/17] Fix tests
---
modules/ppcp-onboarding/src/Helper/OnboardingUrl.php | 5 +----
tests/PHPUnit/Onboarding/Helper/OnboardingUrlTest.php | 5 ++---
2 files changed, 3 insertions(+), 7 deletions(-)
diff --git a/modules/ppcp-onboarding/src/Helper/OnboardingUrl.php b/modules/ppcp-onboarding/src/Helper/OnboardingUrl.php
index 9d4c9aa74..881d4295f 100644
--- a/modules/ppcp-onboarding/src/Helper/OnboardingUrl.php
+++ b/modules/ppcp-onboarding/src/Helper/OnboardingUrl.php
@@ -346,10 +346,7 @@ class OnboardingUrl {
* @return void
*/
public function delete(): void {
- $cache_key = $this->cache_key();
- if ( $this->cache->has( $cache_key ) ) {
- $this->cache->delete( $cache_key );
- }
+ $this->cache->delete( $this->cache_key() );
}
/**
diff --git a/tests/PHPUnit/Onboarding/Helper/OnboardingUrlTest.php b/tests/PHPUnit/Onboarding/Helper/OnboardingUrlTest.php
index 8967e9a56..ea8b0ab0e 100644
--- a/tests/PHPUnit/Onboarding/Helper/OnboardingUrlTest.php
+++ b/tests/PHPUnit/Onboarding/Helper/OnboardingUrlTest.php
@@ -3,7 +3,7 @@ declare(strict_types=1);
namespace WooCommerce\PayPalCommerce\Onboarding\Helper;
-use PHPUnit\Framework\TestCase;
+use WooCommerce\PayPalCommerce\TestCase;
use WooCommerce\PayPalCommerce\ApiClient\Helper\Cache;
use RuntimeException;
use function Brain\Monkey\Functions\when;
@@ -15,7 +15,7 @@ class OnboardingUrlTest extends TestCase
private $user_id = 123;
private $onboardingUrl;
- protected function setUp(): void
+ public function setUp(): void
{
parent::setUp();
@@ -118,7 +118,6 @@ class OnboardingUrlTest extends TestCase
public function test_delete()
{
// Expectations
- $this->cache->shouldReceive('has')->once();
$this->cache->shouldReceive('delete')->once();
$this->onboardingUrl->delete();
From 7415fdb32d427d6b60271a81271573f8094364f1 Mon Sep 17 00:00:00 2001
From: Pedro Silva
Date: Wed, 5 Jul 2023 10:48:29 +0100
Subject: [PATCH 14/17] Do not declare subscription support for PayPal when
only ACDC vaulting
This reverts commit 01717e740a31b74e1128c1b6356efa002ca10496.
---
modules/ppcp-wc-gateway/src/Gateway/PayPalGateway.php | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/modules/ppcp-wc-gateway/src/Gateway/PayPalGateway.php b/modules/ppcp-wc-gateway/src/Gateway/PayPalGateway.php
index c703de904..933e6ce51 100644
--- a/modules/ppcp-wc-gateway/src/Gateway/PayPalGateway.php
+++ b/modules/ppcp-wc-gateway/src/Gateway/PayPalGateway.php
@@ -227,7 +227,6 @@ class PayPalGateway extends \WC_Payment_Gateway {
if (
( $this->config->has( 'vault_enabled' ) && $this->config->get( 'vault_enabled' ) )
- || ( $this->config->has( 'vault_enabled_dcc' ) && $this->config->get( 'vault_enabled_dcc' ) )
|| ( $this->config->has( 'subscriptions_mode' ) && $this->config->get( 'subscriptions_mode' ) === 'subscriptions_api' )
) {
array_push(
@@ -244,6 +243,8 @@ class PayPalGateway extends \WC_Payment_Gateway {
'subscription_payment_method_change_admin',
'multiple_subscriptions'
);
+ } elseif ( $this->config->has( 'vault_enabled_dcc' ) && $this->config->get( 'vault_enabled_dcc' ) ) {
+ $this->supports[] = 'tokenization';
}
}
From fb0725df77f790d53d7e18c191bb549d57f59af5 Mon Sep 17 00:00:00 2001
From: Emili Castells Guasch
Date: Thu, 7 Sep 2023 10:08:18 +0200
Subject: [PATCH 15/17] Improve dockblock
---
modules/ppcp-vaulting/src/PaymentTokenHelper.php | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/modules/ppcp-vaulting/src/PaymentTokenHelper.php b/modules/ppcp-vaulting/src/PaymentTokenHelper.php
index 22d973a3b..de940ccf3 100644
--- a/modules/ppcp-vaulting/src/PaymentTokenHelper.php
+++ b/modules/ppcp-vaulting/src/PaymentTokenHelper.php
@@ -9,16 +9,18 @@ declare(strict_types=1);
namespace WooCommerce\PayPalCommerce\Vaulting;
+use WC_Payment_Token;
+
/**
* Class PaymentTokenHelper
*/
class PaymentTokenHelper {
/**
- * Checks if given PayPal token exist as WC Payment Token.
+ * Checks if given token exist as WC Payment Token.
*
- * @param array $wc_tokens WC Payment Tokens.
- * @param string $token_id PayPal Token ID.
+ * @param WC_Payment_Token[] $wc_tokens WC Payment Tokens.
+ * @param string $token_id Payment Token ID.
* @return bool
*/
public function token_exist( array $wc_tokens, string $token_id ): bool {
From a53246259547d410d236828d43e3acbce76043f7 Mon Sep 17 00:00:00 2001
From: Pedro Silva
Date: Fri, 8 Sep 2023 10:32:34 +0100
Subject: [PATCH 16/17] Fix onboarding email with spaces/plus signs. Fix order
item when image_url is empty.
---
modules/ppcp-api-client/src/Entity/Item.php | 5 ++++-
.../src/Settings/SettingsListener.php | 12 +++++++++++-
2 files changed, 15 insertions(+), 2 deletions(-)
diff --git a/modules/ppcp-api-client/src/Entity/Item.php b/modules/ppcp-api-client/src/Entity/Item.php
index 7d38e5f78..cc739635f 100644
--- a/modules/ppcp-api-client/src/Entity/Item.php
+++ b/modules/ppcp-api-client/src/Entity/Item.php
@@ -249,9 +249,12 @@ class Item {
'sku' => $this->sku(),
'category' => $this->category(),
'url' => $this->url(),
- 'image_url' => $this->image_url(),
);
+ if ( $this->image_url() ) {
+ $item['image_url'] = $this->image_url();
+ }
+
if ( $this->tax() ) {
$item['tax'] = $this->tax()->to_array();
}
diff --git a/modules/ppcp-wc-gateway/src/Settings/SettingsListener.php b/modules/ppcp-wc-gateway/src/Settings/SettingsListener.php
index bd36ca5d4..df6f013a5 100644
--- a/modules/ppcp-wc-gateway/src/Settings/SettingsListener.php
+++ b/modules/ppcp-wc-gateway/src/Settings/SettingsListener.php
@@ -211,7 +211,7 @@ class SettingsListener {
}
$merchant_id = sanitize_text_field( wp_unslash( $_GET['merchantIdInPayPal'] ) );
- $merchant_email = sanitize_text_field( wp_unslash( $_GET['merchantId'] ) );
+ $merchant_email = $this->sanitize_onboarding_email( sanitize_text_field( wp_unslash( $_GET['merchantId'] ) ) );
$onboarding_token = sanitize_text_field( wp_unslash( $_GET['ppcpToken'] ) );
$retry_count = isset( $_GET['ppcpRetry'] ) ? ( (int) sanitize_text_field( wp_unslash( $_GET['ppcpRetry'] ) ) ) : 0;
// phpcs:enable WordPress.Security.NonceVerification.Missing
@@ -278,6 +278,16 @@ class SettingsListener {
$this->onboarding_redirect();
}
+ /**
+ * Sanitizes the onboarding email.
+ *
+ * @param string $email The onboarding email.
+ * @return string
+ */
+ private function sanitize_onboarding_email( string $email ): string {
+ return str_replace( ' ', '+', $email );
+ }
+
/**
* Redirect to the onboarding URL.
*
From fa45071a5f7ae0c138a26ef18b57cca7e83a2340 Mon Sep 17 00:00:00 2001
From: Narek Zakarian
Date: Fri, 8 Sep 2023 14:41:21 +0400
Subject: [PATCH 17/17] Don't send `image_url` when it is empty
---
modules/ppcp-api-client/src/Entity/Item.php | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/modules/ppcp-api-client/src/Entity/Item.php b/modules/ppcp-api-client/src/Entity/Item.php
index 7d38e5f78..cc739635f 100644
--- a/modules/ppcp-api-client/src/Entity/Item.php
+++ b/modules/ppcp-api-client/src/Entity/Item.php
@@ -249,9 +249,12 @@ class Item {
'sku' => $this->sku(),
'category' => $this->category(),
'url' => $this->url(),
- 'image_url' => $this->image_url(),
);
+ if ( $this->image_url() ) {
+ $item['image_url'] = $this->image_url();
+ }
+
if ( $this->tax() ) {
$item['tax'] = $this->tax()->to_array();
}