From 7c43d9128864535fcb49029c48283e2df688a89f Mon Sep 17 00:00:00 2001 From: Alex P Date: Tue, 14 Feb 2023 10:29:08 +0200 Subject: [PATCH] Allow to capture automatically on status change --- .../ppcp-onboarding/resources/js/settings.js | 4 ++ modules/ppcp-wc-gateway/services.php | 17 ++++++ .../ppcp-wc-gateway/src/WCGatewayModule.php | 53 +++++++++++++++++++ 3 files changed, 74 insertions(+) diff --git a/modules/ppcp-onboarding/resources/js/settings.js b/modules/ppcp-onboarding/resources/js/settings.js index 2eaad8ed2..44fa692ed 100644 --- a/modules/ppcp-onboarding/resources/js/settings.js +++ b/modules/ppcp-onboarding/resources/js/settings.js @@ -396,6 +396,10 @@ document.addEventListener( { value:'authorize', selector:'#field-capture_for_virtual_only' + }, + { + value:'authorize', + selector:'#field-capture_on_status_change' } ] ); diff --git a/modules/ppcp-wc-gateway/services.php b/modules/ppcp-wc-gateway/services.php index ca6281e98..5d5b8cad2 100644 --- a/modules/ppcp-wc-gateway/services.php +++ b/modules/ppcp-wc-gateway/services.php @@ -538,6 +538,23 @@ return array( 'requirements' => array(), 'gateway' => 'paypal', ), + 'capture_on_status_change' => array( + 'title' => __( 'Capture On Status Change', 'woocommerce-paypal-payments' ), + 'type' => 'checkbox', + 'default' => false, + 'desc_tip' => true, + 'description' => __( + 'The transaction will be captured automatically when the order status changes to Processing or Completed.', + 'woocommerce-paypal-payments' + ), + 'label' => __( 'Capture On Status Change', 'woocommerce-paypal-payments' ), + 'screens' => array( + State::STATE_START, + State::STATE_ONBOARDED, + ), + 'requirements' => array(), + 'gateway' => 'paypal', + ), 'capture_for_virtual_only' => array( 'title' => __( 'Capture Virtual-Only Orders ', 'woocommerce-paypal-payments' ), 'type' => 'checkbox', diff --git a/modules/ppcp-wc-gateway/src/WCGatewayModule.php b/modules/ppcp-wc-gateway/src/WCGatewayModule.php index b5d2939d0..2f0dca8ec 100644 --- a/modules/ppcp-wc-gateway/src/WCGatewayModule.php +++ b/modules/ppcp-wc-gateway/src/WCGatewayModule.php @@ -9,6 +9,8 @@ declare(strict_types=1); namespace WooCommerce\PayPalCommerce\WcGateway; +use Psr\Log\LoggerInterface; +use Throwable; use WooCommerce\PayPalCommerce\Vendor\Dhii\Container\ServiceProvider; use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface; use WC_Order; @@ -306,6 +308,57 @@ class WCGatewayModule implements ModuleInterface { $endpoint->handle_request(); } ); + + add_action( + 'woocommerce_order_status_changed', + static function ( int $order_id, string $from, string $to ) use ( $c ) { + $wc_order = wc_get_order( $order_id ); + if ( ! $wc_order instanceof WC_Order ) { + return; + } + + $settings = $c->get( 'wcgateway.settings' ); + assert( $settings instanceof ContainerInterface ); + + if ( ! $settings->has( 'capture_on_status_change' ) || ! $settings->get( 'capture_on_status_change' ) ) { + 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 ) { + return; + } + + /** + * The filter returning the WC order statuses which trigger capturing of payment authorization. + */ + $capture_statuses = apply_filters( 'woocommerce_paypal_payments_auto_capture_statuses', array( 'processing', 'completed' ), $wc_order ); + if ( ! in_array( $to, $capture_statuses, true ) ) { + return; + } + + $authorized_payment_processor = $c->get( 'wcgateway.processor.authorized-payments' ); + assert( $authorized_payment_processor instanceof AuthorizedPaymentsProcessor ); + + try { + if ( $authorized_payment_processor->capture_authorized_payment( $wc_order ) ) { + return; + } + } catch ( Throwable $error ) { + $logger = $c->get( 'woocommerce.logger.woocommerce' ); + assert( $logger instanceof LoggerInterface ); + $logger->error( "Capture failed. {$error->getMessage()} {$error->getFile()}:{$error->getLine()}" ); + } + + $wc_order->update_status( + 'failed', + __( 'Could not capture the payment.', 'woocommerce-paypal-payments' ) + ); + }, + 10, + 3 + ); } /**