Skip to content

Commit ba5de3a

Browse files
authored
Require the verified PaymentIntent to belong to the order being completed (#1416)
1 parent 9ad2246 commit ba5de3a

1 file changed

Lines changed: 19 additions & 0 deletions

File tree

modules/membership/includes/Admin/Services/Stripe/StripeService.php

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1015,6 +1015,25 @@ public function update_order( $data ) {
10151015
} elseif ( 'succeeded' === $payment_status ) {
10161016
$member_order = $this->members_orders_repository->get_member_orders( $member_id );
10171017

1018+
// The retrieved PaymentIntent must belong to the order being completed. Verification runs
1019+
// against the order that owns the transaction while completion applies to the member's newest
1020+
// order; without this guard a succeeded PaymentIntent from an earlier order can be replayed to
1021+
// complete a newer pending order, renewing/extending a membership with no new payment.
1022+
if ( empty( $member_order ) || (int) $latest_order['ID'] !== (int) $member_order['ID'] ) {
1023+
return $this->update_order_error(
1024+
$response,
1025+
__( 'Payment verification failed.', 'user-registration' ),
1026+
'Payment confirmation rejected: PaymentIntent does not belong to the order being completed',
1027+
array(
1028+
'error_code' => 'PAYMENT_INTENT_ORDER_MISMATCH',
1029+
'member_id' => $member_id,
1030+
'payment_intent_id' => $pi_id,
1031+
'verified_order_id' => $latest_order['ID'],
1032+
'target_order_id' => $member_order['ID'] ?? 0,
1033+
)
1034+
);
1035+
}
1036+
10181037
if ( 'completed' === $member_order['status'] ) {
10191038
$response['message'] = $is_upgrading ? __( 'Membership upgraded successfully.', 'user-registration' ) : get_option( 'user_registration_successful_membership_creation_message', esc_html__( 'New member has been successfully created.', 'user-registration' ) );
10201039
$response['status'] = true;

0 commit comments

Comments
 (0)