Skip to main content

lockbook_server_lib/billing/
stripe_error.rs

1use tracing::*;
2
3use super::stripe_model::{StripeDeclineCodeCatcher, StripeKnownDeclineCode};
4
5#[derive(Debug)]
6pub enum SimplifiedStripeError {
7    CardDecline,
8    InsufficientFunds,
9    TryAgain,
10    CardNotSupported,
11    ExpiredCard,
12    InvalidCardNumber,
13    InvalidCardExpYear,
14    InvalidCardExpMonth,
15    InvalidCardCvc,
16    Other(String),
17}
18
19impl From<stripe::StripeError> for SimplifiedStripeError {
20    fn from(error: stripe::StripeError) -> Self {
21        debug!(?error, "Stripe error");
22
23        match error {
24            stripe::StripeError::Stripe(stripe_error) => {
25                simplify_stripe_error(stripe_error.code, stripe_error.decline_code)
26            }
27            _ => SimplifiedStripeError::Other(format!("Unexpected stripe error: {error:?}")),
28        }
29    }
30}
31
32fn simplify_stripe_error(
33    error_code: Option<stripe::ErrorCode>, maybe_decline_code: Option<String>,
34) -> SimplifiedStripeError {
35    match error_code {
36        None => SimplifiedStripeError::Other(format!(
37            "Stripe error with no details: error_code: {error_code:?}, decline_code: {maybe_decline_code:?}"
38        )),
39        Some(error_code) => match error_code {
40            stripe::ErrorCode::BalanceInsufficient => SimplifiedStripeError::InsufficientFunds,
41            stripe::ErrorCode::CardDeclined => match maybe_decline_code {
42                None => SimplifiedStripeError::CardDecline,
43                Some(decline_code) => {
44                    match serde_json::from_str::<StripeDeclineCodeCatcher>(&format!(
45                        "\"{decline_code}\""
46                    ))
47                    .map_err(|e| {
48                        SimplifiedStripeError::Other(format!(
49                            "An error was encountered while serializing decline code: {e:?}"
50                        ))
51                    }) {
52                        Ok(StripeDeclineCodeCatcher::Unknown(code)) => {
53                            warn!(?code, "Unknown decline code from stripe");
54                            SimplifiedStripeError::CardDecline
55                        }
56                        Ok(StripeDeclineCodeCatcher::Known(decline_code)) => match decline_code {
57                            // Try again
58                            StripeKnownDeclineCode::ApproveWithId
59                            | StripeKnownDeclineCode::IssuerNotAvailable
60                            | StripeKnownDeclineCode::ProcessingError
61                            | StripeKnownDeclineCode::ReenterTransaction
62                            | StripeKnownDeclineCode::TryAgainLater => {
63                                SimplifiedStripeError::TryAgain
64                            }
65
66                            // Not supported
67                            StripeKnownDeclineCode::CardNotSupported
68                            | StripeKnownDeclineCode::CurrencyNotSupported => {
69                                SimplifiedStripeError::CardNotSupported
70                            }
71
72                            // Balance or credit exceeded
73                            StripeKnownDeclineCode::CardVelocityExceeded
74                            | StripeKnownDeclineCode::InsufficientFunds
75                            | StripeKnownDeclineCode::WithdrawalCountLimitExceeded => {
76                                SimplifiedStripeError::InsufficientFunds
77                            }
78
79                            // Expired card
80                            StripeKnownDeclineCode::ExpiredCard => {
81                                SimplifiedStripeError::ExpiredCard
82                            }
83
84                            // Generic
85                            StripeKnownDeclineCode::CallIssuer
86                            | StripeKnownDeclineCode::DoNotTryAgain
87                            | StripeKnownDeclineCode::DoNotHonor
88                            | StripeKnownDeclineCode::NewAccountInformationAvailable
89                            | StripeKnownDeclineCode::RestrictedCard
90                            | StripeKnownDeclineCode::RevocationOfAllAuthorizations
91                            | StripeKnownDeclineCode::RevocationOfAuthorization
92                            | StripeKnownDeclineCode::SecurityViolation
93                            | StripeKnownDeclineCode::ServiceNotAllowed
94                            | StripeKnownDeclineCode::StopPaymentOrder
95                            | StripeKnownDeclineCode::TransactionNotAllowed
96                            | StripeKnownDeclineCode::Fraudulent
97                            | StripeKnownDeclineCode::GenericDecline
98                            | StripeKnownDeclineCode::LostCard
99                            | StripeKnownDeclineCode::MerchantBlacklist
100                            | StripeKnownDeclineCode::NoActionTaken
101                            | StripeKnownDeclineCode::NotPermitted
102                            | StripeKnownDeclineCode::PickupCard
103                            | StripeKnownDeclineCode::StolenCard => {
104                                SimplifiedStripeError::CardDecline
105                            }
106
107                            // Incorrect number
108                            StripeKnownDeclineCode::IncorrectNumber
109                            | StripeKnownDeclineCode::InvalidNumber => {
110                                SimplifiedStripeError::InvalidCardNumber
111                            }
112
113                            // Incorrect cvc
114                            StripeKnownDeclineCode::IncorrectCvc
115                            | StripeKnownDeclineCode::InvalidCvc => {
116                                SimplifiedStripeError::InvalidCardCvc
117                            }
118
119                            // Incorrect expiry month
120                            StripeKnownDeclineCode::InvalidExpiryMonth => {
121                                SimplifiedStripeError::InvalidCardExpMonth
122                            }
123
124                            // Incorrect expiry year
125                            StripeKnownDeclineCode::InvalidExpiryYear => {
126                                SimplifiedStripeError::InvalidCardExpYear
127                            }
128                        },
129                        Err(e) => e,
130                    }
131                }
132            },
133            stripe::ErrorCode::ExpiredCard => SimplifiedStripeError::ExpiredCard,
134            stripe::ErrorCode::InvalidCardType => SimplifiedStripeError::CardNotSupported,
135            stripe::ErrorCode::InvalidCvc | stripe::ErrorCode::IncorrectCvc => {
136                SimplifiedStripeError::InvalidCardCvc
137            }
138            stripe::ErrorCode::InvalidExpiryMonth => SimplifiedStripeError::InvalidCardExpMonth,
139            stripe::ErrorCode::InvalidExpiryYear => SimplifiedStripeError::InvalidCardExpYear,
140            stripe::ErrorCode::InvalidNumber | stripe::ErrorCode::IncorrectNumber => {
141                SimplifiedStripeError::InvalidCardNumber
142            }
143            stripe::ErrorCode::ProcessingError => SimplifiedStripeError::TryAgain,
144            _ => SimplifiedStripeError::Other(format!("Unexpected error code: {error_code:?}")),
145        },
146    }
147}