Files
Narayan Bhat 0fb0191784 feat(payment_method_session): implement payment methods session confirm (#7248)
Co-authored-by: Sanchith Hegde <sanchith.hegde@juspay.in>
Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com>
Co-authored-by: Anurag Thakur <anurag.thakur@juspay.in>
Co-authored-by: Pa1NarK <69745008+pixincreate@users.noreply.github.com>
Co-authored-by: Shankar Singh C <83439957+ShankarSinghC@users.noreply.github.com>
Co-authored-by: Sai Harsha Vardhan <56996463+sai-harsha-vardhan@users.noreply.github.com>
Co-authored-by: hrithikesh026 <hrithikesh.vm@juspay.in>
Co-authored-by: Debarati Ghatak <88573135+cookieg13@users.noreply.github.com>
Co-authored-by: awasthi21 <107559116+awasthi21@users.noreply.github.com>
Co-authored-by: Gnanasundari24 <118818938+Gnanasundari24@users.noreply.github.com>
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Arindam Sahoo <88739246+arindam-sahoo@users.noreply.github.com>
Co-authored-by: Arindam Sahoo <arindam.sahoo@Arindam-Sahoo-F565040VFJ.local>
Co-authored-by: Sakil Mostak <73734619+Sakilmostak@users.noreply.github.com>
Co-authored-by: AkshayaFoiger <131388445+AkshayaFoiger@users.noreply.github.com>
Co-authored-by: Riddhiagrawal001 <50551695+Riddhiagrawal001@users.noreply.github.com>
Co-authored-by: Suman Maji <77887221+sumanmaji4@users.noreply.github.com>
Co-authored-by: Sandeep Kumar <83278309+tsdk02@users.noreply.github.com>
Co-authored-by: Debarshi Gupta <debarshigupta47@gmail.com>
Co-authored-by: Debarshi Gupta <debarshi.gupta@Debarshi-Gupta-CM92YWDXFD.local>
Co-authored-by: Sanchith Hegde <22217505+SanchithHegde@users.noreply.github.com>
Co-authored-by: Swangi Kumari <85639103+swangi-kumari@users.noreply.github.com>
Co-authored-by: pranav-arjunan <pranav.arjunan@juspay.in>
Co-authored-by: Kashif <kashif.dev@protonmail.com>
Co-authored-by: Sagnik Mitra <83326850+ImSagnik007@users.noreply.github.com>
Co-authored-by: sweta-kumari-sharma <77436883+Sweta-Kumari-Sharma@users.noreply.github.com>
Co-authored-by: shivansh.mathur <shivansh.mathur@juspay.in>
2025-02-26 17:24:53 +00:00

302 lines
12 KiB
Rust

pub use common_enums::{ApiClientError, ApplicationError, ApplicationResult};
use common_utils::errors::ErrorSwitch;
use hyperswitch_domain_models::errors::StorageError as DataStorageError;
pub use redis_interface::errors::RedisError;
use crate::store::errors::DatabaseError;
#[derive(Debug, thiserror::Error)]
pub enum StorageError {
#[error("DatabaseError: {0:?}")]
DatabaseError(error_stack::Report<DatabaseError>),
#[error("ValueNotFound: {0}")]
ValueNotFound(String),
#[error("DuplicateValue: {entity} already exists {key:?}")]
DuplicateValue {
entity: &'static str,
key: Option<String>,
},
#[error("Timed out while trying to connect to the database")]
DatabaseConnectionError,
#[error("KV error")]
KVError,
#[error("Serialization failure")]
SerializationFailed,
#[error("MockDb error")]
MockDbError,
#[error("Kafka error")]
KafkaError,
#[error("Customer with this id is Redacted")]
CustomerRedacted,
#[error("Deserialization failure")]
DeserializationFailed,
#[error("Error while encrypting data")]
EncryptionError,
#[error("Error while decrypting data from database")]
DecryptionError,
#[error("RedisError: {0:?}")]
RedisError(error_stack::Report<RedisError>),
}
impl ErrorSwitch<DataStorageError> for StorageError {
fn switch(&self) -> DataStorageError {
self.into()
}
}
#[allow(clippy::from_over_into)]
impl Into<DataStorageError> for &StorageError {
fn into(self) -> DataStorageError {
match self {
StorageError::DatabaseError(i) => match i.current_context() {
DatabaseError::DatabaseConnectionError => DataStorageError::DatabaseConnectionError,
// TODO: Update this error type to encompass & propagate the missing type (instead of generic `db value not found`)
DatabaseError::NotFound => {
DataStorageError::ValueNotFound(String::from("db value not found"))
}
// TODO: Update this error type to encompass & propagate the duplicate type (instead of generic `db value not found`)
DatabaseError::UniqueViolation => DataStorageError::DuplicateValue {
entity: "db entity",
key: None,
},
err => DataStorageError::DatabaseError(error_stack::report!(*err)),
},
StorageError::ValueNotFound(i) => DataStorageError::ValueNotFound(i.clone()),
StorageError::DuplicateValue { entity, key } => DataStorageError::DuplicateValue {
entity,
key: key.clone(),
},
StorageError::DatabaseConnectionError => DataStorageError::DatabaseConnectionError,
StorageError::KVError => DataStorageError::KVError,
StorageError::SerializationFailed => DataStorageError::SerializationFailed,
StorageError::MockDbError => DataStorageError::MockDbError,
StorageError::KafkaError => DataStorageError::KafkaError,
StorageError::CustomerRedacted => DataStorageError::CustomerRedacted,
StorageError::DeserializationFailed => DataStorageError::DeserializationFailed,
StorageError::EncryptionError => DataStorageError::EncryptionError,
StorageError::DecryptionError => DataStorageError::DecryptionError,
StorageError::RedisError(i) => match i.current_context() {
// TODO: Update this error type to encompass & propagate the missing type (instead of generic `redis value not found`)
RedisError::NotFound => {
DataStorageError::ValueNotFound("redis value not found".to_string())
}
RedisError::JsonSerializationFailed => DataStorageError::SerializationFailed,
RedisError::JsonDeserializationFailed => DataStorageError::DeserializationFailed,
i => DataStorageError::RedisError(format!("{:?}", i)),
},
}
}
}
impl From<error_stack::Report<RedisError>> for StorageError {
fn from(err: error_stack::Report<RedisError>) -> Self {
Self::RedisError(err)
}
}
impl From<diesel::result::Error> for StorageError {
fn from(err: diesel::result::Error) -> Self {
Self::from(error_stack::report!(DatabaseError::from(err)))
}
}
impl From<error_stack::Report<DatabaseError>> for StorageError {
fn from(err: error_stack::Report<DatabaseError>) -> Self {
Self::DatabaseError(err)
}
}
impl StorageError {
pub fn is_db_not_found(&self) -> bool {
match self {
Self::DatabaseError(err) => matches!(err.current_context(), DatabaseError::NotFound),
Self::ValueNotFound(_) => true,
Self::RedisError(err) => matches!(err.current_context(), RedisError::NotFound),
_ => false,
}
}
pub fn is_db_unique_violation(&self) -> bool {
match self {
Self::DatabaseError(err) => {
matches!(err.current_context(), DatabaseError::UniqueViolation,)
}
_ => false,
}
}
}
pub trait RedisErrorExt {
#[track_caller]
fn to_redis_failed_response(self, key: &str) -> error_stack::Report<DataStorageError>;
}
impl RedisErrorExt for error_stack::Report<RedisError> {
fn to_redis_failed_response(self, key: &str) -> error_stack::Report<DataStorageError> {
match self.current_context() {
RedisError::NotFound => self.change_context(DataStorageError::ValueNotFound(format!(
"Data does not exist for key {key}",
))),
RedisError::SetNxFailed | RedisError::SetAddMembersFailed => {
self.change_context(DataStorageError::DuplicateValue {
entity: "redis",
key: Some(key.to_string()),
})
}
_ => self.change_context(DataStorageError::KVError),
}
}
}
#[derive(Debug, thiserror::Error, PartialEq)]
pub enum ConnectorError {
#[error("Error while obtaining URL for the integration")]
FailedToObtainIntegrationUrl,
#[error("Failed to encode connector request")]
RequestEncodingFailed,
#[error("Request encoding failed : {0}")]
RequestEncodingFailedWithReason(String),
#[error("Parsing failed")]
ParsingFailed,
#[error("Failed to deserialize connector response")]
ResponseDeserializationFailed,
#[error("Failed to execute a processing step: {0:?}")]
ProcessingStepFailed(Option<bytes::Bytes>),
#[error("The connector returned an unexpected response: {0:?}")]
UnexpectedResponseError(bytes::Bytes),
#[error("Failed to parse custom routing rules from merchant account")]
RoutingRulesParsingError,
#[error("Failed to obtain preferred connector from merchant account")]
FailedToObtainPreferredConnector,
#[error("An invalid connector name was provided")]
InvalidConnectorName,
#[error("An invalid Wallet was used")]
InvalidWallet,
#[error("Failed to handle connector response")]
ResponseHandlingFailed,
#[error("Missing required field: {field_name}")]
MissingRequiredField { field_name: &'static str },
#[error("Missing required fields: {field_names:?}")]
MissingRequiredFields { field_names: Vec<&'static str> },
#[error("Failed to obtain authentication type")]
FailedToObtainAuthType,
#[error("Failed to obtain certificate")]
FailedToObtainCertificate,
#[error("Connector meta data not found")]
NoConnectorMetaData,
#[error("Failed to obtain certificate key")]
FailedToObtainCertificateKey,
#[error("This step has not been implemented for: {0}")]
NotImplemented(String),
#[error("{message} is not supported by {connector}")]
NotSupported {
message: String,
connector: &'static str,
payment_experience: String,
},
#[error("{flow} flow not supported by {connector} connector")]
FlowNotSupported { flow: String, connector: String },
#[error("Capture method not supported")]
CaptureMethodNotSupported,
#[error("Missing connector transaction ID")]
MissingConnectorTransactionID,
#[error("Missing connector refund ID")]
MissingConnectorRefundID,
#[error("Webhooks not implemented for this connector")]
WebhooksNotImplemented,
#[error("Failed to decode webhook event body")]
WebhookBodyDecodingFailed,
#[error("Signature not found for incoming webhook")]
WebhookSignatureNotFound,
#[error("Failed to verify webhook source")]
WebhookSourceVerificationFailed,
#[error("Could not find merchant secret in DB for incoming webhook source verification")]
WebhookVerificationSecretNotFound,
#[error("Incoming webhook object reference ID not found")]
WebhookReferenceIdNotFound,
#[error("Incoming webhook event type not found")]
WebhookEventTypeNotFound,
#[error("Incoming webhook event resource object not found")]
WebhookResourceObjectNotFound,
#[error("Could not respond to the incoming webhook event")]
WebhookResponseEncodingFailed,
#[error("Invalid Date/time format")]
InvalidDateFormat,
#[error("Date Formatting Failed")]
DateFormattingFailed,
#[error("Invalid Data format")]
InvalidDataFormat { field_name: &'static str },
#[error("Payment Method data / Payment Method Type / Payment Experience Mismatch ")]
MismatchedPaymentData,
#[error("Failed to parse Wallet token")]
InvalidWalletToken { wallet_name: String },
#[error("Missing Connector Related Transaction ID")]
MissingConnectorRelatedTransactionID { id: String },
#[error("File Validation failed")]
FileValidationFailed { reason: String },
#[error("Missing 3DS redirection payload: {field_name}")]
MissingConnectorRedirectionPayload { field_name: &'static str },
}
#[derive(Debug, thiserror::Error)]
pub enum HealthCheckDBError {
#[error("Error while connecting to database")]
DBError,
#[error("Error while writing to database")]
DBWriteError,
#[error("Error while reading element in the database")]
DBReadError,
#[error("Error while deleting element in the database")]
DBDeleteError,
#[error("Unpredictable error occurred")]
UnknownError,
#[error("Error in database transaction")]
TransactionError,
#[error("Error while executing query in Sqlx Analytics")]
SqlxAnalyticsError,
#[error("Error while executing query in Clickhouse Analytics")]
ClickhouseAnalyticsError,
#[error("Error while executing query in Opensearch")]
OpensearchError,
}
impl From<diesel::result::Error> for HealthCheckDBError {
fn from(error: diesel::result::Error) -> Self {
match error {
diesel::result::Error::DatabaseError(_, _) => Self::DBError,
diesel::result::Error::RollbackErrorOnCommit { .. }
| diesel::result::Error::RollbackTransaction
| diesel::result::Error::AlreadyInTransaction
| diesel::result::Error::NotInTransaction
| diesel::result::Error::BrokenTransactionManager => Self::TransactionError,
_ => Self::UnknownError,
}
}
}
#[derive(Debug, thiserror::Error)]
pub enum HealthCheckRedisError {
#[error("Failed to establish Redis connection")]
RedisConnectionError,
#[error("Failed to set key value in Redis")]
SetFailed,
#[error("Failed to get key value in Redis")]
GetFailed,
#[error("Failed to delete key value in Redis")]
DeleteFailed,
}
#[derive(Debug, Clone, thiserror::Error)]
pub enum HealthCheckLockerError {
#[error("Failed to establish Locker connection")]
FailedToCallLocker,
}
#[derive(Debug, Clone, thiserror::Error)]
pub enum HealthCheckGRPCServiceError {
#[error("Failed to establish connection with gRPC service")]
FailedToCallService,
}