fix(connector): [Bluesnap] fix psync status to failure when it is '403' (#2772)

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
This commit is contained in:
chikke srujan
2023-11-03 18:57:20 +05:30
committed by GitHub
parent 585937204d
commit 9314d14463
4 changed files with 59 additions and 28 deletions

View File

@ -37,6 +37,8 @@ use crate::{
utils::{self, BytesExt}, utils::{self, BytesExt},
}; };
pub const BLUESNAP_TRANSACTION_NOT_FOUND: &str = "is not authorized to view merchant-transaction:";
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Bluesnap; pub struct Bluesnap;
@ -132,12 +134,24 @@ impl ConnectorCommon for Bluesnap {
message: error_res.error_name.clone().unwrap_or(error_res.error_code), message: error_res.error_name.clone().unwrap_or(error_res.error_code),
reason: Some(error_res.error_description), reason: Some(error_res.error_description),
}, },
bluesnap::BluesnapErrors::General(error_response) => ErrorResponse { bluesnap::BluesnapErrors::General(error_response) => {
status_code: res.status_code, let error_res = if res.status_code == 403
code: consts::NO_ERROR_CODE.to_string(), && error_response.contains(BLUESNAP_TRANSACTION_NOT_FOUND)
message: error_response.clone(), {
reason: Some(error_response), format!(
}, "{} in bluesnap dashboard",
consts::REQUEST_TIMEOUT_PAYMENT_NOT_FOUND
)
} else {
error_response.clone()
};
ErrorResponse {
status_code: res.status_code,
code: consts::NO_ERROR_CODE.to_string(),
message: error_response,
reason: Some(error_res),
}
}
}; };
Ok(response_error_message) Ok(response_error_message)
} }
@ -322,21 +336,26 @@ impl ConnectorIntegration<api::PSync, types::PaymentsSyncData, types::PaymentsRe
req: &types::PaymentsSyncRouterData, req: &types::PaymentsSyncRouterData,
connectors: &settings::Connectors, connectors: &settings::Connectors,
) -> CustomResult<String, errors::ConnectorError> { ) -> CustomResult<String, errors::ConnectorError> {
let meta_data: CustomResult<bluesnap::BluesnapConnectorMetaData, errors::ConnectorError> = let connector_transaction_id = req.request.connector_transaction_id.clone();
connector_utils::to_connector_meta_from_secret(req.connector_meta_data.clone()); match connector_transaction_id {
// if connector_transaction_id is present, we always sync with connector_transaction_id
match meta_data { types::ResponseId::ConnectorTransactionId(trans_id) => {
// if merchant_id is present, psync can be made using merchant_transaction_id get_psync_url_with_connector_transaction_id(
Ok(data) => get_url_with_merchant_transaction_id( trans_id,
self.base_url(connectors).to_string(), self.base_url(connectors).to_string(),
data.merchant_id, )
req.attempt_id.to_owned(), }
), _ => {
// otherwise psync is made using connector_transaction_id // if connector_transaction_id is not present, we sync with merchant_transaction_id
Err(_) => get_psync_url_with_connector_transaction_id( let meta_data: bluesnap::BluesnapConnectorMetaData =
&req.request.connector_transaction_id, connector_utils::to_connector_meta_from_secret(req.connector_meta_data.clone())
self.base_url(connectors).to_string(), .change_context(errors::ConnectorError::ResponseHandlingFailed)?;
), get_url_with_merchant_transaction_id(
self.base_url(connectors).to_string(),
meta_data.merchant_id,
req.attempt_id.to_owned(),
)
}
} }
} }
@ -1269,12 +1288,9 @@ fn get_url_with_merchant_transaction_id(
} }
fn get_psync_url_with_connector_transaction_id( fn get_psync_url_with_connector_transaction_id(
connector_transaction_id: &types::ResponseId, connector_transaction_id: String,
base_url: String, base_url: String,
) -> CustomResult<String, errors::ConnectorError> { ) -> CustomResult<String, errors::ConnectorError> {
let connector_transaction_id = connector_transaction_id
.get_connector_transaction_id()
.change_context(errors::ConnectorError::MissingConnectorTransactionID)?;
Ok(format!( Ok(format!(
"{}{}{}", "{}{}{}",
base_url, "services/2/transactions/", connector_transaction_id base_url, "services/2/transactions/", connector_transaction_id

View File

@ -13,6 +13,7 @@ pub(crate) const ALPHABETS: [char; 62] = [
pub const REQUEST_TIME_OUT: u64 = 30; pub const REQUEST_TIME_OUT: u64 = 30;
pub const REQUEST_TIMEOUT_ERROR_CODE: &str = "TIMEOUT"; pub const REQUEST_TIMEOUT_ERROR_CODE: &str = "TIMEOUT";
pub const REQUEST_TIMEOUT_ERROR_MESSAGE: &str = "Connector did not respond in specified time"; pub const REQUEST_TIMEOUT_ERROR_MESSAGE: &str = "Connector did not respond in specified time";
pub const REQUEST_TIMEOUT_PAYMENT_NOT_FOUND: &str = "Timed out ,payment not found";
pub const REQUEST_TIMEOUT_ERROR_MESSAGE_FROM_PSYNC: &str = pub const REQUEST_TIMEOUT_ERROR_MESSAGE_FROM_PSYNC: &str =
"This Payment has been moved to failed as there is no response from the connector"; "This Payment has been moved to failed as there is no response from the connector";

View File

@ -326,7 +326,7 @@ async fn payment_response_update_tracker<F: Clone, T: types::Capturable>(
match err.status_code { match err.status_code {
// marking failure for 2xx because this is genuine payment failure // marking failure for 2xx because this is genuine payment failure
200..=299 => storage::enums::AttemptStatus::Failure, 200..=299 => storage::enums::AttemptStatus::Failure,
_ => payment_data.payment_attempt.status, _ => router_data.status,
} }
} else { } else {
match err.status_code { match err.status_code {

View File

@ -10,7 +10,7 @@ use std::{
}; };
use actix_web::{body, web, FromRequest, HttpRequest, HttpResponse, Responder, ResponseError}; use actix_web::{body, web, FromRequest, HttpRequest, HttpResponse, Responder, ResponseError};
use api_models::enums::CaptureMethod; use api_models::enums::{AttemptStatus, CaptureMethod};
pub use client::{proxy_bypass_urls, ApiClient, MockApiClient, ProxyClient}; pub use client::{proxy_bypass_urls, ApiClient, MockApiClient, ProxyClient};
pub use common_utils::request::{ContentType, Method, Request, RequestBuilder}; pub use common_utils::request::{ContentType, Method, Request, RequestBuilder};
use common_utils::{ use common_utils::{
@ -403,7 +403,21 @@ where
500..=511 => { 500..=511 => {
connector_integration.get_5xx_error_response(body)? connector_integration.get_5xx_error_response(body)?
} }
_ => connector_integration.get_error_response(body)?, _ => {
let error_res =
connector_integration.get_error_response(body)?;
if router_data.connector == "bluesnap"
&& error_res.status_code == 403
&& error_res.reason
== Some(format!(
"{} in bluesnap dashboard",
consts::REQUEST_TIMEOUT_PAYMENT_NOT_FOUND
))
{
router_data.status = AttemptStatus::Failure;
};
error_res
}
}; };
router_data.response = Err(error); router_data.response = Err(error);