diff --git a/connector-template/mod.rs b/connector-template/mod.rs index 4bf5813468..ce7dc0777b 100644 --- a/connector-template/mod.rs +++ b/connector-template/mod.rs @@ -123,7 +123,7 @@ impl fn get_error_response( &self, - _res: Bytes, + _res: types::Response, ) -> CustomResult { self.build_error_response(res) } @@ -220,7 +220,7 @@ impl fn get_error_response( &self, - _res: Bytes, + _res: types::Response, ) -> CustomResult { self.build_error_response(res) } @@ -299,7 +299,7 @@ impl .change_context(errors::ConnectorError::ResponseHandlingFailed) } - fn get_error_response(&self, res: Bytes) -> CustomResult { + fn get_error_response(&self, res: types::Response) -> CustomResult { self.build_error_response(res) } } @@ -357,7 +357,7 @@ impl .change_context(errors::ConnectorError::ResponseHandlingFailed) } - fn get_error_response(&self, res: Bytes) -> CustomResult { + fn get_error_response(&self, res: types::Response) -> CustomResult { self.build_error_response(res) } } @@ -407,7 +407,7 @@ impl .change_context(errors::ConnectorError::ResponseHandlingFailed) } - fn get_error_response(&self, res: Bytes) -> CustomResult { + fn get_error_response(&self, res: types::Response) -> CustomResult { self.build_error_response(res) } } diff --git a/crates/router/src/compatibility/stripe/errors.rs b/crates/router/src/compatibility/stripe/errors.rs index 30ac8b608f..47052115a4 100644 --- a/crates/router/src/compatibility/stripe/errors.rs +++ b/crates/router/src/compatibility/stripe/errors.rs @@ -359,6 +359,7 @@ impl From for StripeErrorCode { errors::ApiErrorResponse::RefundFailed { data } => Self::RefundFailed, // Nothing at stripe to map errors::ApiErrorResponse::InternalServerError => Self::InternalServerError, // not a stripe code + errors::ApiErrorResponse::ExternalConnectorError { .. } => Self::InternalServerError, errors::ApiErrorResponse::IncorrectConnectorNameGiven => Self::InternalServerError, errors::ApiErrorResponse::MandateActive => Self::MandateActive, //not a stripe code errors::ApiErrorResponse::CustomerRedacted => Self::CustomerRedacted, //not a stripe code diff --git a/crates/router/src/connector/aci.rs b/crates/router/src/connector/aci.rs index eae5292ace..6a3cabafb6 100644 --- a/crates/router/src/connector/aci.rs +++ b/crates/router/src/connector/aci.rs @@ -2,7 +2,6 @@ mod result_codes; mod transformers; use std::fmt::Debug; -use bytes::Bytes; use error_stack::{IntoReport, ResultExt}; use transformers as aci; @@ -167,11 +166,12 @@ impl fn get_error_response( &self, - res: Bytes, + res: types::Response, ) -> CustomResult { - let response: aci::AciPaymentsResponse = res - .parse_struct("AciPaymentsResponse") - .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; + let response: aci::AciPaymentsResponse = + res.response + .parse_struct("AciPaymentsResponse") + .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; Ok(types::ErrorResponse { code: response.result.code, message: response.result.description, @@ -183,6 +183,7 @@ impl ) }) }), + status_code: res.status_code, }) } } @@ -277,12 +278,14 @@ impl fn get_error_response( &self, - res: Bytes, + res: types::Response, ) -> CustomResult { - let response: aci::AciPaymentsResponse = res - .parse_struct("AciPaymentsResponse") - .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; + let response: aci::AciPaymentsResponse = + res.response + .parse_struct("AciPaymentsResponse") + .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; Ok(types::ErrorResponse { + status_code: res.status_code, code: response.result.code, message: response.result.description, reason: response.result.parameter_errors.and_then(|errors| { @@ -376,12 +379,14 @@ impl fn get_error_response( &self, - res: Bytes, + res: types::Response, ) -> CustomResult { - let response: aci::AciPaymentsResponse = res - .parse_struct("AciPaymentsResponse") - .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; + let response: aci::AciPaymentsResponse = + res.response + .parse_struct("AciPaymentsResponse") + .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; Ok(types::ErrorResponse { + status_code: res.status_code, code: response.result.code, message: response.result.description, reason: response.result.parameter_errors.and_then(|errors| { @@ -483,12 +488,14 @@ impl services::ConnectorIntegration CustomResult { let response: aci::AciRefundResponse = res + .response .parse_struct("AciRefundResponse") .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; Ok(types::ErrorResponse { + status_code: res.status_code, code: response.result.code, message: response.result.description, reason: response.result.parameter_errors.and_then(|errors| { diff --git a/crates/router/src/connector/adyen.rs b/crates/router/src/connector/adyen.rs index 960260f5de..eb98e0c6dc 100644 --- a/crates/router/src/connector/adyen.rs +++ b/crates/router/src/connector/adyen.rs @@ -3,7 +3,6 @@ mod transformers; use std::fmt::Debug; use base64::Engine; -use bytes::Bytes; use error_stack::{IntoReport, ResultExt}; use router_env::{instrument, tracing}; @@ -156,12 +155,14 @@ impl } fn get_error_response( &self, - res: Bytes, + res: types::Response, ) -> CustomResult { let response: adyen::ErrorResponse = res + .response .parse_struct("adyen::ErrorResponse") .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; Ok(types::ErrorResponse { + status_code: res.status_code, code: response.error_code, message: response.message, reason: None, @@ -288,12 +289,14 @@ impl fn get_error_response( &self, - res: Bytes, + res: types::Response, ) -> CustomResult { let response: adyen::ErrorResponse = res + .response .parse_struct("ErrorResponse") .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; Ok(types::ErrorResponse { + status_code: res.status_code, code: response.error_code, message: response.message, reason: None, @@ -397,12 +400,14 @@ impl fn get_error_response( &self, - res: Bytes, + res: types::Response, ) -> CustomResult { let response: adyen::ErrorResponse = res + .response .parse_struct("ErrorResponse") .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; Ok(types::ErrorResponse { + status_code: res.status_code, code: response.error_code, message: response.message, reason: None, @@ -490,13 +495,15 @@ impl fn get_error_response( &self, - res: Bytes, + res: types::Response, ) -> CustomResult { let response: adyen::ErrorResponse = res + .response .parse_struct("ErrorResponse") .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; logger::info!(response=?res); Ok(types::ErrorResponse { + status_code: res.status_code, code: response.error_code, message: response.message, reason: None, @@ -588,13 +595,15 @@ impl services::ConnectorIntegration CustomResult { let response: adyen::ErrorResponse = res + .response .parse_struct("ErrorResponse") .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; logger::info!(response=?res); Ok(types::ErrorResponse { + status_code: res.status_code, code: response.error_code, message: response.message, reason: None, diff --git a/crates/router/src/connector/adyen/transformers.rs b/crates/router/src/connector/adyen/transformers.rs index b0d3e5acd3..8fdba3f30b 100644 --- a/crates/router/src/connector/adyen/transformers.rs +++ b/crates/router/src/connector/adyen/transformers.rs @@ -466,6 +466,7 @@ impl TryFrom> pub fn get_adyen_response( response: AdyenResponse, is_capture_manual: bool, + status_code: u16, ) -> errors::CustomResult< ( storage_enums::AttemptStatus, @@ -494,6 +495,7 @@ pub fn get_adyen_response( .refusal_reason .unwrap_or_else(|| consts::NO_ERROR_MESSAGE.to_string()), reason: None, + status_code, }) } else { None @@ -511,6 +513,7 @@ pub fn get_adyen_response( pub fn get_redirection_response( response: AdyenRedirectionResponse, + status_code: u16, ) -> errors::CustomResult< ( storage_enums::AttemptStatus, @@ -530,6 +533,7 @@ pub fn get_redirection_response( .refusal_reason .unwrap_or_else(|| consts::NO_ERROR_MESSAGE.to_string()), reason: None, + status_code, }) } else { None @@ -585,10 +589,10 @@ impl let is_manual_capture = items.1; let (status, error, payment_response_data) = match item.response { AdyenPaymentResponse::AdyenResponse(response) => { - get_adyen_response(response, is_manual_capture)? + get_adyen_response(response, is_manual_capture, item.http_code)? } AdyenPaymentResponse::AdyenRedirectResponse(response) => { - get_redirection_response(response)? + get_redirection_response(response, item.http_code)? } }; diff --git a/crates/router/src/connector/applepay.rs b/crates/router/src/connector/applepay.rs index 7d83716b91..2c461bf9ef 100644 --- a/crates/router/src/connector/applepay.rs +++ b/crates/router/src/connector/applepay.rs @@ -2,7 +2,6 @@ mod transformers; use std::fmt::Debug; -use bytes::Bytes; use common_utils::ext_traits::ValueExt; use error_stack::{IntoReport, ResultExt}; @@ -160,12 +159,14 @@ impl fn get_error_response( &self, - res: Bytes, + res: types::Response, ) -> CustomResult { let response: applepay::ErrorResponse = res + .response .parse_struct("ErrorResponse") .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; Ok(types::ErrorResponse { + status_code: res.status_code, code: response.status_code, message: response.status_message, reason: None, diff --git a/crates/router/src/connector/authorizedotnet.rs b/crates/router/src/connector/authorizedotnet.rs index 242f018d2e..dd592bb508 100644 --- a/crates/router/src/connector/authorizedotnet.rs +++ b/crates/router/src/connector/authorizedotnet.rs @@ -3,7 +3,6 @@ mod transformers; use std::fmt::Debug; -use bytes::Bytes; use error_stack::{IntoReport, ResultExt}; use transformers as authorizedotnet; @@ -160,7 +159,7 @@ impl fn get_error_response( &self, - res: Bytes, + res: types::Response, ) -> CustomResult { get_error_response(res) } @@ -263,7 +262,7 @@ impl fn get_error_response( &self, - res: Bytes, + res: types::Response, ) -> CustomResult { logger::debug!(authorizedotnetpayments_create_error_response=?res); get_error_response(res) @@ -356,7 +355,7 @@ impl fn get_error_response( &self, - res: Bytes, + res: types::Response, ) -> CustomResult { get_error_response(res) } @@ -452,7 +451,7 @@ impl services::ConnectorIntegration CustomResult { get_error_response(res) } @@ -541,7 +540,7 @@ impl services::ConnectorIntegration CustomResult { get_error_response(res) } @@ -574,8 +573,13 @@ impl api::IncomingWebhook for Authorizedotnet { impl services::ConnectorRedirectResponse for Authorizedotnet {} #[inline] -fn get_error_response(bytes: Bytes) -> CustomResult { - let response: authorizedotnet::AuthorizedotnetPaymentsResponse = bytes +fn get_error_response( + types::Response { + response, + status_code, + }: types::Response, +) -> CustomResult { + let response: authorizedotnet::AuthorizedotnetPaymentsResponse = response .parse_struct("AuthorizedotnetPaymentsResponse") .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; @@ -589,11 +593,13 @@ fn get_error_response(bytes: Bytes) -> CustomResult code: error.error_code, message: error.error_text, reason: None, + status_code: item.http_code, }) }); @@ -431,6 +432,7 @@ impl TryFrom CustomResult { let response: braintree::ErrorResponse = res + .response .parse_struct("Error Response") .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; Ok(types::ErrorResponse { + status_code: res.status_code, code: consts::NO_ERROR_CODE.to_string(), message: response.api_error_response.message, reason: None, @@ -251,13 +252,15 @@ impl fn get_error_response( &self, - res: Bytes, + res: types::Response, ) -> CustomResult { let response: braintree::ErrorResponse = res + .response .parse_struct("Braintree Error Response") .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; Ok(types::ErrorResponse { + status_code: res.status_code, code: consts::NO_ERROR_CODE.to_string(), message: response.api_error_response.message, reason: None, @@ -381,14 +384,16 @@ impl fn get_error_response( &self, - res: Bytes, + res: types::Response, ) -> CustomResult { logger::debug!(braintreepayments_create_response=?res); let response: braintree::ErrorResponse = res + .response .parse_struct("Braintree ErrorResponse") .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; Ok(types::ErrorResponse { + status_code: res.status_code, code: consts::NO_ERROR_CODE.to_string(), message: response.api_error_response.message, reason: None, @@ -458,13 +463,15 @@ impl fn get_error_response( &self, - res: Bytes, + res: types::Response, ) -> CustomResult { let response: braintree::ErrorResponse = res + .response .parse_struct("Braintree ErrorResponse") .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; Ok(types::ErrorResponse { + status_code: res.status_code, code: consts::NO_ERROR_CODE.to_string(), message: response.api_error_response.message, reason: None, @@ -590,7 +597,7 @@ impl services::ConnectorIntegration CustomResult { Err(errors::ConnectorError::NotImplemented("braintree".to_string()).into()) } @@ -622,7 +629,7 @@ impl services::ConnectorIntegration CustomResult { Err(errors::ConnectorError::NotImplemented("braintree".to_string()).into()) } diff --git a/crates/router/src/connector/checkout.rs b/crates/router/src/connector/checkout.rs index 205c367402..82253d6ff0 100644 --- a/crates/router/src/connector/checkout.rs +++ b/crates/router/src/connector/checkout.rs @@ -4,7 +4,6 @@ mod transformers; use std::fmt::Debug; -use bytes::Bytes; use error_stack::{IntoReport, ResultExt}; use self::transformers as checkout; @@ -165,12 +164,14 @@ impl fn get_error_response( &self, - res: Bytes, + res: types::Response, ) -> CustomResult { let response: checkout::ErrorResponse = res + .response .parse_struct("ErrorResponse") .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; Ok(types::ErrorResponse { + status_code: res.status_code, code: response .error_codes .unwrap_or_else(|| vec![consts::NO_ERROR_CODE.to_string()]) @@ -262,12 +263,14 @@ impl fn get_error_response( &self, - res: Bytes, + res: types::Response, ) -> CustomResult { let response: checkout::ErrorResponse = res + .response .parse_struct("ErrorResponse") .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; Ok(types::ErrorResponse { + status_code: res.status_code, code: response .error_codes .unwrap_or_else(|| vec![consts::NO_ERROR_CODE.to_string()]) @@ -364,13 +367,15 @@ impl fn get_error_response( &self, - res: Bytes, + res: types::Response, ) -> CustomResult { logger::debug!(checkout_error_response=?res); let response: checkout::ErrorResponse = res + .response .parse_struct("ErrorResponse") .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; Ok(types::ErrorResponse { + status_code: res.status_code, code: response .error_codes .unwrap_or_else(|| vec![consts::NO_ERROR_CODE.to_string()]) @@ -463,12 +468,14 @@ impl fn get_error_response( &self, - res: Bytes, + res: types::Response, ) -> CustomResult { let response: checkout::ErrorResponse = res + .response .parse_struct("ErrorResponse") .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; Ok(types::ErrorResponse { + status_code: res.status_code, code: response .error_codes .unwrap_or_else(|| vec![consts::NO_ERROR_CODE.to_string()]) @@ -572,12 +579,14 @@ impl services::ConnectorIntegration CustomResult { let response: checkout::ErrorResponse = res + .response .parse_struct("ErrorResponse") .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; Ok(types::ErrorResponse { + status_code: res.status_code, code: response .error_codes .unwrap_or_else(|| vec![consts::NO_ERROR_CODE.to_string()]) @@ -671,12 +680,14 @@ impl services::ConnectorIntegration CustomResult { let response: checkout::ErrorResponse = res + .response .parse_struct("ErrorResponse") .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; Ok(types::ErrorResponse { + status_code: res.status_code, code: response .error_codes .unwrap_or_else(|| vec![consts::NO_ERROR_CODE.to_string()]) diff --git a/crates/router/src/connector/cybersource.rs b/crates/router/src/connector/cybersource.rs index 80a27e09a9..1db71ae90c 100644 --- a/crates/router/src/connector/cybersource.rs +++ b/crates/router/src/connector/cybersource.rs @@ -3,7 +3,6 @@ mod transformers; use std::fmt::Debug; use base64::Engine; -use bytes::Bytes; use error_stack::{IntoReport, ResultExt}; use ring::{digest, hmac}; use time::OffsetDateTime; @@ -87,12 +86,14 @@ impl ConnectorCommon for Cybersource { fn build_error_response( &self, - res: Bytes, + res: types::Response, ) -> CustomResult { let response: cybersource::ErrorResponse = res + .response .parse_struct("Cybersource ErrorResponse") .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; Ok(types::ErrorResponse { + status_code: res.status_code, code: consts::NO_ERROR_CODE.to_string(), message: response.details.to_string(), reason: None, @@ -256,7 +257,7 @@ impl ConnectorIntegration CustomResult { self.build_error_response(res) } @@ -337,7 +338,7 @@ impl ConnectorIntegration CustomResult { self.build_error_response(res) } @@ -422,7 +423,7 @@ impl ConnectorIntegration CustomResult { self.build_error_response(res) } @@ -499,7 +500,7 @@ impl ConnectorIntegration CustomResult { self.build_error_response(res) } @@ -585,7 +586,7 @@ impl ConnectorIntegration CustomResult { self.build_error_response(res) } @@ -653,7 +654,7 @@ impl ConnectorIntegration CustomResult { self.build_error_response(res) } diff --git a/crates/router/src/connector/cybersource/transformers.rs b/crates/router/src/connector/cybersource/transformers.rs index 8e84d5687d..d7dbb8a820 100644 --- a/crates/router/src/connector/cybersource/transformers.rs +++ b/crates/router/src/connector/cybersource/transformers.rs @@ -300,6 +300,7 @@ impl code: consts::NO_ERROR_CODE.to_string(), message: error.message, reason: Some(error.reason), + status_code: item.http_code, }), _ => Ok(types::PaymentsResponseData::TransactionResponse { resource_id: types::ResponseId::ConnectorTransactionId(item.response.id), diff --git a/crates/router/src/connector/fiserv.rs b/crates/router/src/connector/fiserv.rs index b4b78f8416..ba20bc5d0a 100644 --- a/crates/router/src/connector/fiserv.rs +++ b/crates/router/src/connector/fiserv.rs @@ -3,7 +3,6 @@ mod transformers; use std::fmt::Debug; use base64::Engine; -use bytes::Bytes; use error_stack::ResultExt; use ring::hmac; use time::OffsetDateTime; @@ -200,9 +199,10 @@ impl fn get_error_response( &self, - res: Bytes, + res: types::Response, ) -> CustomResult { let response: fiserv::ErrorResponse = res + .response .parse_struct("Fiserv ErrorResponse") .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; @@ -223,6 +223,7 @@ impl }; Ok(types::ErrorResponse { + status_code: res.status_code, code: consts::NO_ERROR_CODE.to_string(), message, reason: None, @@ -347,9 +348,10 @@ impl fn get_error_response( &self, - res: Bytes, + res: types::Response, ) -> CustomResult { let response: fiserv::ErrorResponse = res + .response .parse_struct("Fiserv ErrorResponse") .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; @@ -369,6 +371,7 @@ impl (None, None) => consts::NO_ERROR_MESSAGE.to_string(), }; Ok(types::ErrorResponse { + status_code: res.status_code, code: consts::NO_ERROR_CODE.to_string(), message, reason: None, diff --git a/crates/router/src/connector/globalpay.rs b/crates/router/src/connector/globalpay.rs index b1244c0f09..0d6cde6864 100644 --- a/crates/router/src/connector/globalpay.rs +++ b/crates/router/src/connector/globalpay.rs @@ -4,7 +4,6 @@ mod transformers; use std::fmt::Debug; -use bytes::Bytes; use error_stack::{IntoReport, ResultExt}; use self::{ @@ -22,7 +21,7 @@ use crate::{ types::{ self, api::{self, ConnectorCommon, ConnectorCommonExt}, - ErrorResponse, Response, + ErrorResponse, }, utils::{self, BytesExt}, }; @@ -77,13 +76,15 @@ impl ConnectorCommon for Globalpay { fn build_error_response( &self, - res: Bytes, + res: types::Response, ) -> CustomResult { let response: globalpay::GlobalpayErrorResponse = res + .response .parse_struct("Globalpay ErrorResponse") .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; Ok(ErrorResponse { + status_code: res.status_code, code: response.error_code, message: response.detailed_error_description, reason: None, @@ -157,7 +158,7 @@ impl ConnectorIntegration CustomResult { let response: GlobalpayPaymentsResponse = res .response @@ -175,7 +176,7 @@ impl ConnectorIntegration CustomResult { self.build_error_response(res) } @@ -228,7 +229,7 @@ impl ConnectorIntegration CustomResult { self.build_error_response(res) } @@ -236,7 +237,7 @@ impl ConnectorIntegration CustomResult { logger::debug!(payment_sync_response=?res); let response: GlobalpayPaymentsResponse = res @@ -311,7 +312,7 @@ impl ConnectorIntegration CustomResult { let response: GlobalpayPaymentsResponse = res .response @@ -329,7 +330,7 @@ impl ConnectorIntegration CustomResult { self.build_error_response(res) } @@ -400,7 +401,7 @@ impl ConnectorIntegration CustomResult { let response: GlobalpayPaymentsResponse = res .response @@ -418,7 +419,7 @@ impl ConnectorIntegration CustomResult { self.build_error_response(res) } @@ -484,7 +485,7 @@ impl ConnectorIntegration, - res: Response, + res: types::Response, ) -> CustomResult, errors::ConnectorError> { logger::debug!(target: "router::connector::globalpay", response=?res); let response: GlobalpayPaymentsResponse = res @@ -502,7 +503,7 @@ impl ConnectorIntegration CustomResult { self.build_error_response(res) } @@ -553,7 +554,7 @@ impl ConnectorIntegration CustomResult { logger::debug!(target: "router::connector::globalpay", response=?res); let response: GlobalpayPaymentsResponse = res @@ -571,7 +572,7 @@ impl ConnectorIntegration CustomResult { self.build_error_response(res) } diff --git a/crates/router/src/connector/klarna.rs b/crates/router/src/connector/klarna.rs index 17423a102b..dc60b8982a 100644 --- a/crates/router/src/connector/klarna.rs +++ b/crates/router/src/connector/klarna.rs @@ -2,7 +2,6 @@ mod transformers; use std::fmt::Debug; use api_models::payments as api_payments; -use bytes::Bytes; use error_stack::{IntoReport, ResultExt}; use transformers as klarna; @@ -141,13 +140,15 @@ impl fn get_error_response( &self, - res: Bytes, + res: types::Response, ) -> CustomResult { logger::debug!(klarna_session_error_logs=?res); let response: klarna::KlarnaErrorResponse = res + .response .parse_struct("KlarnaErrorResponse") .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; Ok(types::ErrorResponse { + status_code: res.status_code, code: response.error_code, message: response.error_messages.join(" & "), reason: None, @@ -284,13 +285,15 @@ impl fn get_error_response( &self, - res: Bytes, + res: types::Response, ) -> CustomResult { logger::debug!(klarna_error_response=?res); let response: klarna::KlarnaErrorResponse = res + .response .parse_struct("KlarnaErrorResponse") .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; Ok(types::ErrorResponse { + status_code: res.status_code, code: response.error_code, message: response.error_messages.join(" & "), reason: None, diff --git a/crates/router/src/connector/payu.rs b/crates/router/src/connector/payu.rs index da46caa247..8828f6d291 100644 --- a/crates/router/src/connector/payu.rs +++ b/crates/router/src/connector/payu.rs @@ -2,7 +2,6 @@ mod transformers; use std::fmt::Debug; -use bytes::Bytes; use error_stack::{IntoReport, ResultExt}; use transformers as payu; @@ -16,7 +15,7 @@ use crate::{ types::{ self, api::{self, ConnectorCommon, ConnectorCommonExt}, - ErrorResponse, Response, + ErrorResponse, }, utils::{self, BytesExt}, }; @@ -67,13 +66,15 @@ impl ConnectorCommon for Payu { } fn build_error_response( &self, - res: Bytes, + res: types::Response, ) -> CustomResult { let response: payu::PayuErrorResponse = res + .response .parse_struct("Payu ErrorResponse") .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; Ok(ErrorResponse { + status_code: res.status_code, code: response.status.status_code, message: response.status.status_desc, reason: response.status.code_literal, @@ -142,7 +143,7 @@ impl fn handle_response( &self, data: &types::PaymentsCancelRouterData, - res: Response, + res: types::Response, ) -> CustomResult { let response: payu::PayuPaymentsCancelResponse = res .response @@ -158,7 +159,7 @@ impl } fn get_error_response( &self, - res: Bytes, + res: types::Response, ) -> CustomResult { self.build_error_response(res) } @@ -216,7 +217,7 @@ impl fn handle_response( &self, data: &types::PaymentsSyncRouterData, - res: Response, + res: types::Response, ) -> CustomResult { logger::debug!(target: "router::connector::payu", response=?res); let response: payu::PayuPaymentsSyncResponse = res @@ -234,7 +235,7 @@ impl fn get_error_response( &self, - res: Bytes, + res: types::Response, ) -> CustomResult { self.build_error_response(res) } @@ -303,7 +304,7 @@ impl fn handle_response( &self, data: &types::PaymentsCaptureRouterData, - res: Response, + res: types::Response, ) -> CustomResult { let response: payu::PayuPaymentsCaptureResponse = res .response @@ -320,7 +321,7 @@ impl fn get_error_response( &self, - res: Bytes, + res: types::Response, ) -> CustomResult { self.build_error_response(res) } @@ -402,7 +403,7 @@ impl fn handle_response( &self, data: &types::PaymentsAuthorizeRouterData, - res: Response, + res: types::Response, ) -> CustomResult { let response: payu::PayuPaymentsResponse = res .response @@ -420,7 +421,7 @@ impl fn get_error_response( &self, - res: Bytes, + res: types::Response, ) -> CustomResult { self.build_error_response(res) } @@ -487,7 +488,7 @@ impl services::ConnectorIntegration, - res: Response, + res: types::Response, ) -> CustomResult, errors::ConnectorError> { logger::debug!(target: "router::connector::payu", response=?res); let response: payu::RefundResponse = res @@ -505,7 +506,7 @@ impl services::ConnectorIntegration CustomResult { self.build_error_response(res) } @@ -557,7 +558,7 @@ impl services::ConnectorIntegration CustomResult { logger::debug!(target: "router::connector::payu", response=?res); let response: payu::RefundSyncResponse = @@ -575,7 +576,7 @@ impl services::ConnectorIntegration CustomResult { self.build_error_response(res) } diff --git a/crates/router/src/connector/rapyd.rs b/crates/router/src/connector/rapyd.rs index b6f35e1a93..c18beaa435 100644 --- a/crates/router/src/connector/rapyd.rs +++ b/crates/router/src/connector/rapyd.rs @@ -2,7 +2,6 @@ mod transformers; use std::fmt::Debug; use base64::Engine; -use bytes::Bytes; use common_utils::date_time; use error_stack::{IntoReport, ResultExt}; use rand::distributions::{Alphanumeric, DistString}; @@ -20,7 +19,7 @@ use crate::{ types::{ self, api::{self, ConnectorCommon}, - ErrorResponse, Response, + ErrorResponse, }, utils::{self, BytesExt}, }; @@ -155,7 +154,7 @@ impl fn handle_response( &self, data: &types::PaymentsAuthorizeRouterData, - res: Response, + res: types::Response, ) -> CustomResult { let response: rapyd::RapydPaymentsResponse = res .response @@ -173,12 +172,14 @@ impl fn get_error_response( &self, - res: Bytes, + res: types::Response, ) -> CustomResult { let response: rapyd::RapydPaymentsResponse = res + .response .parse_struct("Rapyd ErrorResponse") .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; Ok(ErrorResponse { + status_code: res.status_code, code: response.status.error_code, message: response.status.status, reason: response.status.message, @@ -265,7 +266,7 @@ impl fn handle_response( &self, data: &types::PaymentsCancelRouterData, - res: Response, + res: types::Response, ) -> CustomResult { let response: rapyd::RapydPaymentsResponse = res .response @@ -283,12 +284,14 @@ impl fn get_error_response( &self, - res: Bytes, + res: types::Response, ) -> CustomResult { let response: rapyd::RapydPaymentsResponse = res + .response .parse_struct("Rapyd ErrorResponse") .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; Ok(ErrorResponse { + status_code: res.status_code, code: response.status.error_code, message: response.status.status, reason: response.status.message, @@ -331,7 +334,7 @@ impl fn get_error_response( &self, - _res: Bytes, + _res: types::Response, ) -> CustomResult { Err(errors::ConnectorError::NotImplemented("PSync".to_string()).into()) } @@ -339,7 +342,7 @@ impl fn handle_response( &self, _data: &types::PaymentsSyncRouterData, - _res: Response, + _res: types::Response, ) -> CustomResult { Err(errors::ConnectorError::NotImplemented("PSync".to_string()).into()) } @@ -416,7 +419,7 @@ impl fn handle_response( &self, data: &types::PaymentsCaptureRouterData, - res: Response, + res: types::Response, ) -> CustomResult { let response: rapyd::RapydPaymentsResponse = res .response @@ -445,12 +448,14 @@ impl fn get_error_response( &self, - res: Bytes, + res: types::Response, ) -> CustomResult { let response: rapyd::RapydPaymentsResponse = res + .response .parse_struct("Rapyd ErrorResponse") .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; Ok(ErrorResponse { + status_code: res.status_code, code: response.status.error_code, message: response.status.status, reason: response.status.message, @@ -541,7 +546,7 @@ impl services::ConnectorIntegration, - res: Response, + res: types::Response, ) -> CustomResult, errors::ConnectorError> { logger::debug!(target: "router::connector::rapyd", response=?res); let response: rapyd::RefundResponse = res @@ -559,12 +564,14 @@ impl services::ConnectorIntegration CustomResult { let response: rapyd::RapydPaymentsResponse = res + .response .parse_struct("Rapyd ErrorResponse") .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; Ok(ErrorResponse { + status_code: res.status_code, code: response.status.error_code, message: response.status.status, reason: response.status.message, @@ -598,7 +605,7 @@ impl services::ConnectorIntegration CustomResult { logger::debug!(target: "router::connector::rapyd", response=?res); let response: rapyd::RefundResponse = res @@ -616,7 +623,7 @@ impl services::ConnectorIntegration CustomResult { Err(errors::ConnectorError::NotImplemented("RSync".to_string()).into()) } diff --git a/crates/router/src/connector/rapyd/transformers.rs b/crates/router/src/connector/rapyd/transformers.rs index f2bd831525..3eb8926f21 100644 --- a/crates/router/src/connector/rapyd/transformers.rs +++ b/crates/router/src/connector/rapyd/transformers.rs @@ -219,6 +219,7 @@ impl TryFrom> enums::AttemptStatus::Failure, Err(types::ErrorResponse { code: item.response.status.error_code, + status_code: item.http_code, message: item.response.status.status, reason: item.response.status.message, }), @@ -228,6 +229,7 @@ impl TryFrom> enums::AttemptStatus::Failure, Err(types::ErrorResponse { code: item.response.status.error_code, + status_code: item.http_code, message: item.response.status.status, reason: item.response.status.message, }), @@ -236,6 +238,7 @@ impl TryFrom> enums::AttemptStatus::Failure, Err(types::ErrorResponse { code: item.response.status.error_code, + status_code: item.http_code, message: item.response.status.status, reason: item.response.status.message, }), @@ -397,6 +400,7 @@ impl TryFrom> code: item.response.status.error_code, message: item.response.status.status, reason: item.response.status.message, + status_code: item.http_code, }), ), }, @@ -406,6 +410,7 @@ impl TryFrom> code: item.response.status.error_code, message: item.response.status.status, reason: item.response.status.message, + status_code: item.http_code, }), ), _ => ( @@ -414,6 +419,7 @@ impl TryFrom> code: item.response.status.error_code, message: item.response.status.status, reason: item.response.status.message, + status_code: item.http_code, }), ), }; @@ -449,6 +455,7 @@ impl TryFrom> enums::AttemptStatus::Failure, Err(types::ErrorResponse { code: item.response.status.error_code, + status_code: item.http_code, message: item.response.status.status, reason: item.response.status.message, }), @@ -458,6 +465,7 @@ impl TryFrom> enums::AttemptStatus::Failure, Err(types::ErrorResponse { code: item.response.status.error_code, + status_code: item.http_code, message: item.response.status.status, reason: item.response.status.message, }), @@ -466,6 +474,7 @@ impl TryFrom> enums::AttemptStatus::Failure, Err(types::ErrorResponse { code: item.response.status.error_code, + status_code: item.http_code, message: item.response.status.status, reason: item.response.status.message, }), diff --git a/crates/router/src/connector/shift4.rs b/crates/router/src/connector/shift4.rs index 64c715c226..ef820241ad 100644 --- a/crates/router/src/connector/shift4.rs +++ b/crates/router/src/connector/shift4.rs @@ -2,7 +2,6 @@ mod transformers; use std::fmt::Debug; -use bytes::Bytes; use common_utils::ext_traits::ByteSliceExt; use error_stack::ResultExt; use transformers as shift4; @@ -19,7 +18,7 @@ use crate::{ types::{ self, api::{self, ConnectorCommon, ConnectorCommonExt}, - ErrorResponse, Response, + ErrorResponse, }, utils::{self, BytesExt, OptionExt}, }; @@ -76,13 +75,15 @@ impl ConnectorCommon for Shift4 { fn build_error_response( &self, - res: Bytes, + res: types::Response, ) -> CustomResult { let response: shift4::ErrorResponse = res + .response .parse_struct("Shift4 ErrorResponse") .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; Ok(ErrorResponse { + status_code: res.status_code, code: response .error .code @@ -157,7 +158,7 @@ impl ConnectorIntegration CustomResult { self.build_error_response(res) } @@ -165,7 +166,7 @@ impl ConnectorIntegration CustomResult { logger::debug!(payment_sync_response=?res); let response: shift4::Shift4PaymentsResponse = res @@ -217,7 +218,7 @@ impl ConnectorIntegration CustomResult { let response: shift4::Shift4PaymentsResponse = res .response @@ -248,7 +249,7 @@ impl ConnectorIntegration CustomResult { self.build_error_response(res) } @@ -317,7 +318,7 @@ impl ConnectorIntegration CustomResult { let response: shift4::Shift4PaymentsResponse = res .response @@ -335,7 +336,7 @@ impl ConnectorIntegration CustomResult { self.build_error_response(res) } @@ -394,7 +395,7 @@ impl ConnectorIntegration, - res: Response, + res: types::Response, ) -> CustomResult, errors::ConnectorError> { logger::debug!(target: "router::connector::shift4", response=?res); let response: shift4::RefundResponse = res @@ -412,7 +413,7 @@ impl ConnectorIntegration CustomResult { self.build_error_response(res) } @@ -468,7 +469,7 @@ impl ConnectorIntegration CustomResult { logger::debug!(target: "router::connector::shift4", response=?res); let response: shift4::RefundResponse = @@ -486,7 +487,7 @@ impl ConnectorIntegration CustomResult { self.build_error_response(res) } diff --git a/crates/router/src/connector/stripe.rs b/crates/router/src/connector/stripe.rs index e6b6687e61..390645b79b 100644 --- a/crates/router/src/connector/stripe.rs +++ b/crates/router/src/connector/stripe.rs @@ -2,7 +2,6 @@ mod transformers; use std::{collections::HashMap, fmt::Debug}; -use bytes::Bytes; use error_stack::{IntoReport, ResultExt}; use router_env::{instrument, tracing}; @@ -167,13 +166,15 @@ impl fn get_error_response( &self, - res: Bytes, + res: types::Response, ) -> CustomResult { let response: stripe::ErrorResponse = res + .response .parse_struct("ErrorResponse") .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; Ok(types::ErrorResponse { + status_code: res.status_code, code: response .error .code @@ -266,13 +267,15 @@ impl fn get_error_response( &self, - res: Bytes, + res: types::Response, ) -> CustomResult { let response: stripe::ErrorResponse = res + .response .parse_struct("ErrorResponse") .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; Ok(types::ErrorResponse { + status_code: res.status_code, code: response .error .code @@ -376,12 +379,14 @@ impl fn get_error_response( &self, - res: Bytes, + res: types::Response, ) -> CustomResult { let response: stripe::ErrorResponse = res + .response .parse_struct("ErrorResponse") .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; Ok(types::ErrorResponse { + status_code: res.status_code, code: response .error .code @@ -481,12 +486,14 @@ impl fn get_error_response( &self, - res: Bytes, + res: types::Response, ) -> CustomResult { let response: stripe::ErrorResponse = res + .response .parse_struct("ErrorResponse") .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; Ok(types::ErrorResponse { + status_code: res.status_code, code: response .error .code @@ -606,12 +613,14 @@ impl fn get_error_response( &self, - res: Bytes, + res: types::Response, ) -> CustomResult { let response: stripe::ErrorResponse = res + .response .parse_struct("ErrorResponse") .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; Ok(types::ErrorResponse { + status_code: res.status_code, code: response .error .code @@ -708,12 +717,14 @@ impl services::ConnectorIntegration CustomResult { let response: stripe::ErrorResponse = res + .response .parse_struct("ErrorResponse") .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; Ok(types::ErrorResponse { + status_code: res.status_code, code: response .error .code @@ -808,12 +819,14 @@ impl services::ConnectorIntegration CustomResult { let response: stripe::ErrorResponse = res + .response .parse_struct("ErrorResponse") .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; Ok(types::ErrorResponse { + status_code: res.status_code, code: response .error .code diff --git a/crates/router/src/connector/worldline.rs b/crates/router/src/connector/worldline.rs index 27b480a222..38e9cd36d0 100644 --- a/crates/router/src/connector/worldline.rs +++ b/crates/router/src/connector/worldline.rs @@ -3,7 +3,6 @@ mod transformers; use std::fmt::Debug; use base64::Engine; -use bytes::Bytes; use error_stack::{IntoReport, ResultExt}; use ring::hmac; use storage_models::enums; @@ -19,7 +18,7 @@ use crate::{ types::{ self, api::{self, ConnectorCommon, ConnectorCommonExt}, - ErrorResponse, Response, + ErrorResponse, }, utils::{self, BytesExt, OptionExt}, }; @@ -105,13 +104,15 @@ impl ConnectorCommon for Worldline { fn build_error_response( &self, - res: Bytes, + res: types::Response, ) -> CustomResult { let response: worldline::ErrorResponse = res + .response .parse_struct("Worldline ErrorResponse") .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; let error = response.errors.into_iter().next().unwrap_or_default(); Ok(ErrorResponse { + status_code: res.status_code, code: error .code .unwrap_or_else(|| consts::NO_ERROR_CODE.to_string()), @@ -175,7 +176,7 @@ impl ConnectorIntegration CustomResult { let response: worldline::PaymentResponse = res .response @@ -192,7 +193,7 @@ impl ConnectorIntegration CustomResult { self.build_error_response(res) } @@ -252,7 +253,7 @@ impl ConnectorIntegration CustomResult { self.build_error_response(res) } @@ -260,7 +261,7 @@ impl ConnectorIntegration CustomResult { logger::debug!(payment_sync_response=?res); let mut response: worldline::Payment = res @@ -354,7 +355,7 @@ impl ConnectorIntegration, - res: Response, + res: types::Response, ) -> CustomResult< types::RouterData, errors::ConnectorError, @@ -380,7 +381,7 @@ impl ConnectorIntegration CustomResult { self.build_error_response(res) } @@ -458,7 +459,7 @@ impl ConnectorIntegration CustomResult { logger::debug!(payment_authorize_response=?res); let mut response: worldline::PaymentResponse = res @@ -477,7 +478,7 @@ impl ConnectorIntegration CustomResult { self.build_error_response(res) } @@ -544,7 +545,7 @@ impl ConnectorIntegration, - res: Response, + res: types::Response, ) -> CustomResult, errors::ConnectorError> { logger::debug!(target: "router::connector::worldline", response=?res); let response: worldline::RefundResponse = res @@ -562,7 +563,7 @@ impl ConnectorIntegration CustomResult { self.build_error_response(res) } @@ -625,7 +626,7 @@ impl ConnectorIntegration CustomResult { logger::debug!(target: "router::connector::worldline", response=?res); let response: worldline::RefundResponse = res @@ -643,7 +644,7 @@ impl ConnectorIntegration CustomResult { self.build_error_response(res) } diff --git a/crates/router/src/connector/worldpay.rs b/crates/router/src/connector/worldpay.rs index f6668a7526..9679a478ee 100644 --- a/crates/router/src/connector/worldpay.rs +++ b/crates/router/src/connector/worldpay.rs @@ -4,7 +4,6 @@ mod transformers; use std::fmt::Debug; -use bytes::Bytes; use error_stack::{IntoReport, ResultExt}; use storage_models::enums; use transformers as worldpay; @@ -73,12 +72,14 @@ impl ConnectorCommon for Worldpay { fn build_error_response( &self, - res: Bytes, + res: Response, ) -> CustomResult { let response: WorldpayErrorResponse = res + .response .parse_struct("WorldpayErrorResponse") .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; Ok(ErrorResponse { + status_code: res.status_code, code: response.error_name, message: response.message, reason: None, @@ -172,7 +173,7 @@ impl ConnectorIntegration CustomResult { self.build_error_response(res) } @@ -228,7 +229,7 @@ impl ConnectorIntegration CustomResult { self.build_error_response(res) } @@ -332,7 +333,7 @@ impl ConnectorIntegration CustomResult { self.build_error_response(res) } @@ -421,7 +422,7 @@ impl ConnectorIntegration CustomResult { self.build_error_response(res) } @@ -510,7 +511,7 @@ impl ConnectorIntegration CustomResult { self.build_error_response(res) } @@ -576,7 +577,7 @@ impl ConnectorIntegration CustomResult { self.build_error_response(res) } diff --git a/crates/router/src/core/errors/api_error_response.rs b/crates/router/src/core/errors/api_error_response.rs index 6ebe7032ac..517de1ec40 100644 --- a/crates/router/src/core/errors/api_error_response.rs +++ b/crates/router/src/core/errors/api_error_response.rs @@ -11,6 +11,7 @@ pub enum ErrorType { ServerNotAvailable, DuplicateRequest, ValidationError, + ConnectorError, } #[allow(dead_code)] @@ -134,6 +135,12 @@ pub enum ApiErrorResponse { MandateValidationFailed { reason: String }, #[error(error_type = ErrorType::ServerNotAvailable, code = "IR_00", message = "This API is under development and will be made available soon.")] NotImplemented, + #[error(error_type = ErrorType::ConnectorError, code = "CE_00", message = "{message}", ignore = "status_code")] + ExternalConnectorError { + message: String, + connector: String, + status_code: u16, + }, } impl ::core::fmt::Display for ApiErrorResponse { @@ -154,6 +161,9 @@ impl actix_web::ResponseError for ApiErrorResponse { Self::Unauthorized | Self::InvalidEphermeralKey | Self::InvalidJwtToken => { StatusCode::UNAUTHORIZED } // 401 + Self::ExternalConnectorError { status_code, .. } => { + StatusCode::from_u16(*status_code).unwrap_or(StatusCode::INTERNAL_SERVER_ERROR) + } Self::InvalidRequestUrl => StatusCode::NOT_FOUND, // 404 Self::InvalidHttpMethod => StatusCode::METHOD_NOT_ALLOWED, // 405 Self::MissingRequiredField { .. } | Self::InvalidDataValue { .. } => { diff --git a/crates/router/src/core/payments/operations/payment_response.rs b/crates/router/src/core/payments/operations/payment_response.rs index 1383a19542..cf9f33ccd6 100644 --- a/crates/router/src/core/payments/operations/payment_response.rs +++ b/crates/router/src/core/payments/operations/payment_response.rs @@ -161,6 +161,7 @@ async fn payment_response_update_tracker( router_data: types::RouterData, storage_scheme: enums::MerchantStorageScheme, ) -> RouterResult> { + let connector = router_data.connector.clone(); let (payment_attempt_update, connector_response_update) = match router_data.response.clone() { Err(err) => ( Some(storage::PaymentAttemptUpdate::ErrorUpdate { @@ -275,5 +276,13 @@ async fn payment_response_update_tracker( .await .map_err(|error| error.to_not_found_response(errors::ApiErrorResponse::PaymentNotFound))?; + router_data.response.map_err(|error_response| { + errors::ApiErrorResponse::ExternalConnectorError { + message: format!("{}: {}", error_response.code, error_response.message), + status_code: error_response.status_code, + connector, + } + })?; + Ok(payment_data) } diff --git a/crates/router/src/services/api.rs b/crates/router/src/services/api.rs index f4aafd37b4..d02398464d 100644 --- a/crates/router/src/services/api.rs +++ b/crates/router/src/services/api.rs @@ -10,7 +10,6 @@ use std::{ }; use actix_web::{body, HttpRequest, HttpResponse, Responder}; -use bytes::Bytes; use error_stack::{report, IntoReport, Report, ResultExt}; use masking::ExposeOptionInterface; use router_env::{instrument, tracing, Tag}; @@ -107,7 +106,7 @@ pub trait ConnectorIntegration: ConnectorIntegrationAny CustomResult { Ok(ErrorResponse::get_not_implemented()) } @@ -170,8 +169,7 @@ where let response = match body { Ok(body) => connector_integration.handle_response(req, body)?, Err(body) => { - let error = - connector_integration.get_error_response(body.response)?; + let error = connector_integration.get_error_response(body)?; router_data.response = Err(error); router_data diff --git a/crates/router/src/types.rs b/crates/router/src/types.rs index 27a0ae9a8e..d9c2e22bd5 100644 --- a/crates/router/src/types.rs +++ b/crates/router/src/types.rs @@ -287,6 +287,7 @@ pub struct ErrorResponse { pub code: String, pub message: String, pub reason: Option, + pub status_code: u16, } impl ErrorResponse { @@ -295,6 +296,7 @@ impl ErrorResponse { code: errors::ApiErrorResponse::NotImplemented.error_code(), message: errors::ApiErrorResponse::NotImplemented.error_message(), reason: None, + status_code: http::StatusCode::INTERNAL_SERVER_ERROR.as_u16(), } } } @@ -305,6 +307,10 @@ impl From for ErrorResponse { code: error.error_code(), message: error.error_message(), reason: None, + status_code: match error { + errors::ApiErrorResponse::ExternalConnectorError { status_code, .. } => status_code, + _ => 500, + }, } } } diff --git a/crates/router/src/types/api.rs b/crates/router/src/types/api.rs index dc4824fe57..b5354041f8 100644 --- a/crates/router/src/types/api.rs +++ b/crates/router/src/types/api.rs @@ -9,7 +9,6 @@ pub mod webhooks; use std::{fmt::Debug, str::FromStr}; -use bytes::Bytes; use error_stack::{report, IntoReport, ResultExt}; pub use self::{admin::*, customers::*, payment_methods::*, payments::*, refunds::*, webhooks::*}; @@ -49,9 +48,10 @@ pub trait ConnectorCommon { /// common error response for a connector if it is same in all case fn build_error_response( &self, - _res: Bytes, + res: types::Response, ) -> CustomResult { Ok(ErrorResponse { + status_code: res.status_code, code: consts::NO_ERROR_CODE.to_string(), message: consts::NO_ERROR_MESSAGE.to_string(), reason: None, diff --git a/crates/router_derive/src/macros/api_error.rs b/crates/router_derive/src/macros/api_error.rs index 8c6790a76d..c3a8c1645a 100644 --- a/crates/router_derive/src/macros/api_error.rs +++ b/crates/router_derive/src/macros/api_error.rs @@ -189,7 +189,8 @@ fn implement_serialize( // Safety: Missing attributes are already checked before this function is called. #[allow(clippy::unwrap_used)] let error_message = properties.message.as_ref().unwrap(); - let msg_unused_fields = get_unused_fields(&variant.fields, &error_message.value()); + let msg_unused_fields = + get_unused_fields(&variant.fields, &error_message.value(), &properties.ignore); // Safety: Missing attributes are already checked before this function is called. #[allow(clippy::unwrap_used)] diff --git a/crates/router_derive/src/macros/api_error/helpers.rs b/crates/router_derive/src/macros/api_error/helpers.rs index 8da29f485b..e1e2a09eac 100644 --- a/crates/router_derive/src/macros/api_error/helpers.rs +++ b/crates/router_derive/src/macros/api_error/helpers.rs @@ -14,6 +14,7 @@ mod keyword { custom_keyword!(error_type); custom_keyword!(code); custom_keyword!(message); + custom_keyword!(ignore); } enum EnumMeta { @@ -107,6 +108,10 @@ enum VariantMeta { keyword: keyword::message, value: LitStr, }, + Ignore { + keyword: keyword::ignore, + value: LitStr, + }, } impl Parse for VariantMeta { @@ -127,6 +132,11 @@ impl Parse for VariantMeta { let _: Token![=] = input.parse()?; let value = input.parse()?; Ok(Self::Message { keyword, value }) + } else if lookahead.peek(keyword::ignore) { + let keyword = input.parse()?; + let _: Token![=] = input.parse()?; + let value = input.parse()?; + Ok(Self::Ignore { keyword, value }) } else { Err(lookahead.error()) } @@ -139,6 +149,7 @@ impl Spanned for VariantMeta { Self::ErrorType { keyword, .. } => keyword.span, Self::Code { keyword, .. } => keyword.span, Self::Message { keyword, .. } => keyword.span, + Self::Ignore { keyword, .. } => keyword.span, } } } @@ -163,6 +174,7 @@ pub(super) struct ErrorVariantProperties { pub error_type: Option, pub code: Option, pub message: Option, + pub ignore: std::collections::HashSet, } impl HasErrorVariantProperties for Variant { @@ -172,6 +184,7 @@ impl HasErrorVariantProperties for Variant { let mut error_type_keyword = None; let mut code_keyword = None; let mut message_keyword = None; + let mut ignore_keyword = None; for meta in self.get_metadata()? { match meta { VariantMeta::ErrorType { keyword, value } => { @@ -198,6 +211,18 @@ impl HasErrorVariantProperties for Variant { message_keyword = Some(keyword); output.message = Some(value); } + VariantMeta::Ignore { keyword, value } => { + if let Some(first_keyword) = ignore_keyword { + return Err(occurrence_error(first_keyword, keyword, "ignore")); + } + ignore_keyword = Some(keyword); + output.ignore = value + .value() + .replace(' ', "") + .split(',') + .map(ToString::to_string) + .collect(); + } } } @@ -227,20 +252,23 @@ pub(super) fn check_missing_attributes( } /// Get all the fields not used in the error message. -pub(super) fn get_unused_fields(fields: &Fields, message: &str) -> Vec { +pub(super) fn get_unused_fields( + fields: &Fields, + message: &str, + ignore: &std::collections::HashSet, +) -> Vec { let fields = match fields { syn::Fields::Unit => Vec::new(), syn::Fields::Unnamed(_) => Vec::new(), syn::Fields::Named(fields) => fields.named.iter().cloned().collect(), }; - fields .iter() .filter(|&field| { // Safety: Named fields are guaranteed to have an identifier. #[allow(clippy::unwrap_used)] let field_name = format!("{}", field.ident.as_ref().unwrap()); - !message.contains(&field_name) + !message.contains(&field_name) && !ignore.contains(&field_name) }) .cloned() .collect()