use crate::{CountryCode, CurrencyCode, PaymentProvider};
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ProviderErrorDetails {
pub provider: PaymentProvider,
pub status: u16,
pub code: Option<String>,
pub request_id: Option<String>,
pub message: String,
}
#[derive(Debug, thiserror::Error)]
#[non_exhaustive]
pub enum PaymentError {
#[error("invalid amount: {0}")]
InvalidAmount(i64),
#[error("invalid currency code: {0}")]
InvalidCurrencyCode(String),
#[error("invalid country code: {0}")]
InvalidCountryCode(String),
#[error("invalid reference: {0}")]
InvalidReference(String),
#[error("invalid idempotency key: {0}")]
InvalidIdempotencyKey(String),
#[error("invalid phone number")]
InvalidPhoneNumber(String),
#[error("invalid url: {0}")]
InvalidUrl(String),
#[error("missing required field: {0}")]
MissingRequiredField(&'static str),
#[error("invalid configuration: {0}")]
InvalidConfiguration(String),
#[error("connector not configured: {provider:?}")]
ConnectorNotConfigured { provider: PaymentProvider },
#[error("unsupported payment method: {0}")]
UnsupportedPaymentMethod(String),
#[error("unsupported country: {0:?}")]
UnsupportedCountry(CountryCode),
#[error("unsupported currency: {0:?}")]
UnsupportedCurrency(CurrencyCode),
#[error("unsupported payment route: method={method}, country={country:?}")]
UnsupportedPaymentRoute {
method: String,
country: Option<CountryCode>,
},
#[error("provider authentication failed")]
AuthenticationFailed,
#[error("provider request failed: {provider:?}, status={status}, message={message}")]
ProviderRequestFailed {
provider: PaymentProvider,
status: u16,
message: String,
},
#[error("provider request failed: {details:?}")]
ProviderDetails {
details: ProviderErrorDetails,
},
#[error("provider unavailable: {0:?}")]
ProviderUnavailable(PaymentProvider),
#[error("rate limited by provider: {0:?}")]
RateLimited(PaymentProvider),
#[error("webhook verification failed")]
WebhookVerificationFailed,
#[error("webhook payload invalid: {0}")]
InvalidWebhookPayload(String),
#[error("operation not supported: {0}")]
UnsupportedOperation(String),
#[error("http error: {0}")]
Http(#[from] reqwest::Error),
#[error("json error: {0}")]
Json(#[from] serde_json::Error),
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn invalid_phone_error_does_not_display_value() {
let error = PaymentError::InvalidPhoneNumber("+260971234567".to_owned());
assert_eq!(error.to_string(), "invalid phone number");
}
}