From e819dc68dfa5a1dacfec5d835dced9b32a94c4cc Mon Sep 17 00:00:00 2001 From: Emili Castells Guasch Date: Mon, 4 Sep 2023 16:33:04 +0200 Subject: [PATCH 1/2] 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 fb0725df77f790d53d7e18c191bb549d57f59af5 Mon Sep 17 00:00:00 2001 From: Emili Castells Guasch Date: Thu, 7 Sep 2023 10:08:18 +0200 Subject: [PATCH 2/2] 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 {