diff --git a/modules/ppcp-api-client/src/Endpoint/OrderEndpoint.php b/modules/ppcp-api-client/src/Endpoint/OrderEndpoint.php index 25e1837f8..d0db7d910 100644 --- a/modules/ppcp-api-client/src/Endpoint/OrderEndpoint.php +++ b/modules/ppcp-api-client/src/Endpoint/OrderEndpoint.php @@ -180,6 +180,7 @@ class OrderEndpoint { * @param PaymentToken|null $payment_token The payment token. * @param string $paypal_request_id The PayPal request id. * @param string $user_action The user action. + * @param string $payment_method WC payment method. * * @return Order * @throws RuntimeException If the request fails. @@ -190,7 +191,8 @@ class OrderEndpoint { Payer $payer = null, PaymentToken $payment_token = null, string $paypal_request_id = '', - string $user_action = ApplicationContext::USER_ACTION_CONTINUE + string $user_action = ApplicationContext::USER_ACTION_CONTINUE, + string $payment_method = '' ): Order { $bearer = $this->bearer->bearer(); $data = array( @@ -217,6 +219,9 @@ class OrderEndpoint { if ( $payment_token ) { $data['payment_source']['token'] = $payment_token->to_array(); } + if ( $payment_method ) { + $data['payment_method'] = $payment_method; + } /** * The filter can be used to modify the order creation request body data. diff --git a/modules/ppcp-button/src/Endpoint/CreateOrderEndpoint.php b/modules/ppcp-button/src/Endpoint/CreateOrderEndpoint.php index 844315b67..1e24c741d 100644 --- a/modules/ppcp-button/src/Endpoint/CreateOrderEndpoint.php +++ b/modules/ppcp-button/src/Endpoint/CreateOrderEndpoint.php @@ -304,7 +304,7 @@ class CreateOrderEndpoint implements EndpointInterface { } try { - $order = $this->create_paypal_order( $wc_order ); + $order = $this->create_paypal_order( $wc_order, $payment_method ); } catch ( Exception $exception ) { $this->logger->error( 'Order creation failed: ' . $exception->getMessage() ); throw $exception; @@ -415,6 +415,7 @@ class CreateOrderEndpoint implements EndpointInterface { * Creates the order in the PayPal, uses data from WC order if provided. * * @param \WC_Order|null $wc_order WC order to get data from. + * @param string $payment_method WC payment method. * * @return Order Created PayPal order. * @@ -422,7 +423,7 @@ class CreateOrderEndpoint implements EndpointInterface { * @throws PayPalApiException If create order request fails. * phpcs:disable Squiz.Commenting.FunctionCommentThrowTag.WrongNumber */ - private function create_paypal_order( \WC_Order $wc_order = null ): Order { + private function create_paypal_order( \WC_Order $wc_order = null, string $payment_method = '' ): Order { assert( $this->purchase_unit instanceof PurchaseUnit ); $funding_source = $this->parsed_request_data['funding_source'] ?? ''; @@ -464,7 +465,8 @@ class CreateOrderEndpoint implements EndpointInterface { $payer, null, '', - $action + $action, + $payment_method ); } catch ( PayPalApiException $exception ) { // Looks like currently there is no proper way to validate the shipping address for PayPal, diff --git a/modules/ppcp-card-fields/src/CardFieldsModule.php b/modules/ppcp-card-fields/src/CardFieldsModule.php index 4471485aa..a8ad4a8a5 100644 --- a/modules/ppcp-card-fields/src/CardFieldsModule.php +++ b/modules/ppcp-card-fields/src/CardFieldsModule.php @@ -89,6 +89,11 @@ class CardFieldsModule implements ModuleInterface { add_filter( 'ppcp_create_order_request_body_data', function( array $data ) use ( $c ): array { + $payment_method = wc_clean( wp_unslash( $_POST['payment_method'] ?? '' ) ); + if ( $payment_method !== CreditCardGateway::ID ) { + return $data; + } + $settings = $c->get( 'wcgateway.settings' ); assert( $settings instanceof Settings ); diff --git a/modules/ppcp-save-payment-methods/src/SavePaymentMethodsModule.php b/modules/ppcp-save-payment-methods/src/SavePaymentMethodsModule.php index b437e7285..135e2acec 100644 --- a/modules/ppcp-save-payment-methods/src/SavePaymentMethodsModule.php +++ b/modules/ppcp-save-payment-methods/src/SavePaymentMethodsModule.php @@ -20,12 +20,11 @@ use WooCommerce\PayPalCommerce\ApiClient\Exception\PayPalApiException; use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException; use WooCommerce\PayPalCommerce\SavePaymentMethods\Endpoint\CreatePaymentToken; use WooCommerce\PayPalCommerce\SavePaymentMethods\Endpoint\CreateSetupToken; -use WooCommerce\PayPalCommerce\Vaulting\PaymentTokenFactory; -use WooCommerce\PayPalCommerce\Vaulting\PaymentTokenHelper; use WooCommerce\PayPalCommerce\Vendor\Dhii\Container\ServiceProvider; use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface; use WooCommerce\PayPalCommerce\Vendor\Interop\Container\ServiceProviderInterface; use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface; +use WooCommerce\PayPalCommerce\WcGateway\Gateway\CreditCardGateway; use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway; /** @@ -112,16 +111,32 @@ class SavePaymentMethodsModule implements ModuleInterface { } } - $data['payment_source'] = array( - 'paypal' => array( - 'attributes' => array( - 'vault' => array( - 'store_in_vault' => 'ON_SUCCESS', - 'usage_type' => 'MERCHANT', + $payment_method = $data['payment_method'] ?? ''; + + if ( $payment_method === CreditCardGateway::ID ) { + $data['payment_source'] = array( + 'card' => array( + 'attributes' => array( + 'vault' => array( + 'store_in_vault' => 'ON_SUCCESS', + ), ), ), - ), - ); + ); + } + + if ( $payment_method === PayPalGateway::ID ) { + $data['payment_source'] = array( + 'paypal' => array( + 'attributes' => array( + 'vault' => array( + 'store_in_vault' => 'ON_SUCCESS', + 'usage_type' => 'MERCHANT', + ), + ), + ), + ); + } return $data; } @@ -137,23 +152,31 @@ class SavePaymentMethodsModule implements ModuleInterface { if ( $payment_vault_attributes ) { update_user_meta( $wc_order->get_customer_id(), '_ppcp_target_customer_id', $payment_vault_attributes->customer->id ); - $payment_token_helper = $c->get( 'vaulting.payment-token-helper' ); - assert( $payment_token_helper instanceof PaymentTokenHelper ); - - $payment_token_factory = $c->get( 'vaulting.payment-token-factory' ); - assert( $payment_token_factory instanceof PaymentTokenFactory ); - - $logger = $c->get( 'woocommerce.logger.woocommerce' ); - assert( $logger instanceof LoggerInterface ); - $wc_payment_tokens = $c->get( 'save-payment-methods.wc-payment-tokens' ); assert( $wc_payment_tokens instanceof WooCommercePaymentTokens ); - $wc_payment_tokens->create_payment_token_paypal( - $wc_order->get_customer_id(), - $payment_vault_attributes->id, - $payment_source->properties()->email_address ?? '' - ); + if ( $wc_order->get_payment_method() === CreditCardGateway::ID ) { + $token = new \WC_Payment_Token_CC(); + $token->set_token( $payment_vault_attributes->id ); + $token->set_user_id( $wc_order->get_customer_id() ); + $token->set_gateway_id( CreditCardGateway::ID ); + + $token->set_last4( $payment_source->properties()->last_digits ?? '' ); + $expiry = explode( '-', $payment_source->properties()->expiry ?? '' ); + $token->set_expiry_year( $expiry[0] ?? '' ); + $token->set_expiry_month( $expiry[1] ?? '' ); + $token->set_card_type( $payment_source->properties()->brand ?? '' ); + + $token->save(); + } + + if ( $wc_order->get_payment_method() === PayPalGateway::ID ) { + $wc_payment_tokens->create_payment_token_paypal( + $wc_order->get_customer_id(), + $payment_vault_attributes->id, + $payment_source->properties()->email_address ?? '' + ); + } } }, 10, @@ -276,5 +299,19 @@ class SavePaymentMethodsModule implements ModuleInterface { } } ); + + add_filter( + 'woocommerce_paypal_payments_credit_card_gateway_vault_supports', + function( array $supports ) use ( $c ): array { + $settings = $c->get( 'wcgateway.settings' ); + assert( $settings instanceof ContainerInterface ); + + if ( $settings->has( 'vault_enabled_dcc' ) && $settings->get( 'vault_enabled_dcc' ) ) { + $supports[] = 'tokenization'; + } + + return $supports; + } + ); } } diff --git a/modules/ppcp-wc-gateway/src/Gateway/CreditCardGateway.php b/modules/ppcp-wc-gateway/src/Gateway/CreditCardGateway.php index a37487ceb..08188a616 100644 --- a/modules/ppcp-wc-gateway/src/Gateway/CreditCardGateway.php +++ b/modules/ppcp-wc-gateway/src/Gateway/CreditCardGateway.php @@ -181,18 +181,25 @@ class CreditCardGateway extends \WC_Payment_Gateway_CC { ); if ( $this->config->has( 'vault_enabled_dcc' ) && $this->config->get( 'vault_enabled_dcc' ) ) { - array_push( + $supports = apply_filters( + 'woocommerce_paypal_payments_credit_card_gateway_vault_supports', + array( + 'subscriptions', + 'subscription_cancellation', + 'subscription_suspension', + 'subscription_reactivation', + 'subscription_amount_changes', + 'subscription_date_changes', + 'subscription_payment_method_change', + 'subscription_payment_method_change_customer', + 'subscription_payment_method_change_admin', + 'multiple_subscriptions', + ) + ); + + $this->supports = array_merge( $this->supports, - 'subscriptions', - 'subscription_cancellation', - 'subscription_suspension', - 'subscription_reactivation', - 'subscription_amount_changes', - 'subscription_date_changes', - 'subscription_payment_method_change', - 'subscription_payment_method_change_customer', - 'subscription_payment_method_change_admin', - 'multiple_subscriptions' + $supports ); } }