From 0d4fbc4c0b3d1212139dbf43ca82441daeff85aa Mon Sep 17 00:00:00 2001 From: Pedro Silva Date: Fri, 26 Jan 2024 14:22:20 +0000 Subject: [PATCH] Refactor Venmo and ApplePay payment tokens. --- .../src/SavePaymentMethodsModule.php | 29 ++++-- .../src/WooCommercePaymentTokens.php | 90 +++++++++++++++++-- .../src/PaymentTokenApplePay.php | 31 +++++++ .../ppcp-vaulting/src/PaymentTokenFactory.php | 6 +- .../ppcp-vaulting/src/PaymentTokenHelper.php | 11 ++- .../ppcp-vaulting/src/PaymentTokenPayPal.php | 21 +---- .../ppcp-vaulting/src/PaymentTokenVenmo.php | 51 +++++++++++ .../src/PaymentTokensMigration.php | 2 +- modules/ppcp-vaulting/src/VaultingModule.php | 37 ++++---- .../src/RenewalHandler.php | 26 +++--- 10 files changed, 234 insertions(+), 70 deletions(-) create mode 100644 modules/ppcp-vaulting/src/PaymentTokenApplePay.php create mode 100644 modules/ppcp-vaulting/src/PaymentTokenVenmo.php diff --git a/modules/ppcp-save-payment-methods/src/SavePaymentMethodsModule.php b/modules/ppcp-save-payment-methods/src/SavePaymentMethodsModule.php index e79ec11f6..5ea2a78dd 100644 --- a/modules/ppcp-save-payment-methods/src/SavePaymentMethodsModule.php +++ b/modules/ppcp-save-payment-methods/src/SavePaymentMethodsModule.php @@ -188,12 +188,29 @@ class SavePaymentMethodsModule implements ModuleInterface { } if ( $wc_order->get_payment_method() === PayPalGateway::ID ) { - $wc_payment_tokens->create_payment_token_paypal( - $wc_order->get_customer_id(), - $token_id, - $payment_source->properties()->email_address ?? '', - $payment_source->name() - ); + switch ( $payment_source->name() ) { + case 'venmo': + $wc_payment_tokens->create_payment_token_venmo( + $wc_order->get_customer_id(), + $token_id, + $payment_source->properties()->email_address ?? '' + ); + break; + case 'apple_pay': + $wc_payment_tokens->create_payment_token_applepay( + $wc_order->get_customer_id(), + $token_id + ); + break; + case 'paypal': + default: + $wc_payment_tokens->create_payment_token_paypal( + $wc_order->get_customer_id(), + $token_id, + $payment_source->properties()->email_address ?? '' + ); + break; + } } } }, diff --git a/modules/ppcp-save-payment-methods/src/WooCommercePaymentTokens.php b/modules/ppcp-save-payment-methods/src/WooCommercePaymentTokens.php index e57198a0d..c878f10d1 100644 --- a/modules/ppcp-save-payment-methods/src/WooCommercePaymentTokens.php +++ b/modules/ppcp-save-payment-methods/src/WooCommercePaymentTokens.php @@ -14,9 +14,11 @@ use Psr\Log\LoggerInterface; use stdClass; use WC_Payment_Token_CC; use WC_Payment_Tokens; +use WooCommerce\PayPalCommerce\Vaulting\PaymentTokenApplePay; use WooCommerce\PayPalCommerce\Vaulting\PaymentTokenFactory; use WooCommerce\PayPalCommerce\Vaulting\PaymentTokenHelper; use WooCommerce\PayPalCommerce\Vaulting\PaymentTokenPayPal; +use WooCommerce\PayPalCommerce\Vaulting\PaymentTokenVenmo; use WooCommerce\PayPalCommerce\WcGateway\Gateway\CreditCardGateway; use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway; @@ -69,19 +71,17 @@ class WooCommercePaymentTokens { * @param int $customer_id The WC customer ID. * @param string $token The PayPal payment token. * @param string $email The PayPal customer email. - * @param string $payment_source The funding source. * * @return int */ public function create_payment_token_paypal( int $customer_id, string $token, - string $email, - string $payment_source = '' + string $email ): int { $wc_tokens = WC_Payment_Tokens::get_customer_tokens( $customer_id, PayPalGateway::ID ); - if ( $this->payment_token_helper->token_exist( $wc_tokens, $token ) ) { + if ( $this->payment_token_helper->token_exist( $wc_tokens, $token, PaymentTokenPayPal::class ) ) { return 0; } @@ -96,10 +96,6 @@ class WooCommercePaymentTokens { $payment_token_paypal->set_email( $email ); } - if ( $payment_source ) { - $payment_token_paypal->set_payment_source( $payment_source ); - } - try { $payment_token_paypal->save(); } catch ( Exception $exception ) { @@ -111,6 +107,84 @@ class WooCommercePaymentTokens { return $payment_token_paypal->get_id(); } + /** + * Creates a WC Payment Token for Venmo payment. + * + * @param int $customer_id The WC customer ID. + * @param string $token The Venmo payment token. + * @param string $email The Venmo customer email. + * + * @return int + */ + public function create_payment_token_venmo( + int $customer_id, + string $token, + string $email + ): int { + + $wc_tokens = WC_Payment_Tokens::get_customer_tokens( $customer_id, PayPalGateway::ID ); + if ( $this->payment_token_helper->token_exist( $wc_tokens, $token, PaymentTokenVenmo::class ) ) { + return 0; + } + + $payment_token_venmo = $this->payment_token_factory->create( 'venmo' ); + assert( $payment_token_venmo instanceof PaymentTokenVenmo ); + + $payment_token_venmo->set_token( $token ); + $payment_token_venmo->set_user_id( $customer_id ); + $payment_token_venmo->set_gateway_id( PayPalGateway::ID ); + + if ( $email && is_email( $email ) ) { + $payment_token_venmo->set_email( $email ); + } + + try { + $payment_token_venmo->save(); + } catch ( Exception $exception ) { + $this->logger->error( + "Could not create WC payment token Venmo for customer {$customer_id}. " . $exception->getMessage() + ); + } + + return $payment_token_venmo->get_id(); + } + + /** + * Creates a WC Payment Token for ApplePay payment. + * + * @param int $customer_id The WC customer ID. + * @param string $token The ApplePay payment token. + * + * @return int + */ + public function create_payment_token_applepay( + int $customer_id, + string $token + ): int { + + $wc_tokens = WC_Payment_Tokens::get_customer_tokens( $customer_id, PayPalGateway::ID ); + if ( $this->payment_token_helper->token_exist( $wc_tokens, $token, PaymentTokenApplePay::class ) ) { + return 0; + } + + $payment_token_applepay = $this->payment_token_factory->create( 'apple_pay' ); + assert( $payment_token_applepay instanceof PaymentTokenApplePay ); + + $payment_token_applepay->set_token( $token ); + $payment_token_applepay->set_user_id( $customer_id ); + $payment_token_applepay->set_gateway_id( PayPalGateway::ID ); + + try { + $payment_token_applepay->save(); + } catch ( Exception $exception ) { + $this->logger->error( + "Could not create WC payment token ApplePay for customer {$customer_id}. " . $exception->getMessage() + ); + } + + return $payment_token_applepay->get_id(); + } + /** * Creates a WC Payment Token for Credit Card payment. * diff --git a/modules/ppcp-vaulting/src/PaymentTokenApplePay.php b/modules/ppcp-vaulting/src/PaymentTokenApplePay.php new file mode 100644 index 000000000..a53aa254a --- /dev/null +++ b/modules/ppcp-vaulting/src/PaymentTokenApplePay.php @@ -0,0 +1,31 @@ +get_token() === $token_id ) { - return true; + if ( null !== $class_name ) { + if ( $wc_token instanceof $class_name ) { + return true; + } + } else { + return true; + } } } diff --git a/modules/ppcp-vaulting/src/PaymentTokenPayPal.php b/modules/ppcp-vaulting/src/PaymentTokenPayPal.php index 3b8eac849..1a5858118 100644 --- a/modules/ppcp-vaulting/src/PaymentTokenPayPal.php +++ b/modules/ppcp-vaulting/src/PaymentTokenPayPal.php @@ -28,8 +28,7 @@ class PaymentTokenPayPal extends WC_Payment_Token { * @var string[] */ protected $extra_data = array( - 'email' => '', - 'payment_source' => '', + 'email' => '', ); /** @@ -49,22 +48,4 @@ class PaymentTokenPayPal extends WC_Payment_Token { public function set_email( $email ) { $this->add_meta_data( 'email', $email, true ); } - - /** - * Get the payment source. - * - * @return string The payment source. - */ - public function get_payment_source() { - return $this->get_meta( 'payment_source' ); - } - - /** - * Set the payment source. - * - * @param string $payment_source The payment source. - */ - public function set_payment_source( string $payment_source ) { - $this->add_meta_data( 'payment_source', $payment_source, true ); - } } diff --git a/modules/ppcp-vaulting/src/PaymentTokenVenmo.php b/modules/ppcp-vaulting/src/PaymentTokenVenmo.php new file mode 100644 index 000000000..d53a4b4fb --- /dev/null +++ b/modules/ppcp-vaulting/src/PaymentTokenVenmo.php @@ -0,0 +1,51 @@ + '', + ); + + /** + * Get PayPal account email. + * + * @return string PayPal account email. + */ + public function get_email() { + return $this->get_meta( 'email' ); + } + + /** + * Set PayPal account email. + * + * @param string $email PayPal account email. + */ + public function set_email( $email ) { + $this->add_meta_data( 'email', $email, true ); + } +} diff --git a/modules/ppcp-vaulting/src/PaymentTokensMigration.php b/modules/ppcp-vaulting/src/PaymentTokensMigration.php index a7d3511cc..1ef41df4a 100644 --- a/modules/ppcp-vaulting/src/PaymentTokensMigration.php +++ b/modules/ppcp-vaulting/src/PaymentTokensMigration.php @@ -107,7 +107,7 @@ class PaymentTokensMigration { } } elseif ( $token->source()->paypal ) { $wc_tokens = WC_Payment_Tokens::get_customer_tokens( $id, PayPalGateway::ID ); - if ( $this->payment_token_helper->token_exist( $wc_tokens, $token->id() ) ) { + if ( $this->payment_token_helper->token_exist( $wc_tokens, $token->id(), PaymentTokenPayPal::class ) ) { $this->logger->info( 'Token already exist for user ' . (string) $id ); continue; } diff --git a/modules/ppcp-vaulting/src/VaultingModule.php b/modules/ppcp-vaulting/src/VaultingModule.php index 1860a889d..ff8acdf3b 100644 --- a/modules/ppcp-vaulting/src/VaultingModule.php +++ b/modules/ppcp-vaulting/src/VaultingModule.php @@ -81,6 +81,12 @@ class VaultingModule implements ModuleInterface { if ( $type === 'WC_Payment_Token_PayPal' ) { return PaymentTokenPayPal::class; } + if ( $type === 'WC_Payment_Token_Venmo' ) { + return PaymentTokenVenmo::class; + } + if ( $type === 'WC_Payment_Token_ApplePay' ) { + return PaymentTokenApplePay::class; + } return $type; } @@ -102,10 +108,7 @@ class VaultingModule implements ModuleInterface { // Exclude ApplePay tokens from payment pages. if ( is_checkout() || is_cart() || is_product() ) { foreach ( $tokens as $index => $token ) { - if ( - $token instanceof PaymentTokenPayPal - && $token->get_payment_source() === 'apple_pay' - ) { + if ( $token instanceof PaymentTokenApplePay ) { unset( $tokens[ $index ] ); } } @@ -129,24 +132,18 @@ class VaultingModule implements ModuleInterface { return $item; } - if ( strtolower( $payment_token->get_type() ) === 'paypal' ) { - assert( $payment_token instanceof PaymentTokenPayPal ); + if ( $payment_token instanceof PaymentTokenPayPal ) { + $item['method']['brand'] = 'PayPal / ' . $payment_token->get_email(); + return $item; + } - $email = $payment_token->get_email(); - $payment_source = $payment_token->get_payment_source(); - $brand_parts = array(); + if ( $payment_token instanceof PaymentTokenVenmo ) { + $item['method']['brand'] = 'Venmo / ' . $payment_token->get_email(); + return $item; + } - if ( $payment_source !== 'paypal' ) { - $brand_parts[] = ucwords( $payment_source ); - } - - if ( $email ) { - $brand_parts[] = $email; - } else { - $brand_parts[] = '#' . ( (string) $payment_token->get_id() ); - } - - $item['method']['brand'] = implode( ' / ', array_filter( $brand_parts ) ); + if ( $payment_token instanceof PaymentTokenApplePay ) { + $item['method']['brand'] = 'ApplePay #' . ( (string) $payment_token->get_id() ); return $item; } diff --git a/modules/ppcp-wc-subscriptions/src/RenewalHandler.php b/modules/ppcp-wc-subscriptions/src/RenewalHandler.php index e3ce5bbfd..a4ce028ee 100644 --- a/modules/ppcp-wc-subscriptions/src/RenewalHandler.php +++ b/modules/ppcp-wc-subscriptions/src/RenewalHandler.php @@ -22,9 +22,11 @@ use WooCommerce\PayPalCommerce\ApiClient\Factory\PayerFactory; use WooCommerce\PayPalCommerce\ApiClient\Factory\PurchaseUnitFactory; use WooCommerce\PayPalCommerce\ApiClient\Factory\ShippingPreferenceFactory; use WooCommerce\PayPalCommerce\Onboarding\Environment; +use WooCommerce\PayPalCommerce\Vaulting\PaymentTokenApplePay; use WooCommerce\PayPalCommerce\Vaulting\PaymentTokenPayPal; use WooCommerce\PayPalCommerce\Vaulting\PaymentTokenRepository; use Psr\Log\LoggerInterface; +use WooCommerce\PayPalCommerce\Vaulting\PaymentTokenVenmo; use WooCommerce\PayPalCommerce\WcGateway\Exception\NotFoundException; use WooCommerce\PayPalCommerce\WcGateway\Gateway\CreditCardGateway; use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway; @@ -209,20 +211,20 @@ class RenewalHandler { ); if ( $token instanceof PaymentTokenPayPal ) { - $payment_source_name = $token->get_payment_source(); + $name = 'paypal'; + } - if ( $payment_source_name ) { - $name = $payment_source_name; - } + if ( $token instanceof PaymentTokenVenmo ) { + $name = 'venmo'; + } - // Add required stored_credentials for apple_pay. - if ( $payment_source_name === 'apple_pay' ) { - $properties['stored_credential'] = array( - 'payment_initiator' => 'MERCHANT', - 'payment_type' => 'RECURRING', - 'usage' => 'SUBSEQUENT', - ); - } + if ( $token instanceof PaymentTokenApplePay ) { + $name = 'apple_pay'; + $properties['stored_credential'] = array( + 'payment_initiator' => 'MERCHANT', + 'payment_type' => 'RECURRING', + 'usage' => 'SUBSEQUENT', + ); } $payment_source = new PaymentSource(