From 78ef57145c74fa8f18063cc4c583506ff37b7a87 Mon Sep 17 00:00:00 2001 From: Emili Castells Guasch Date: Fri, 1 Mar 2024 11:17:27 +0100 Subject: [PATCH 1/4] Use intent value from settings --- modules/ppcp-save-payment-methods/services.php | 1 + .../src/Endpoint/CaptureCardPayment.php | 16 ++++++++++++++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/modules/ppcp-save-payment-methods/services.php b/modules/ppcp-save-payment-methods/services.php index 74db6f203..f60b1e6fd 100644 --- a/modules/ppcp-save-payment-methods/services.php +++ b/modules/ppcp-save-payment-methods/services.php @@ -829,6 +829,7 @@ $container->get( 'api.endpoint.order' ), $container->get( 'session.handler' ), $container->get( 'wc-subscriptions.helpers.real-time-account-updater' ), + $container->get( 'wcgateway.settings' ), $container->get( 'woocommerce.logger.woocommerce' ) ); }, diff --git a/modules/ppcp-save-payment-methods/src/Endpoint/CaptureCardPayment.php b/modules/ppcp-save-payment-methods/src/Endpoint/CaptureCardPayment.php index 07db9a3a2..6d18a82a6 100644 --- a/modules/ppcp-save-payment-methods/src/Endpoint/CaptureCardPayment.php +++ b/modules/ppcp-save-payment-methods/src/Endpoint/CaptureCardPayment.php @@ -22,6 +22,7 @@ use WooCommerce\PayPalCommerce\Button\Endpoint\EndpointInterface; use WooCommerce\PayPalCommerce\Button\Endpoint\RequestData; use WooCommerce\PayPalCommerce\Session\SessionHandler; +use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings; use WooCommerce\PayPalCommerce\WcSubscriptions\Helper\RealTimeAccountUpdaterHelper; use WP_Error; @@ -90,6 +91,13 @@ class CaptureCardPayment implements EndpointInterface { */ private $real_time_account_updater_helper; + /** + * The settings. + * + * @var Settings + */ + private $settings; + /** * The logger. * @@ -108,6 +116,7 @@ class CaptureCardPayment implements EndpointInterface { * @param OrderEndpoint $order_endpoint The order endpoint. * @param SessionHandler $session_handler The session handler. * @param RealTimeAccountUpdaterHelper $real_time_account_updater_helper Real Time Account Updater helper. + * @param Settings $settings The settings. * @param LoggerInterface $logger The logger. */ public function __construct( @@ -119,6 +128,7 @@ public function __construct( OrderEndpoint $order_endpoint, SessionHandler $session_handler, RealTimeAccountUpdaterHelper $real_time_account_updater_helper, + Settings $settings, LoggerInterface $logger ) { $this->request_data = $request_data; @@ -130,6 +140,7 @@ public function __construct( $this->session_handler = $session_handler; $this->real_time_account_updater_helper = $real_time_account_updater_helper; $this->logger = $logger; + $this->settings = $settings; } /** @@ -198,10 +209,11 @@ public function handle_request(): bool { * @throws RuntimeException When request fails. */ private function create_order( string $vault_id ): stdClass { - $items = array( $this->purchase_unit_factory->from_wc_cart() ); + $intent = $this->settings->has( 'intent' ) && strtoupper( (string) $this->settings->get( 'intent' ) ) === 'AUTHORIZE' ? 'AUTHORIZE' : 'CAPTURE'; + $items = array( $this->purchase_unit_factory->from_wc_cart() ); $data = array( - 'intent' => 'CAPTURE', + 'intent' => $intent, 'purchase_units' => array_map( static function ( PurchaseUnit $item ): array { return $item->to_array( true, false ); From 6aedb517078140156181be223113b9e2842d8490 Mon Sep 17 00:00:00 2001 From: Emili Castells Guasch Date: Fri, 1 Mar 2024 13:55:00 +0100 Subject: [PATCH 2/4] Ensure correct transaction url by saving payment mode meta --- modules/ppcp-wc-gateway/services.php | 5 +-- .../src/Gateway/CreditCardGateway.php | 35 +++++++++++++------ 2 files changed, 28 insertions(+), 12 deletions(-) diff --git a/modules/ppcp-wc-gateway/services.php b/modules/ppcp-wc-gateway/services.php index 264cf3c1f..cd04bd00c 100644 --- a/modules/ppcp-wc-gateway/services.php +++ b/modules/ppcp-wc-gateway/services.php @@ -127,9 +127,10 @@ $state, $transaction_url_provider, $subscription_helper, - $logger, $payments_endpoint, - $vaulted_credit_card_handler + $vaulted_credit_card_handler, + $container->get( 'onboarding.environment' ), + $logger ); }, 'wcgateway.card-button-gateway' => static function ( ContainerInterface $container ): CardButtonGateway { diff --git a/modules/ppcp-wc-gateway/src/Gateway/CreditCardGateway.php b/modules/ppcp-wc-gateway/src/Gateway/CreditCardGateway.php index 424ed2d8b..03dcfcb77 100644 --- a/modules/ppcp-wc-gateway/src/Gateway/CreditCardGateway.php +++ b/modules/ppcp-wc-gateway/src/Gateway/CreditCardGateway.php @@ -16,6 +16,7 @@ use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PaymentsEndpoint; use WooCommerce\PayPalCommerce\ApiClient\Exception\PayPalApiException; use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException; +use WooCommerce\PayPalCommerce\Onboarding\Environment; use WooCommerce\PayPalCommerce\Onboarding\State; use WooCommerce\PayPalCommerce\Session\SessionHandler; use WooCommerce\PayPalCommerce\WcGateway\Processor\TransactionIdHandlingTrait; @@ -115,18 +116,25 @@ class CreditCardGateway extends \WC_Payment_Gateway_CC { protected $subscription_helper; /** - * The logger. + * The payments endpoint * - * @var LoggerInterface + * @var PaymentsEndpoint */ - protected $logger; + protected $payments_endpoint; /** - * The payments endpoint + * The environment. * - * @var PaymentsEndpoint + * @var Environment */ - protected $payments_endpoint; + private $environment; + + /** + * The logger. + * + * @var LoggerInterface + */ + protected $logger; /** * CreditCardGateway constructor. @@ -140,9 +148,10 @@ class CreditCardGateway extends \WC_Payment_Gateway_CC { * @param State $state The state. * @param TransactionUrlProvider $transaction_url_provider Service able to provide view transaction url base. * @param SubscriptionHelper $subscription_helper The subscription helper. - * @param LoggerInterface $logger The logger. * @param PaymentsEndpoint $payments_endpoint The payments endpoint. * @param VaultedCreditCardHandler $vaulted_credit_card_handler The vaulted credit card handler. + * @param Environment $environment The environment. + * @param LoggerInterface $logger The logger. */ public function __construct( SettingsRenderer $settings_renderer, @@ -154,9 +163,10 @@ public function __construct( State $state, TransactionUrlProvider $transaction_url_provider, SubscriptionHelper $subscription_helper, - LoggerInterface $logger, PaymentsEndpoint $payments_endpoint, - VaultedCreditCardHandler $vaulted_credit_card_handler + VaultedCreditCardHandler $vaulted_credit_card_handler, + Environment $environment, + LoggerInterface $logger ) { $this->id = self::ID; $this->settings_renderer = $settings_renderer; @@ -168,9 +178,10 @@ public function __construct( $this->state = $state; $this->transaction_url_provider = $transaction_url_provider; $this->subscription_helper = $subscription_helper; - $this->logger = $logger; $this->payments_endpoint = $payments_endpoint; $this->vaulted_credit_card_handler = $vaulted_credit_card_handler; + $this->environment = $environment; + $this->logger = $logger; if ( $state->current_state() === State::STATE_ONBOARDED ) { $this->supports = array( 'refunds' ); @@ -370,6 +381,10 @@ public function process_payment( $order_id ) { if ( $saved_payment_card ) { if ( $saved_payment_card['payment_source'] === 'card' && $saved_payment_card['status'] === 'COMPLETED' ) { $wc_order->update_meta_data( PayPalGateway::ORDER_ID_META_KEY, $saved_payment_card['order_id'] ); + $wc_order->update_meta_data( + PayPalGateway::ORDER_PAYMENT_MODE_META_KEY, + $this->environment->current_environment_is( Environment::SANDBOX ) ? 'sandbox' : 'live' + ); $wc_order->save_meta_data(); $this->update_transaction_id( $saved_payment_card['order_id'], $wc_order ); From fd829933c4eafd69c86de9260bf73dff2be7a01e Mon Sep 17 00:00:00 2001 From: Emili Castells Guasch Date: Fri, 1 Mar 2024 16:21:09 +0100 Subject: [PATCH 3/4] Add authorize handling for saved card payment token (WIP) --- modules/ppcp-wc-gateway/services.php | 1 + .../src/Gateway/CreditCardGateway.php | 42 +++++++++++++++++-- 2 files changed, 40 insertions(+), 3 deletions(-) diff --git a/modules/ppcp-wc-gateway/services.php b/modules/ppcp-wc-gateway/services.php index cd04bd00c..f7521ad61 100644 --- a/modules/ppcp-wc-gateway/services.php +++ b/modules/ppcp-wc-gateway/services.php @@ -130,6 +130,7 @@ $payments_endpoint, $vaulted_credit_card_handler, $container->get( 'onboarding.environment' ), + $container->get( 'api.endpoint.order' ), $logger ); }, diff --git a/modules/ppcp-wc-gateway/src/Gateway/CreditCardGateway.php b/modules/ppcp-wc-gateway/src/Gateway/CreditCardGateway.php index 03dcfcb77..421c2675e 100644 --- a/modules/ppcp-wc-gateway/src/Gateway/CreditCardGateway.php +++ b/modules/ppcp-wc-gateway/src/Gateway/CreditCardGateway.php @@ -13,12 +13,15 @@ use Psr\Log\LoggerInterface; use WC_Order; use WC_Payment_Tokens; +use WooCommerce\PayPalCommerce\ApiClient\Endpoint\OrderEndpoint; use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PaymentsEndpoint; use WooCommerce\PayPalCommerce\ApiClient\Exception\PayPalApiException; use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException; use WooCommerce\PayPalCommerce\Onboarding\Environment; use WooCommerce\PayPalCommerce\Onboarding\State; use WooCommerce\PayPalCommerce\Session\SessionHandler; +use WooCommerce\PayPalCommerce\WcGateway\Processor\AuthorizedPaymentsProcessor; +use WooCommerce\PayPalCommerce\WcGateway\Processor\PaymentsStatusHandlingTrait; use WooCommerce\PayPalCommerce\WcGateway\Processor\TransactionIdHandlingTrait; use WooCommerce\PayPalCommerce\WcSubscriptions\Helper\SubscriptionHelper; use WooCommerce\PayPalCommerce\Vaulting\PaymentTokenRepository; @@ -34,7 +37,7 @@ */ class CreditCardGateway extends \WC_Payment_Gateway_CC { - use ProcessPaymentTrait, GatewaySettingsRendererTrait, TransactionIdHandlingTrait; + use ProcessPaymentTrait, GatewaySettingsRendererTrait, TransactionIdHandlingTrait, PaymentsStatusHandlingTrait; const ID = 'ppcp-credit-card-gateway'; @@ -129,6 +132,13 @@ class CreditCardGateway extends \WC_Payment_Gateway_CC { */ private $environment; + /** + * The order endpoint. + * + * @var OrderEndpoint + */ + private $order_endpoint; + /** * The logger. * @@ -151,6 +161,7 @@ class CreditCardGateway extends \WC_Payment_Gateway_CC { * @param PaymentsEndpoint $payments_endpoint The payments endpoint. * @param VaultedCreditCardHandler $vaulted_credit_card_handler The vaulted credit card handler. * @param Environment $environment The environment. + * @param OrderEndpoint $order_endpoint The order endpoint. * @param LoggerInterface $logger The logger. */ public function __construct( @@ -166,6 +177,7 @@ public function __construct( PaymentsEndpoint $payments_endpoint, VaultedCreditCardHandler $vaulted_credit_card_handler, Environment $environment, + OrderEndpoint $order_endpoint, LoggerInterface $logger ) { $this->id = self::ID; @@ -181,6 +193,7 @@ public function __construct( $this->payments_endpoint = $payments_endpoint; $this->vaulted_credit_card_handler = $vaulted_credit_card_handler; $this->environment = $environment; + $this->order_endpoint = $order_endpoint; $this->logger = $logger; if ( $state->current_state() === State::STATE_ONBOARDED ) { @@ -387,12 +400,35 @@ public function process_payment( $order_id ) { ); $wc_order->save_meta_data(); - $this->update_transaction_id( $saved_payment_card['order_id'], $wc_order ); - $wc_order->payment_complete(); + $order_id = $saved_payment_card['order_id'] ?? ''; + if ( $order_id ) { + $order = $this->order_endpoint->order( $order_id ); + $wc_order->update_meta_data( PayPalGateway::INTENT_META_KEY, $order->intent() ); + + if ( $order->intent() === 'AUTHORIZE' ) { + $order = $this->order_endpoint->authorize( $order ); + + $wc_order->update_meta_data( AuthorizedPaymentsProcessor::CAPTURED_META_KEY, 'false' ); + + if ( $this->subscription_helper->has_subscription( $wc_order->get_id() ) ) { + $wc_order->update_meta_data( '_ppcp_captured_vault_webhook', 'false' ); + } + } + + $transaction_id = $this->get_paypal_order_transaction_id( $order ); + if ( $transaction_id ) { + $this->update_transaction_id( $transaction_id, $wc_order ); + } + + $this->handle_new_order_status( $order, $wc_order ); + } + WC()->session->set( 'ppcp_saved_payment_card', null ); return $this->handle_payment_success( $wc_order ); } + + WC()->session->set( 'ppcp_saved_payment_card', null ); } /** From 2d1e8d0a288dce4d3db79bdf736e829b0a5e83dc Mon Sep 17 00:00:00 2001 From: Emili Castells Guasch Date: Mon, 4 Mar 2024 09:51:33 +0100 Subject: [PATCH 4/4] Fix phpunit --- .../WcGateway/Gateway/CreditCardGatewayTest.php | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/tests/PHPUnit/WcGateway/Gateway/CreditCardGatewayTest.php b/tests/PHPUnit/WcGateway/Gateway/CreditCardGatewayTest.php index 15689d08e..08d5a77b2 100644 --- a/tests/PHPUnit/WcGateway/Gateway/CreditCardGatewayTest.php +++ b/tests/PHPUnit/WcGateway/Gateway/CreditCardGatewayTest.php @@ -4,6 +4,8 @@ namespace WooCommerce\PayPalCommerce\WcGateway\Gateway; use Mockery; +use WooCommerce\PayPalCommerce\ApiClient\Endpoint\OrderEndpoint; +use WooCommerce\PayPalCommerce\Onboarding\Environment; use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface; use Psr\Log\LoggerInterface; use WC_Order; @@ -32,6 +34,8 @@ class CreditCardGatewayTest extends TestCase private $logger; private $paymentsEndpoint; private $vaultedCreditCardHandler; + private $environment; + private $orderEndpoint; private $testee; public function setUp(): void @@ -50,6 +54,8 @@ public function setUp(): void $this->logger = Mockery::mock(LoggerInterface::class); $this->paymentsEndpoint = Mockery::mock(PaymentsEndpoint::class); $this->vaultedCreditCardHandler = Mockery::mock(VaultedCreditCardHandler::class); + $this->environment = Mockery::mock(Environment::class); + $this->orderEndpoint = Mockery::mock(OrderEndpoint::class); $this->state->shouldReceive('current_state')->andReturn(State::STATE_ONBOARDED); $this->config->shouldReceive('has')->andReturn(true); @@ -67,9 +73,11 @@ public function setUp(): void $this->state, $this->transactionUrlProvider, $this->subscriptionHelper, - $this->logger, $this->paymentsEndpoint, - $this->vaultedCreditCardHandler + $this->vaultedCreditCardHandler, + $this->environment, + $this->orderEndpoint, + $this->logger ); }