Skip to content

Commit 127f0a1

Browse files
james-allanwjrosaMayisha
authored andcommitted
Use metadata stored on the intent to fetch an order for webhook processing (#3567)
* Use metadata stored on the intent to fetch an order for webhook processing * Tidy comments * More comment changes * Comment tweaks * Add changelog entries * Add signature to root generate_payment_request() function * Update unit test to expect signature * Make sure guest customers are accounted for * Update tests/phpunit/test-class-wc-stripe-upe-payment-gateway.php Co-authored-by: Mayisha <[email protected]> * Update tests/phpunit/test-class-wc-stripe-upe-payment-gateway.php Co-authored-by: Mayisha <[email protected]> --------- Co-authored-by: Wesley Rosa <[email protected]> Co-authored-by: Mayisha <[email protected]>
1 parent cbb5fd6 commit 127f0a1

File tree

6 files changed

+76
-4
lines changed

6 files changed

+76
-4
lines changed

changelog.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
*** Changelog ***
22

33
= 8.9.0 - xxxx-xx-xx =
4+
* Update - Enhance webhook processing to enable retrieving orders using payment_intent metadata.
5+
* Dev - Minor updates to the webhook handler class related to payment method names constants.
6+
* Tweak - Improve error message displayed when payment method creation fails in classic checkout.
7+
* Dev - Replace two occurrences of payment method names with their constant equivalents.
48
* Fix - Hide express checkout when credit card payments are not enabled.
59
* Fix - Fix issues when detaching payment methods on staging sites (with the new checkout experience enabled).
610
* Fix - Display a notice if taxes vary by customer's billing address when checking out using the Stripe Express Checkout Element.

includes/abstracts/abstract-wc-stripe-payment-gateway.php

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -481,8 +481,9 @@ public function generate_payment_request( $order, $prepared_payment_method ) {
481481
$metadata = [
482482
__( 'customer_name', 'woocommerce-gateway-stripe' ) => sanitize_text_field( $billing_first_name ) . ' ' . sanitize_text_field( $billing_last_name ),
483483
__( 'customer_email', 'woocommerce-gateway-stripe' ) => sanitize_email( $billing_email ),
484-
'order_id' => $order->get_order_number(),
485-
'site_url' => esc_url( get_site_url() ),
484+
'order_id' => $order->get_order_number(),
485+
'site_url' => esc_url( get_site_url() ),
486+
'signature' => $this->get_order_signature( $order ),
486487
];
487488

488489
if ( $this->has_subscription( $order->get_id() ) ) {
@@ -2324,4 +2325,23 @@ public function get_balance_transaction_id_from_charge( $charge ) {
23242325

23252326
return $balance_transaction_id;
23262327
}
2328+
2329+
/**
2330+
* Generates a unique signature for an order.
2331+
*
2332+
* This signature is included as metadata in Stripe requests and used to identify the order when webhooks are received.
2333+
*
2334+
* @param WC_Order $order The Order object.
2335+
* @return string The order's unique signature. Format: order_id:md5(order_id-order_key-customer_id-order_total).
2336+
*/
2337+
protected function get_order_signature( $order ) {
2338+
$signature = [
2339+
absint( $order->get_id() ),
2340+
$order->get_order_key(),
2341+
$order->get_customer_id() ?? '',
2342+
WC_Stripe_Helper::get_stripe_amount( $order->get_total(), $order->get_currency() ),
2343+
];
2344+
2345+
return sprintf( '%d:%s', $order->get_id(), md5( implode( '-', $signature ) ) );
2346+
}
23272347
}

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

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -892,9 +892,14 @@ public function get_partial_amount_to_charge( $notification ) {
892892
return false;
893893
}
894894

895+
/**
896+
* Handles the processing of a payment intent webhook.
897+
*
898+
* @param stdClass $notification The webhook notification from Stripe.
899+
*/
895900
public function process_payment_intent_success( $notification ) {
896901
$intent = $notification->data->object;
897-
$order = WC_Stripe_Helper::get_order_by_intent_id( $intent->id );
902+
$order = $this->get_order_from_intent( $intent );
898903

899904
if ( ! $order ) {
900905
WC_Stripe_Logger::log( 'Could not find order via intent ID: ' . $intent->id );
@@ -1198,6 +1203,43 @@ public function process_webhook( $request_body ) {
11981203

11991204
}
12001205
}
1206+
1207+
/**
1208+
* Fetches an order from a payment intent.
1209+
*
1210+
* @param stdClass $intent The Stripe PaymentIntent object.
1211+
* @return WC_Order|false The order object, or false if not found.
1212+
*/
1213+
private function get_order_from_intent( $intent ) {
1214+
// Attempt to get the order from the intent metadata.
1215+
if ( isset( $intent->metadata->signature ) ) {
1216+
$signature = wc_clean( $intent->metadata->signature );
1217+
$data = explode( ':', $signature );
1218+
1219+
// Verify we received the order ID and signature (hash).
1220+
$order = isset( $data[0], $data[1] ) ? wc_get_order( absint( $data[0] ) ) : false;
1221+
1222+
if ( $order ) {
1223+
$intent_id = WC_Stripe_Helper::get_intent_id_from_order( $order );
1224+
1225+
// Return the order if the intent ID matches.
1226+
if ( $intent->id === $intent_id ) {
1227+
return $order;
1228+
}
1229+
1230+
/**
1231+
* If the order has no intent ID stored, we may have failed to store it during the initial payment request.
1232+
* Confirm that the signature matches the order, otherwise fall back to finding the order via the intent ID.
1233+
*/
1234+
if ( empty( $intent_id ) && $this->get_order_signature( $order ) === $signature ) {
1235+
return $order;
1236+
}
1237+
}
1238+
}
1239+
1240+
// Fall back to finding the order via the intent ID.
1241+
return WC_Stripe_Helper::get_order_by_intent_id( $intent->id );
1242+
}
12011243
}
12021244

12031245
new WC_Stripe_Webhook_Handler();

includes/payment-methods/class-wc-stripe-upe-payment-gateway.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1750,6 +1750,7 @@ public function get_metadata_from_order( $order ) {
17501750
'order_id' => $order->get_order_number(),
17511751
'order_key' => $order->get_order_key(),
17521752
'payment_type' => $payment_type,
1753+
'signature' => $this->get_order_signature( $order ),
17531754
];
17541755

17551756
return apply_filters( 'wc_stripe_intent_metadata', $metadata, $order );

readme.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,10 @@ If you get stuck, you can ask for help in the [Plugin Forum](https://wordpress.o
111111
== Changelog ==
112112

113113
= 8.9.0 - xxxx-xx-xx =
114+
* Update - Enhance webhook processing to enable retrieving orders using payment_intent metadata.
115+
* Dev - Minor updates to the webhook handler class related to payment method names constants.
116+
* Tweak - Improve error message displayed when payment method creation fails in classic checkout.
117+
* Dev - Replace two occurrences of payment method names with their constant equivalents.
114118
* Fix - Hide express checkout when credit card payments are not enabled.
115119
* Fix - Fix issues when detaching payment methods on staging sites (with the new checkout experience enabled).
116120
* Fix - Display a notice if taxes vary by customer's billing address when checking out using the Stripe Express Checkout Element.

tests/phpunit/test-class-wc-stripe-upe-payment-gateway.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -218,9 +218,10 @@ private function get_order_details( $order ) {
218218
'customer_name' => 'Jeroen Sormani',
219219
'customer_email' => '[email protected]',
220220
'site_url' => 'http://example.org',
221-
'order_id' => $order_id,
221+
'order_id' => $order_number,
222222
'order_key' => $order_key,
223223
'payment_type' => 'single',
224+
'signature' => sprintf( '%d:%s', $order->get_id(), md5( implode( '-', [ absint( $order->get_id() ), $order->get_order_key(), $order->get_customer_id(), $amount ] ) ) ),
224225
];
225226
return [ $amount, $description, $metadata ];
226227
}

0 commit comments

Comments
 (0)