diff --git a/crates/router/src/connector/bankofamerica.rs b/crates/router/src/connector/bankofamerica.rs index 4f51012763ed..4ca0b6484660 100644 --- a/crates/router/src/connector/bankofamerica.rs +++ b/crates/router/src/connector/bankofamerica.rs @@ -376,6 +376,33 @@ impl ConnectorIntegration CustomResult { self.build_error_response(res) } + + fn get_5xx_error_response( + &self, + res: Response, + ) -> CustomResult { + let response: bankofamerica::BankOfAmerica5XXErrorResponse = res + .response + .parse_struct("BankOfAmerica 5XX ErrorResponse") + .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; + let attempt_status = match response.reason { + Some(reason) => match reason { + transformers::Reason::SystemError => Some(enums::AttemptStatus::Failure), + transformers::Reason::ServerTimeout | transformers::Reason::ServiceTimeout => None, + }, + None => None, + }; + Ok(ErrorResponse { + status_code: res.status_code, + reason: response.status.clone(), + code: response.status.unwrap_or(consts::NO_ERROR_CODE.to_string()), + message: response + .message + .unwrap_or(consts::NO_ERROR_MESSAGE.to_string()), + attempt_status, + connector_transaction_id: None, + }) + } } impl ConnectorIntegration @@ -542,6 +569,27 @@ impl ConnectorIntegration CustomResult { self.build_error_response(res) } + + fn get_5xx_error_response( + &self, + res: Response, + ) -> CustomResult { + let response: bankofamerica::BankOfAmerica5XXErrorResponse = res + .response + .parse_struct("BankOfAmerica 5XX ErrorResponse") + .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; + + Ok(ErrorResponse { + status_code: res.status_code, + reason: response.status.clone(), + code: response.status.unwrap_or(consts::NO_ERROR_CODE.to_string()), + message: response + .message + .unwrap_or(consts::NO_ERROR_MESSAGE.to_string()), + attempt_status: None, + connector_transaction_id: None, + }) + } } impl ConnectorIntegration @@ -641,6 +689,27 @@ impl ConnectorIntegration CustomResult { self.build_error_response(res) } + + fn get_5xx_error_response( + &self, + res: Response, + ) -> CustomResult { + let response: bankofamerica::BankOfAmerica5XXErrorResponse = res + .response + .parse_struct("BankOfAmerica 5XX ErrorResponse") + .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; + + Ok(ErrorResponse { + status_code: res.status_code, + reason: response.status.clone(), + code: response.status.unwrap_or(consts::NO_ERROR_CODE.to_string()), + message: response + .message + .unwrap_or(consts::NO_ERROR_MESSAGE.to_string()), + attempt_status: None, + connector_transaction_id: None, + }) + } } impl ConnectorIntegration @@ -731,6 +800,33 @@ impl ConnectorIntegration CustomResult { self.build_error_response(res) } + + fn get_5xx_error_response( + &self, + res: Response, + ) -> CustomResult { + let response: bankofamerica::BankOfAmerica5XXErrorResponse = res + .response + .parse_struct("BankOfAmerica 5XX ErrorResponse") + .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; + let attempt_status = match response.reason { + Some(reason) => match reason { + transformers::Reason::SystemError => Some(enums::AttemptStatus::Failure), + transformers::Reason::ServerTimeout | transformers::Reason::ServiceTimeout => None, + }, + None => None, + }; + Ok(ErrorResponse { + status_code: res.status_code, + reason: response.status.clone(), + code: response.status.unwrap_or(consts::NO_ERROR_CODE.to_string()), + message: response + .message + .unwrap_or(consts::NO_ERROR_MESSAGE.to_string()), + attempt_status, + connector_transaction_id: None, + }) + } } impl ConnectorIntegration diff --git a/crates/router/src/connector/bankofamerica/transformers.rs b/crates/router/src/connector/bankofamerica/transformers.rs index ce9c39d6ae6b..3e9bd2219fad 100644 --- a/crates/router/src/connector/bankofamerica/transformers.rs +++ b/crates/router/src/connector/bankofamerica/transformers.rs @@ -1016,6 +1016,22 @@ pub struct BankOfAmericaStandardErrorResponse { pub details: Option>, } +#[derive(Debug, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct BankOfAmerica5XXErrorResponse { + pub status: Option, + pub message: Option, + pub reason: Option, +} + +#[derive(Debug, Deserialize)] +#[serde(rename_all = "SCREAMING_SNAKE_CASE")] +pub enum Reason { + SystemError, + ServerTimeout, + ServiceTimeout, +} + #[derive(Debug, Deserialize)] pub struct BankOfAmericaAuthenticationErrorResponse { pub response: AuthenticationErrorInformation, diff --git a/crates/router/src/core/payments/operations/payment_response.rs b/crates/router/src/core/payments/operations/payment_response.rs index e7b821a42b94..ebd0813b5b12 100644 --- a/crates/router/src/core/payments/operations/payment_response.rs +++ b/crates/router/src/core/payments/operations/payment_response.rs @@ -332,20 +332,34 @@ async fn payment_response_update_tracker( } None => { let flow_name = core_utils::get_flow_name::()?; - let status = + let option_gsm = payments_helpers::get_gsm_record( + state, + Some(err.code.clone()), + Some(err.message.clone()), + connector_name, + flow_name.clone(), + ) + .await; + let status = match err.attempt_status { + // Use the status sent by connector in error_response if it's present + Some(status) => status, + None => // mark previous attempt status for technical failures in PSync flow - if flow_name == "PSync" { - match err.status_code { - // marking failure for 2xx because this is genuine payment failure - 200..=299 => storage::enums::AttemptStatus::Failure, - _ => router_data.status, - } - } else { - match err.status_code { - 500..=511 => storage::enums::AttemptStatus::Pending, - _ => storage::enums::AttemptStatus::Failure, + { + if flow_name == "PSync" { + match err.status_code { + // marking failure for 2xx because this is genuine payment failure + 200..=299 => storage::enums::AttemptStatus::Failure, + _ => router_data.status, + } + } else { + match err.status_code { + 500..=511 => storage::enums::AttemptStatus::Pending, + _ => storage::enums::AttemptStatus::Failure, + } } - }; + } + }; ( None, Some(storage::PaymentAttemptUpdate::ErrorUpdate {