@@ -525,15 +525,30 @@ public function process_webhook_capture( $notification ) {
525
525
* @param object $notification
526
526
*/
527
527
public function process_webhook_charge_succeeded ( $ notification ) {
528
- // The following payment methods are synchronous so does not need to be handle via webhook.
529
- if ( ( isset ( $ notification -> data -> object -> source -> type ) && WC_Stripe_Payment_Methods:: CARD === $ notification -> data -> object -> source -> type ) || ( isset ( $ notification ->data -> object -> source -> type ) && ' three_d_secure ' === $ notification -> data -> object -> source -> type ) ) {
528
+ if ( empty ( $ notification -> data -> object ) ) {
529
+ WC_Stripe_Logger:: log ( ' Missing charge object in charge.succeeded webhook, Event ID: %s ' , $ notification ->id ?? ' unknown ' );
530
530
return ;
531
531
}
532
532
533
- $ order = WC_Stripe_Helper::get_order_by_charge_id ( $ notification ->data ->object ->id );
533
+ // https://docs.stripe.com/api/events/types#event_types-charge.succeeded
534
+ $ charge = $ notification ->data ->object ;
535
+
536
+ // The following payment methods are synchronous so does not need to be handled via webhook.
537
+ $ payment_method_type = $ this ->get_payment_method_type_from_charge ( $ charge );
538
+ $ synchronous_methods = [
539
+ WC_Stripe_Payment_Methods::CARD ,
540
+ WC_Stripe_Payment_Methods::AMAZON_PAY ,
541
+ 'three_d_secure ' ,
542
+ ];
543
+
544
+ if ( in_array ( $ payment_method_type , $ synchronous_methods , true ) ) {
545
+ return ;
546
+ }
547
+
548
+ $ order = WC_Stripe_Helper::get_order_by_charge_id ( $ charge ->id );
534
549
535
550
if ( ! $ order ) {
536
- WC_Stripe_Logger::log ( 'Could not find order via charge ID: ' . $ notification -> data -> object ->id );
551
+ WC_Stripe_Logger::log ( 'Could not find order via charge ID: ' . $ charge ->id );
537
552
return ;
538
553
}
539
554
@@ -545,15 +560,15 @@ public function process_webhook_charge_succeeded( $notification ) {
545
560
// setting is enabled, Stripe API still sends a "charge.succeeded" webhook but
546
561
// the payment has not been captured, yet. This ensures that the payment has been
547
562
// captured, before completing the payment.
548
- if ( ! $ notification -> data -> object ->captured ) {
563
+ if ( ! $ charge ->captured ) {
549
564
return ;
550
565
}
551
566
552
567
// Store other data such as fees
553
- $ order ->set_transaction_id ( $ notification -> data -> object ->id );
568
+ $ order ->set_transaction_id ( $ charge ->id );
554
569
555
- if ( isset ( $ notification -> data -> object ->balance_transaction ) ) {
556
- $ this ->update_fees ( $ order , $ notification -> data -> object ->balance_transaction );
570
+ if ( isset ( $ charge ->balance_transaction ) ) {
571
+ $ this ->update_fees ( $ order , $ charge ->balance_transaction );
557
572
}
558
573
559
574
/**
@@ -568,10 +583,10 @@ public function process_webhook_charge_succeeded( $notification ) {
568
583
* to ensure the review.closed event handler will update the status to the proper status.
569
584
*/
570
585
if ( 'manual_review ' !== $ this ->get_risk_outcome ( $ notification ) ) {
571
- $ order ->payment_complete ( $ notification -> data -> object ->id );
586
+ $ order ->payment_complete ( $ charge ->id );
572
587
573
588
/* translators: transaction id */
574
- $ order ->add_order_note ( sprintf ( __ ( 'Stripe charge complete (Charge ID: %s) ' , 'woocommerce-gateway-stripe ' ), $ notification -> data -> object ->id ) );
589
+ $ order ->add_order_note ( sprintf ( __ ( 'Stripe charge complete (Charge ID: %s) ' , 'woocommerce-gateway-stripe ' ), $ charge ->id ) );
575
590
}
576
591
577
592
if ( is_callable ( [ $ order , 'save ' ] ) ) {
@@ -1358,6 +1373,27 @@ private function get_order_from_intent( $intent ) {
1358
1373
// Fall back to finding the order via the intent ID.
1359
1374
return WC_Stripe_Helper::get_order_by_intent_id ( $ intent ->id );
1360
1375
}
1376
+
1377
+ /**
1378
+ * Get the payment method type from the charge object.
1379
+ * https://docs.stripe.com/api/charges/object
1380
+ *
1381
+ * @param object $charge The charge object from Stripe
1382
+ * @return string|null The payment method type, or null if not found
1383
+ */
1384
+ private function get_payment_method_type_from_charge ( $ charge ) {
1385
+ // We don't expect $charge->source to be set,
1386
+ // but we keep it here to ensure backwards compatibility.
1387
+ if ( isset ( $ charge ->source ->type ) ) {
1388
+ return $ charge ->source ->type ;
1389
+ }
1390
+
1391
+ if ( isset ( $ charge ->payment_method_details ->type ) ) {
1392
+ return $ charge ->payment_method_details ->type ;
1393
+ }
1394
+
1395
+ return null ;
1396
+ }
1361
1397
}
1362
1398
1363
1399
new WC_Stripe_Webhook_Handler ();
0 commit comments