From fb9361dca8617e70dc5729c5dab8a1e81e90f0c8 Mon Sep 17 00:00:00 2001 From: DEEPANSHU BANSAL Date: Mon, 18 Dec 2023 14:14:47 +0530 Subject: [PATCH] fix(connector): [BOA/CYBERSOURCE] Handle authentication error --- crates/router/src/connector/bankofamerica.rs | 75 +++++++++++-------- .../connector/bankofamerica/transformers.rs | 19 ++++- crates/router/src/connector/cybersource.rs | 74 +++++++++++------- .../src/connector/cybersource/transformers.rs | 63 ++++++++++------ 4 files changed, 147 insertions(+), 84 deletions(-) diff --git a/crates/router/src/connector/bankofamerica.rs b/crates/router/src/connector/bankofamerica.rs index cac3bacc211d..891ae7eb228c 100644 --- a/crates/router/src/connector/bankofamerica.rs +++ b/crates/router/src/connector/bankofamerica.rs @@ -203,37 +203,50 @@ impl ConnectorCommon for Bankofamerica { } else { consts::NO_ERROR_MESSAGE }; - - let (code, message) = match response.error_information { - Some(ref error_info) => (error_info.reason.clone(), error_info.message.clone()), - None => ( - response - .reason - .map_or(consts::NO_ERROR_CODE.to_string(), |reason| { - reason.to_string() - }), - response - .message - .map_or(error_message.to_string(), |message| message), - ), - }; - let connector_reason = match response.details { - Some(details) => details - .iter() - .map(|det| format!("{} : {}", det.field, det.reason)) - .collect::>() - .join(", "), - None => message.clone(), - }; - - Ok(ErrorResponse { - status_code: res.status_code, - code, - message, - reason: Some(connector_reason), - attempt_status: None, - connector_transaction_id: None, - }) + match response { + transformers::BankOfAmericaErrorResponse::StandardError(response) => { + let (code, message) = match response.error_information { + Some(ref error_info) => (error_info.reason.clone(), error_info.message.clone()), + None => ( + response + .reason + .map_or(consts::NO_ERROR_CODE.to_string(), |reason| { + reason.to_string() + }), + response + .message + .map_or(error_message.to_string(), |message| message), + ), + }; + let connector_reason = match response.details { + Some(details) => details + .iter() + .map(|det| format!("{} : {}", det.field, det.reason)) + .collect::>() + .join(", "), + None => message.clone(), + }; + + Ok(ErrorResponse { + status_code: res.status_code, + code, + message, + reason: Some(connector_reason), + attempt_status: None, + connector_transaction_id: None, + }) + } + transformers::BankOfAmericaErrorResponse::AuthenticationError(response) => { + Ok(ErrorResponse { + status_code: res.status_code, + code: consts::NO_ERROR_CODE.to_string(), + message: response.response.rmsg, + reason: None, + attempt_status: None, + connector_transaction_id: None, + }) + } + } } } diff --git a/crates/router/src/connector/bankofamerica/transformers.rs b/crates/router/src/connector/bankofamerica/transformers.rs index 52df839c46b8..e7c0c7a579b4 100644 --- a/crates/router/src/connector/bankofamerica/transformers.rs +++ b/crates/router/src/connector/bankofamerica/transformers.rs @@ -1016,7 +1016,7 @@ impl TryFrom, pub status: Option, pub message: Option, @@ -1024,6 +1024,18 @@ pub struct BankOfAmericaErrorResponse { pub details: Option>, } +#[derive(Debug, Deserialize)] +pub struct BankOfAmericaAuthenticationErrorResponse { + pub response: AuthenticationErrorInformation, +} + +#[derive(Debug, Deserialize)] +#[serde(untagged)] +pub enum BankOfAmericaErrorResponse { + StandardError(BankOfAmericaStandardErrorResponse), + AuthenticationError(BankOfAmericaAuthenticationErrorResponse), +} + #[derive(Debug, Deserialize, Clone)] #[serde(rename_all = "camelCase")] pub struct Details { @@ -1036,3 +1048,8 @@ pub struct ErrorInformation { pub message: String, pub reason: String, } + +#[derive(Debug, Default, Deserialize)] +pub struct AuthenticationErrorInformation { + pub rmsg: String, +} diff --git a/crates/router/src/connector/cybersource.rs b/crates/router/src/connector/cybersource.rs index 06be499fae4f..dc9c83a567f1 100644 --- a/crates/router/src/connector/cybersource.rs +++ b/crates/router/src/connector/cybersource.rs @@ -109,44 +109,60 @@ impl ConnectorCommon for Cybersource { &self, res: types::Response, ) -> CustomResult { - let response: cybersource::ErrorResponse = res + let response: cybersource::CybersourceErrorResponse = res .response .parse_struct("Cybersource ErrorResponse") .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; - let details = response.details.unwrap_or_default(); - let connector_reason = details - .iter() - .map(|det| format!("{} : {}", det.field, det.reason)) - .collect::>() - .join(", "); let error_message = if res.status_code == 401 { consts::CONNECTOR_UNAUTHORIZED_ERROR } else { consts::NO_ERROR_MESSAGE }; - - let (code, message) = match response.error_information { - Some(ref error_info) => (error_info.reason.clone(), error_info.message.clone()), - None => ( - response - .reason - .map_or(consts::NO_ERROR_CODE.to_string(), |reason| { - reason.to_string() - }), - response - .message - .map_or(error_message.to_string(), |message| message), - ), - }; - Ok(types::ErrorResponse { - status_code: res.status_code, - code, - message, - reason: Some(connector_reason), - attempt_status: None, - connector_transaction_id: None, - }) + match response { + transformers::CybersourceErrorResponse::StandardError(response) => { + let (code, message) = match response.error_information { + Some(ref error_info) => (error_info.reason.clone(), error_info.message.clone()), + None => ( + response + .reason + .map_or(consts::NO_ERROR_CODE.to_string(), |reason| { + reason.to_string() + }), + response + .message + .map_or(error_message.to_string(), |message| message), + ), + }; + let connector_reason = match response.details { + Some(details) => details + .iter() + .map(|det| format!("{} : {}", det.field, det.reason)) + .collect::>() + .join(", "), + None => message.clone(), + }; + + Ok(types::ErrorResponse { + status_code: res.status_code, + code, + message, + reason: Some(connector_reason), + attempt_status: None, + connector_transaction_id: None, + }) + } + transformers::CybersourceErrorResponse::AuthenticationError(response) => { + Ok(types::ErrorResponse { + status_code: res.status_code, + code: consts::NO_ERROR_CODE.to_string(), + message: response.response.rmsg, + reason: None, + attempt_status: None, + connector_transaction_id: None, + }) + } + } } } diff --git a/crates/router/src/connector/cybersource/transformers.rs b/crates/router/src/connector/cybersource/transformers.rs index 6a1c237b55fd..f99c90989d0c 100644 --- a/crates/router/src/connector/cybersource/transformers.rs +++ b/crates/router/src/connector/cybersource/transformers.rs @@ -1286,29 +1286,6 @@ impl } } -#[derive(Debug, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct ErrorResponse { - pub error_information: Option, - pub status: Option, - pub message: Option, - pub reason: Option, - pub details: Option>, -} - -#[derive(Debug, Deserialize, Clone)] -#[serde(rename_all = "camelCase")] -pub struct Details { - pub field: String, - pub reason: String, -} - -#[derive(Debug, Deserialize)] -pub struct ErrorInformation { - pub message: String, - pub reason: String, -} - #[derive(Debug, Serialize)] #[serde(rename_all = "camelCase")] pub struct CybersourceRefundRequest { @@ -1408,3 +1385,43 @@ impl TryFrom, + pub status: Option, + pub message: Option, + pub reason: Option, + pub details: Option>, +} + +#[derive(Debug, Deserialize)] +pub struct CybersourceAuthenticationErrorResponse { + pub response: AuthenticationErrorInformation, +} + +#[derive(Debug, Deserialize)] +#[serde(untagged)] +pub enum CybersourceErrorResponse { + StandardError(CybersourceStandardErrorResponse), + AuthenticationError(CybersourceAuthenticationErrorResponse), +} + +#[derive(Debug, Deserialize, Clone)] +#[serde(rename_all = "camelCase")] +pub struct Details { + pub field: String, + pub reason: String, +} + +#[derive(Debug, Default, Deserialize)] +pub struct ErrorInformation { + pub message: String, + pub reason: String, +} + +#[derive(Debug, Default, Deserialize)] +pub struct AuthenticationErrorInformation { + pub rmsg: String, +}