Skip to content

Commit

Permalink
feat(connector): [BOA] Fix 5XX Error response
Browse files Browse the repository at this point in the history
  • Loading branch information
deepanshu-iiitu committed Dec 20, 2023
1 parent 6030854 commit d2b3b2d
Show file tree
Hide file tree
Showing 3 changed files with 138 additions and 12 deletions.
96 changes: 96 additions & 0 deletions crates/router/src/connector/bankofamerica.rs
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,33 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
) -> CustomResult<ErrorResponse, errors::ConnectorError> {
self.build_error_response(res)
}

fn get_5xx_error_response(
&self,
res: Response,
) -> CustomResult<ErrorResponse, errors::ConnectorError> {
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<api::PSync, types::PaymentsSyncData, types::PaymentsResponseData>
Expand Down Expand Up @@ -542,6 +569,27 @@ impl ConnectorIntegration<api::Capture, types::PaymentsCaptureData, types::Payme
) -> CustomResult<ErrorResponse, errors::ConnectorError> {
self.build_error_response(res)
}

fn get_5xx_error_response(
&self,
res: Response,
) -> CustomResult<ErrorResponse, errors::ConnectorError> {
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<api::Void, types::PaymentsCancelData, types::PaymentsResponseData>
Expand Down Expand Up @@ -641,6 +689,27 @@ impl ConnectorIntegration<api::Void, types::PaymentsCancelData, types::PaymentsR
) -> CustomResult<ErrorResponse, errors::ConnectorError> {
self.build_error_response(res)
}

fn get_5xx_error_response(
&self,
res: Response,
) -> CustomResult<ErrorResponse, errors::ConnectorError> {
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<api::Execute, types::RefundsData, types::RefundsResponseData>
Expand Down Expand Up @@ -731,6 +800,33 @@ impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsRespon
) -> CustomResult<ErrorResponse, errors::ConnectorError> {
self.build_error_response(res)
}

fn get_5xx_error_response(
&self,
res: Response,
) -> CustomResult<ErrorResponse, errors::ConnectorError> {
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<api::RSync, types::RefundsData, types::RefundsResponseData>
Expand Down
16 changes: 16 additions & 0 deletions crates/router/src/connector/bankofamerica/transformers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1016,6 +1016,22 @@ pub struct BankOfAmericaStandardErrorResponse {
pub details: Option<Vec<Details>>,
}

#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct BankOfAmerica5XXErrorResponse {
pub status: Option<String>,
pub message: Option<String>,
pub reason: Option<Reason>,
}

#[derive(Debug, Deserialize)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
pub enum Reason {
SystemError,
ServerTimeout,
ServiceTimeout,
}

#[derive(Debug, Deserialize)]
pub struct BankOfAmericaAuthenticationErrorResponse {
pub response: AuthenticationErrorInformation,
Expand Down
38 changes: 26 additions & 12 deletions crates/router/src/core/payments/operations/payment_response.rs
Original file line number Diff line number Diff line change
Expand Up @@ -332,20 +332,34 @@ async fn payment_response_update_tracker<F: Clone, T: types::Capturable>(
}
None => {
let flow_name = core_utils::get_flow_name::<F>()?;
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 {
Expand Down

0 comments on commit d2b3b2d

Please sign in to comment.