From 6d372efbed08bc4ef7d946fb36acb67458896433 Mon Sep 17 00:00:00 2001 From: Sahkal Poddar Date: Fri, 12 Jul 2024 05:14:16 +0530 Subject: [PATCH] fix(router): fixed integrity check failures in case of 3ds flow in sync flow (#5279) --- .../src/router_request_types.rs | 3 - .../hyperswitch_interfaces/src/integrity.rs | 75 +++++++++++++------ crates/router/src/connector/stripe.rs | 1 - crates/router/src/connector/utils.rs | 6 -- .../src/core/payments/flows/psync_flow.rs | 12 ++- .../router/src/core/payments/transformers.rs | 2 - crates/router/tests/connectors/bambora.rs | 2 - crates/router/tests/connectors/forte.rs | 1 - crates/router/tests/connectors/nexinets.rs | 1 - crates/router/tests/connectors/paypal.rs | 2 - crates/router/tests/connectors/utils.rs | 1 - crates/router/tests/connectors/zen.rs | 2 - 12 files changed, 61 insertions(+), 47 deletions(-) diff --git a/crates/hyperswitch_domain_models/src/router_request_types.rs b/crates/hyperswitch_domain_models/src/router_request_types.rs index 004db8ffef..f30e6010cf 100644 --- a/crates/hyperswitch_domain_models/src/router_request_types.rs +++ b/crates/hyperswitch_domain_models/src/router_request_types.rs @@ -84,8 +84,6 @@ pub struct SyncIntegrityObject { pub amount: Option, /// Sync currency pub currency: Option, - /// Sync capture amount in case of automatic capture - pub captured_amount: Option, } #[derive(Debug, serde::Deserialize, Clone)] @@ -384,7 +382,6 @@ pub struct PaymentsSyncData { pub amount: MinorUnit, pub integrity_object: Option, - pub captured_amount: Option, } #[derive(Debug, Default, Clone)] diff --git a/crates/hyperswitch_interfaces/src/integrity.rs b/crates/hyperswitch_interfaces/src/integrity.rs index 63c0038518..43d7f4b317 100644 --- a/crates/hyperswitch_interfaces/src/integrity.rs +++ b/crates/hyperswitch_interfaces/src/integrity.rs @@ -140,11 +140,19 @@ impl FlowIntegrity for RefundIntegrityObject { let mut mismatched_fields = Vec::new(); if req_integrity_object.currency != res_integrity_object.currency { - mismatched_fields.push("currency".to_string()); + mismatched_fields.push(format_mismatch( + "currency", + &req_integrity_object.currency.to_string(), + &res_integrity_object.currency.to_string(), + )); } if req_integrity_object.refund_amount != res_integrity_object.refund_amount { - mismatched_fields.push("refund_amount".to_string()); + mismatched_fields.push(format_mismatch( + "refund_amount", + &req_integrity_object.refund_amount.to_string(), + &res_integrity_object.refund_amount.to_string(), + )); } if mismatched_fields.is_empty() { @@ -170,11 +178,19 @@ impl FlowIntegrity for AuthoriseIntegrityObject { let mut mismatched_fields = Vec::new(); if req_integrity_object.amount != res_integrity_object.amount { - mismatched_fields.push("amount".to_string()); + mismatched_fields.push(format_mismatch( + "amount", + &req_integrity_object.amount.to_string(), + &res_integrity_object.amount.to_string(), + )); } if req_integrity_object.currency != res_integrity_object.currency { - mismatched_fields.push("currency".to_string()); + mismatched_fields.push(format_mismatch( + "currency", + &req_integrity_object.currency.to_string(), + &res_integrity_object.currency.to_string(), + )); } if mismatched_fields.is_empty() { @@ -199,30 +215,29 @@ impl FlowIntegrity for SyncIntegrityObject { ) -> Result<(), IntegrityCheckError> { let mut mismatched_fields = Vec::new(); - res_integrity_object - .captured_amount - .zip(req_integrity_object.captured_amount) - .map(|tup| { - if tup.0 != tup.1 { - mismatched_fields.push("captured_amount".to_string()); - } - }); - res_integrity_object .amount .zip(req_integrity_object.amount) - .map(|tup| { - if tup.0 != tup.1 { - mismatched_fields.push("amount".to_string()); + .map(|(res_amount, req_amount)| { + if res_amount != req_amount { + mismatched_fields.push(format_mismatch( + "amount", + &req_amount.to_string(), + &res_amount.to_string(), + )); } }); res_integrity_object .currency .zip(req_integrity_object.currency) - .map(|tup| { - if tup.0 != tup.1 { - mismatched_fields.push("currency".to_string()); + .map(|(res_currency, req_currency)| { + if res_currency != req_currency { + mismatched_fields.push(format_mismatch( + "currency", + &req_currency.to_string(), + &res_currency.to_string(), + )); } }); @@ -251,14 +266,22 @@ impl FlowIntegrity for CaptureIntegrityObject { res_integrity_object .capture_amount .zip(req_integrity_object.capture_amount) - .map(|tup| { - if tup.0 != tup.1 { - mismatched_fields.push("capture_amount".to_string()); + .map(|(res_amount, req_amount)| { + if res_amount != req_amount { + mismatched_fields.push(format_mismatch( + "capture_amount", + &req_amount.to_string(), + &res_amount.to_string(), + )); } }); if req_integrity_object.currency != res_integrity_object.currency { - mismatched_fields.push("currency".to_string()); + mismatched_fields.push(format_mismatch( + "currency", + &req_integrity_object.currency.to_string(), + &res_integrity_object.currency.to_string(), + )); } if mismatched_fields.is_empty() { @@ -322,7 +345,11 @@ impl GetIntegrityObject for PaymentsSyncData { SyncIntegrityObject { amount: Some(self.amount), currency: Some(self.currency), - captured_amount: self.captured_amount, } } } + +#[inline] +fn format_mismatch(field: &str, expected: &str, found: &str) -> String { + format!("{} expected {} but found {}", field, expected, found) +} diff --git a/crates/router/src/connector/stripe.rs b/crates/router/src/connector/stripe.rs index af83353ba9..7e4b644203 100644 --- a/crates/router/src/connector/stripe.rs +++ b/crates/router/src/connector/stripe.rs @@ -842,7 +842,6 @@ impl self.amount_converter, response.amount, response.currency.clone(), - response.amount_received, )?; event_builder.map(|i| i.set_response_body(&response)); diff --git a/crates/router/src/connector/utils.rs b/crates/router/src/connector/utils.rs index a2b2e4e059..d56de472eb 100644 --- a/crates/router/src/connector/utils.rs +++ b/crates/router/src/connector/utils.rs @@ -2914,21 +2914,15 @@ pub fn get_sync_integrity_object( amount_convertor: &dyn AmountConvertor, amount: T, currency: String, - captured_amount: Option, ) -> Result> { let currency_enum = enums::Currency::from_str(currency.to_uppercase().as_str()) .change_context(errors::ConnectorError::ParsingFailed)?; let amount_in_minor_unit = convert_back_amount_to_minor_units(amount_convertor, amount, currency_enum)?; - let capture_amount_in_minor_unit = captured_amount - .map(|amount| convert_back_amount_to_minor_units(amount_convertor, amount, currency_enum)) - .transpose()?; - Ok(SyncIntegrityObject { amount: Some(amount_in_minor_unit), currency: Some(currency_enum), - captured_amount: capture_amount_in_minor_unit, }) } diff --git a/crates/router/src/core/payments/flows/psync_flow.rs b/crates/router/src/core/payments/flows/psync_flow.rs index 336f73e99e..d094fe6a21 100644 --- a/crates/router/src/core/payments/flows/psync_flow.rs +++ b/crates/router/src/core/payments/flows/psync_flow.rs @@ -72,7 +72,7 @@ impl Feature types::SyncRequestType::MultipleCaptureSync(pending_connector_capture_id_list), Ok(services::CaptureSyncMethod::Individual), ) => { - let resp = self + let mut new_router_data = self .execute_connector_processing_step_for_each_capture( state, pending_connector_capture_id_list, @@ -80,7 +80,15 @@ impl Feature connector_integration, ) .await?; - Ok(resp) + // Initiating Integrity checks + let integrity_result = helpers::check_integrity_based_on_flow( + &new_router_data.request, + &new_router_data.response, + ); + + new_router_data.integrity_check = integrity_result; + + Ok(new_router_data) } (types::SyncRequestType::MultipleCaptureSync(_), Err(err)) => Err(err), _ => { diff --git a/crates/router/src/core/payments/transformers.rs b/crates/router/src/core/payments/transformers.rs index 5bc6c2a615..d5f391ba15 100644 --- a/crates/router/src/core/payments/transformers.rs +++ b/crates/router/src/core/payments/transformers.rs @@ -1372,7 +1372,6 @@ impl TryFrom> for types::PaymentsSyncData .as_ref() .map(|surcharge_details| surcharge_details.final_amount) .unwrap_or(payment_data.amount.into()); - let captured_amount = payment_data.payment_intent.amount_captured; Ok(Self { amount, integrity_object: None, @@ -1395,7 +1394,6 @@ impl TryFrom> for types::PaymentsSyncData payment_method_type: payment_data.payment_attempt.payment_method_type, currency: payment_data.currency, payment_experience: payment_data.payment_attempt.payment_experience, - captured_amount, }) } } diff --git a/crates/router/tests/connectors/bambora.rs b/crates/router/tests/connectors/bambora.rs index b3fdc8f0bf..a4cb9b4c5e 100644 --- a/crates/router/tests/connectors/bambora.rs +++ b/crates/router/tests/connectors/bambora.rs @@ -114,7 +114,6 @@ async fn should_sync_authorized_payment() { payment_experience: None, integrity_object: None, amount: MinorUnit::new(100), - captured_amount: None, }), None, ) @@ -234,7 +233,6 @@ async fn should_sync_auto_captured_payment() { payment_experience: None, integrity_object: None, amount: MinorUnit::new(100), - captured_amount: None, }), None, ) diff --git a/crates/router/tests/connectors/forte.rs b/crates/router/tests/connectors/forte.rs index 4b14ff9f21..45a30614bf 100644 --- a/crates/router/tests/connectors/forte.rs +++ b/crates/router/tests/connectors/forte.rs @@ -163,7 +163,6 @@ async fn should_sync_authorized_payment() { payment_experience: None, integrity_object: None, amount: MinorUnit::new(100), - captured_amount: None, }), get_default_payment_info(), ) diff --git a/crates/router/tests/connectors/nexinets.rs b/crates/router/tests/connectors/nexinets.rs index c9ed317ac9..7909aa9c7f 100644 --- a/crates/router/tests/connectors/nexinets.rs +++ b/crates/router/tests/connectors/nexinets.rs @@ -130,7 +130,6 @@ async fn should_sync_authorized_payment() { payment_experience: None, integrity_object: None, amount: MinorUnit::new(100), - captured_amount: None, }), None, ) diff --git a/crates/router/tests/connectors/paypal.rs b/crates/router/tests/connectors/paypal.rs index 698839887d..8de891ef09 100644 --- a/crates/router/tests/connectors/paypal.rs +++ b/crates/router/tests/connectors/paypal.rs @@ -147,7 +147,6 @@ async fn should_sync_authorized_payment() { payment_experience: None, integrity_object: None, amount: MinorUnit::new(100), - captured_amount: None, }), get_default_payment_info(), ) @@ -349,7 +348,6 @@ async fn should_sync_auto_captured_payment() { payment_experience: None, amount: MinorUnit::new(100), integrity_object: None, - captured_amount: None, }), get_default_payment_info(), ) diff --git a/crates/router/tests/connectors/utils.rs b/crates/router/tests/connectors/utils.rs index 652e3a9ff7..b03fee739f 100644 --- a/crates/router/tests/connectors/utils.rs +++ b/crates/router/tests/connectors/utils.rs @@ -1000,7 +1000,6 @@ impl Default for PaymentSyncType { payment_experience: None, amount: MinorUnit::new(100), integrity_object: None, - captured_amount: None, }; Self(data) } diff --git a/crates/router/tests/connectors/zen.rs b/crates/router/tests/connectors/zen.rs index cd4c65d45f..2b9ea8f821 100644 --- a/crates/router/tests/connectors/zen.rs +++ b/crates/router/tests/connectors/zen.rs @@ -108,7 +108,6 @@ async fn should_sync_authorized_payment() { payment_experience: None, amount: MinorUnit::new(100), integrity_object: None, - captured_amount: None, }), None, ) @@ -228,7 +227,6 @@ async fn should_sync_auto_captured_payment() { payment_experience: None, amount: MinorUnit::new(100), integrity_object: None, - captured_amount: None, }), None, )