feat(connector): [BOA] Handle BOA 5XX errors (#3178)

This commit is contained in:
DEEPANSHU BANSAL
2023-12-20 18:17:28 +05:30
committed by GitHub
parent e7949c23b9
commit 1d80949bef
3 changed files with 104 additions and 12 deletions

View File

@ -385,6 +385,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::BankOfAmericaServerErrorResponse = res
.response
.parse_struct("BankOfAmericaServerErrorResponse")
.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>
@ -546,6 +573,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::BankOfAmericaServerErrorResponse = res
.response
.parse_struct("BankOfAmericaServerErrorResponse")
.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>
@ -640,6 +688,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::BankOfAmericaServerErrorResponse = res
.response
.parse_struct("BankOfAmericaServerErrorResponse")
.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>

View File

@ -626,6 +626,7 @@ impl<F>
attempt_status: None,
connector_transaction_id: None,
}),
status: enums::AttemptStatus::Failure,
..item.data
}),
}
@ -1024,6 +1025,22 @@ pub struct BankOfAmericaStandardErrorResponse {
pub details: Option<Vec<Details>>,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct BankOfAmericaServerErrorResponse {
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,

View File

@ -471,20 +471,26 @@ async fn payment_response_update_tracker<F: Clone, T: types::Capturable>(
flow_name.clone(),
)
.await;
let status =
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,
{
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,
}
}
} else {
match err.status_code {
500..=511 => storage::enums::AttemptStatus::Pending,
_ => storage::enums::AttemptStatus::Failure,
}
};
}
};
(
None,
Some(storage::PaymentAttemptUpdate::ErrorUpdate {