bugfix: use connector error handler for 500 error messages. (#696)

This commit is contained in:
Narayan Bhat
2023-03-02 16:46:27 +05:30
committed by GitHub
parent d622b7438e
commit 9fe2093215
10 changed files with 60 additions and 35 deletions

View File

@ -356,6 +356,7 @@ pub enum PaymentMethodIssuerCode {
Debug, Debug,
serde::Serialize, serde::Serialize,
serde::Deserialize, serde::Deserialize,
strum::Display,
ToSchema, ToSchema,
Default, Default,
frunk::LabelledGeneric, frunk::LabelledGeneric,

View File

@ -397,6 +397,7 @@ impl<'a> TryFrom<&api_enums::BankNames> for AdyenTestBankNames<'a> {
_ => Err(errors::ConnectorError::NotSupported { _ => Err(errors::ConnectorError::NotSupported {
payment_method: String::from("BankRedirect"), payment_method: String::from("BankRedirect"),
connector: "Adyen", connector: "Adyen",
payment_experience: api_enums::PaymentExperience::RedirectToUrl.to_string(),
})?, })?,
}) })
} }

View File

@ -7,6 +7,7 @@ use transformers as klarna;
use crate::{ use crate::{
configs::settings, configs::settings,
connector::utils as connector_utils,
core::errors::{self, CustomResult}, core::errors::{self, CustomResult},
headers, headers,
services::{self}, services::{self},
@ -230,34 +231,37 @@ impl
connectors: &settings::Connectors, connectors: &settings::Connectors,
) -> CustomResult<String, errors::ConnectorError> { ) -> CustomResult<String, errors::ConnectorError> {
let payment_method_data = &req.request.payment_method_data; let payment_method_data = &req.request.payment_method_data;
let payment_experience = req
.request
.payment_experience
.as_ref()
.ok_or_else(connector_utils::missing_field_err("payment_experience"))?;
let payment_method_type = req
.request
.payment_method_type
.as_ref()
.ok_or_else(connector_utils::missing_field_err("payment_method_type"))?;
match payment_method_data { match payment_method_data {
api_payments::PaymentMethodData::PayLater(api_payments::PayLaterData::KlarnaSdk { api_payments::PaymentMethodData::PayLater(api_payments::PayLaterData::KlarnaSdk {
token, token,
}) => match ( }) => match (payment_experience, payment_method_type) {
req.request.payment_experience.as_ref(),
req.request.payment_method_type.as_ref(),
) {
( (
Some(storage_enums::PaymentExperience::InvokeSdkClient), storage_enums::PaymentExperience::InvokeSdkClient,
Some(storage_enums::PaymentMethodType::Klarna), storage_enums::PaymentMethodType::Klarna,
) => Ok(format!( ) => Ok(format!(
"{}payments/v1/authorizations/{}/order", "{}payments/v1/authorizations/{}/order",
self.base_url(connectors), self.base_url(connectors),
token token
)), )),
(None, _) | (_, None) => Err(error_stack::report!( _ => Err(error_stack::report!(errors::ConnectorError::NotSupported {
errors::ConnectorError::MissingRequiredField { payment_method: payment_method_type.to_string(),
field_name: "payment_experience/payment_method_type" connector: "klarna",
} payment_experience: payment_experience.to_string()
)), })),
_ => Err(error_stack::report!(
errors::ConnectorError::MismatchedPaymentData
)),
}, },
_ => Err(error_stack::report!( _ => Err(error_stack::report!(
errors::ConnectorError::NotImplemented( errors::ConnectorError::MismatchedPaymentData
"We only support wallet payments through klarna".to_string(),
)
)), )),
} }
} }

View File

@ -1,6 +1,6 @@
use std::str::FromStr; use std::str::FromStr;
use api_models::{self, payments}; use api_models::{self, enums as api_enums, payments};
use common_utils::{fp_utils, pii::Email}; use common_utils::{fp_utils, pii::Email};
use error_stack::{IntoReport, ResultExt}; use error_stack::{IntoReport, ResultExt};
use masking::ExposeInterface; use masking::ExposeInterface;
@ -315,8 +315,9 @@ impl TryFrom<&api_models::enums::BankNames> for StripeBankNames {
api_models::enums::BankNames::VolkskreditbankAg => Self::VolkskreditbankAg, api_models::enums::BankNames::VolkskreditbankAg => Self::VolkskreditbankAg,
api_models::enums::BankNames::VrBankBraunau => Self::VrBankBraunau, api_models::enums::BankNames::VrBankBraunau => Self::VrBankBraunau,
_ => Err(errors::ConnectorError::NotSupported { _ => Err(errors::ConnectorError::NotSupported {
payment_method: String::from("BankRedirect"), payment_method: api_enums::PaymentMethod::BankRedirect.to_string(),
connector: "Stripe", connector: "Stripe",
payment_experience: api_enums::PaymentExperience::RedirectToUrl.to_string(),
})?, })?,
}) })
} }
@ -366,14 +367,16 @@ fn infer_stripe_pay_later_type(
Ok(StripePaymentMethodType::AfterpayClearpay) Ok(StripePaymentMethodType::AfterpayClearpay)
} }
_ => Err(errors::ConnectorError::NotSupported { _ => Err(errors::ConnectorError::NotSupported {
payment_method: format!("{pm_type} payments by {experience}"), payment_method: pm_type.to_string(),
connector: "stripe", connector: "stripe",
payment_experience: experience.to_string(),
}), }),
} }
} else { } else {
Err(errors::ConnectorError::NotSupported { Err(errors::ConnectorError::NotSupported {
payment_method: format!("{pm_type} payments by {experience}"), payment_method: pm_type.to_string(),
connector: "stripe", connector: "stripe",
payment_experience: experience.to_string(),
}) })
} }
} }

View File

@ -6,7 +6,12 @@ use serde::{Deserialize, Serialize};
use crate::{ use crate::{
connector::utils::{self, CardData}, connector::utils::{self, CardData},
core::errors, core::errors,
types::{self, api, storage::enums, transformers::ForeignFrom}, types::{
self,
api::{self, enums as api_enums},
storage::enums,
transformers::ForeignFrom,
},
}; };
#[derive(Default, Debug, Serialize, Eq, PartialEq)] #[derive(Default, Debug, Serialize, Eq, PartialEq)]
@ -125,8 +130,9 @@ impl TryFrom<utils::CardIssuer> for Gateway {
utils::CardIssuer::Discover => Ok(Self::Discover), utils::CardIssuer::Discover => Ok(Self::Discover),
utils::CardIssuer::Visa => Ok(Self::Visa), utils::CardIssuer::Visa => Ok(Self::Visa),
_ => Err(errors::ConnectorError::NotSupported { _ => Err(errors::ConnectorError::NotSupported {
payment_method: format!("{issuer}"), payment_method: api_enums::PaymentMethod::Card.to_string(),
connector: "worldline", connector: "worldline",
payment_experience: api_enums::PaymentExperience::RedirectToUrl.to_string(),
} }
.into()), .into()),
} }

View File

@ -254,6 +254,7 @@ pub enum ConnectorError {
NotSupported { NotSupported {
payment_method: String, payment_method: String,
connector: &'static str, connector: &'static str,
payment_experience: String,
}, },
#[error("Missing connector transaction ID")] #[error("Missing connector transaction ID")]
MissingConnectorTransactionID, MissingConnectorTransactionID,

View File

@ -423,7 +423,7 @@ impl common_utils::errors::ErrorSwitch<api_models::errors::types::ApiErrorRespon
AER::NotFound(ApiError::new("HE", 2, "API Key does not exist in our records", None)) AER::NotFound(ApiError::new("HE", 2, "API Key does not exist in our records", None))
} }
Self::NotSupported { message } => { Self::NotSupported { message } => {
AER::BadRequest(ApiError::new("HE", 3, "{message}", None)) AER::BadRequest(ApiError::new("HE", 3, "Payment method type not supported", Some(Extra {reason: Some(message.to_owned()), ..Default::default()})))
} }
} }
} }

View File

@ -107,8 +107,8 @@ impl ConnectorErrorExt for error_stack::Report<errors::ConnectorError> {
"payment_method_data, payment_method_type and payment_experience does not match", "payment_method_data, payment_method_type and payment_experience does not match",
} }
}, },
errors::ConnectorError::NotSupported { payment_method, connector } => { errors::ConnectorError::NotSupported { payment_method, connector, payment_experience } => {
errors::ApiErrorResponse::NotSupported { message: format!("{payment_method} is not supported by {connector}") } errors::ApiErrorResponse::NotSupported { message: format!("Payment method type {payment_method} is not supported by {connector} through payment experience {payment_experience}") }
} }
_ => errors::ApiErrorResponse::InternalServerError, _ => errors::ApiErrorResponse::InternalServerError,
}; };

View File

@ -315,14 +315,22 @@ async fn handle_response(
} }
status_code @ 500..=599 => { status_code @ 500..=599 => {
let error = match status_code { let bytes = response.bytes().await.map_err(|error| {
500 => errors::ApiClientError::InternalServerErrorReceived, report!(error)
502 => errors::ApiClientError::BadGatewayReceived, .change_context(errors::ApiClientError::ResponseDecodingFailed)
503 => errors::ApiClientError::ServiceUnavailableReceived, .attach_printable("Client error response received")
504 => errors::ApiClientError::GatewayTimeoutReceived, })?;
_ => errors::ApiClientError::UnexpectedServerResponse, // let error = match status_code {
}; // 500 => errors::ApiClientError::InternalServerErrorReceived,
Err(Report::new(error).attach_printable("Server error response received")) // 502 => errors::ApiClientError::BadGatewayReceived,
// 503 => errors::ApiClientError::ServiceUnavailableReceived,
// 504 => errors::ApiClientError::GatewayTimeoutReceived,
// _ => errors::ApiClientError::UnexpectedServerResponse,
// };
Ok(Err(types::Response {
response: bytes,
status_code,
}))
} }
status_code @ 400..=499 => { status_code @ 400..=499 => {

View File

@ -135,7 +135,8 @@ async fn should_throw_not_implemented_for_unsupported_issuer() {
*response.unwrap_err().current_context(), *response.unwrap_err().current_context(),
errors::ConnectorError::NotSupported { errors::ConnectorError::NotSupported {
payment_method: "Maestro".to_string(), payment_method: "Maestro".to_string(),
connector: "worldline" connector: "worldline",
payment_experience: "redirect_to_url".to_string(),
} }
) )
} }