Skip to content

Commit b9b4d1f

Browse files
mattallanmattallan
authored andcommitted
Process payment intent webhook for successful card purchases asynchronously (#3575)
* Refactor process_payment_intent_success() to default to processing succeeded webhook async * Don't call process_response() with a null charge object if not found * Add changelog entry * Trim whitespace off the end and tweak wording of log
1 parent 61385aa commit b9b4d1f

File tree

3 files changed

+21
-19
lines changed

3 files changed

+21
-19
lines changed

changelog.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
= 8.8.2 - xxxx-xx-xx =
44
* Fix - Prevent marking renewal orders as processing/completed multiple times due to handling the Stripe webhook in parallel.
55
* Dev - Refactor lock_order_payment() to use order meta instead of transients.
6+
* Update - Process successful payment intent webhooks asynchronously.
67

78
= 8.8.1 - 2024-10-28 =
89
* Tweak - Disables APMs when using the legacy checkout experience due Stripe deprecation by October 29, 2024.

includes/class-wc-stripe-webhook-handler.php

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -928,22 +928,20 @@ public function process_payment_intent_success( $notification ) {
928928
break;
929929
case 'payment_intent.succeeded':
930930
case 'payment_intent.amount_capturable_updated':
931-
$charge = $this->get_latest_charge_from_intent( $intent );
932-
933931
WC_Stripe_Logger::log( "Stripe PaymentIntent $intent->id succeeded for order $order_id" );
934932

935-
/**
936-
* Check if the order is awaiting further action from the customer. If so, do not process the payment via the webhook, let the redirect handle it.
937-
*
938-
* This is a stop-gap to fix a critical issue, see https://github.com/woocommerce/woocommerce-gateway-stripe/issues/2536. It would
939-
* be better if we removed the need for additional meta data in favor of refactoring this part of the payment processing.
940-
*/
941-
$is_awaiting_action = $order->get_meta( '_stripe_upe_waiting_for_redirect' ) ?? false;
933+
$process_webhook_async = apply_filters( 'wc_stripe_process_payment_intent_webhook_async', true, $order, $intent, $notification );
934+
$is_awaiting_action = $order->get_meta( '_stripe_upe_waiting_for_redirect' ) ?? false;
935+
936+
// Process the webhook now if it's for a voucher or wallet payment , or if filtered to process immediately and order is not awaiting action.
937+
if ( $is_voucher_payment || $is_wallet_payment || ( ! $process_webhook_async && ! $is_awaiting_action ) ) {
938+
$charge = $this->get_latest_charge_from_intent( $intent );
942939

943-
// Voucher payments are only processed via the webhook so are excluded from the above check.
944-
// Wallets are also processed via the webhook, not redirection.
945-
if ( ! $is_voucher_payment && ! $is_wallet_payment && $is_awaiting_action ) {
946-
WC_Stripe_Logger::log( "Stripe UPE waiting for redirect. Scheduled deferred webhook processing. The status for order $order_id might need manual adjustment." );
940+
do_action( 'wc_gateway_stripe_process_payment', $charge, $order );
941+
942+
$this->process_response( $charge, $order );
943+
} else {
944+
WC_Stripe_Logger::log( "Processing $notification->type ($intent->id) asynchronously for order $order_id." );
947945

948946
// Schedule a job to check on the status of this intent.
949947
$this->defer_webhook_processing(
@@ -954,14 +952,11 @@ public function process_payment_intent_success( $notification ) {
954952
]
955953
);
956954

957-
do_action( 'wc_gateway_stripe_process_payment_intent_incomplete', $order );
958-
return;
955+
if ( $is_awaiting_action ) {
956+
do_action( 'wc_gateway_stripe_process_payment_intent_incomplete', $order );
957+
}
959958
}
960959

961-
do_action( 'wc_gateway_stripe_process_payment', $charge, $order );
962-
963-
// Process valid response.
964-
$this->process_response( $charge, $order );
965960
break;
966961
default:
967962
if ( $is_voucher_payment && 'payment_intent.payment_failed' === $notification->type ) {
@@ -1123,6 +1118,11 @@ protected function handle_deferred_payment_intent_succeeded( $order, $intent_id
11231118

11241119
$charge = $this->get_latest_charge_from_intent( $intent );
11251120

1121+
if ( ! $charge ) {
1122+
WC_Stripe_Logger::log( "Skipped processing deferred webhook for Stripe PaymentIntent {$intent_id} for order {$order->get_id()} - no charge found." );
1123+
return;
1124+
}
1125+
11261126
WC_Stripe_Logger::log( "Processing Stripe PaymentIntent {$intent_id} for order {$order->get_id()} via deferred webhook." );
11271127

11281128
do_action( 'wc_gateway_stripe_process_payment', $charge, $order );

readme.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,5 +113,6 @@ If you get stuck, you can ask for help in the [Plugin Forum](https://wordpress.o
113113
= 8.8.2 - xxxx-xx-xx =
114114
* Fix - Prevent marking renewal orders as processing/completed multiple times due to handling the Stripe webhook in parallel.
115115
* Dev - Refactor lock_order_payment() to use order meta instead of transients.
116+
* Update - Process successful payment intent webhooks asynchronously.
116117

117118
[See changelog for all versions](https://raw.githubusercontent.com/woocommerce/woocommerce-gateway-stripe/trunk/changelog.txt).

0 commit comments

Comments
 (0)