paddle_rust_sdk/
error.rs

1//! Error handling module for Paddle API client
2
3use std::error;
4use std::fmt;
5
6use chrono::Duration;
7use serde::Deserialize;
8
9use crate::ErrorResponse;
10
11/// Type of error encountered.
12#[derive(Debug, Deserialize)]
13#[serde(rename_all = "snake_case")]
14pub enum ErrorType {
15    /// Typically means there's a problem with the request that you made.
16    RequestError,
17    /// Typically means there's a problem with the Paddle API.
18    ApiError,
19}
20
21/// Error generated when validating webhook signatures
22#[derive(Debug)]
23pub enum SignatureError {
24    /// No signature provided
25    Empty,
26    /// Invalid signature format
27    InvalidFormat,
28    /// A part of the signature is invalid
29    InvalidPartFormat,
30    /// Unable to extract timestamp or signature
31    ParseError,
32    /// Generated when the signature was calculated earlier in time then allowed
33    MaxVarianceExceeded(Duration),
34}
35
36impl fmt::Display for SignatureError {
37    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
38        match self {
39            Self::Empty => write!(f, "empty string provided"),
40            Self::InvalidFormat => write!(f, "invalid format"),
41            Self::InvalidPartFormat => write!(f, "invalid signature part format"),
42            Self::ParseError => write!(f, "unable to extract timestamp or signature"),
43            Self::MaxVarianceExceeded(dur) => write!(f, "request was made more than {dur} ago"),
44        }
45    }
46}
47
48/// Error struct for a single invalid field.
49#[derive(Debug, Deserialize)]
50pub struct ValidationError {
51    /// Field where validation error occurred.
52    pub field: String,
53    /// Information about how the field failed validation.
54    pub message: String,
55}
56
57/// Error type returned from the Paddle API
58#[derive(Debug, Deserialize)]
59pub struct PaddleApiError {
60    /// Type of error encountered.
61    #[serde(rename = "type")]
62    pub error_type: ErrorType,
63    /// Short snake case string that describes this error. Use to search the error reference.
64    pub code: String,
65    /// Some information about what went wrong as a human-readable string.
66    pub detail: String,
67    /// Link to a page in the error reference for this specific error.
68    pub documentation_url: String,
69    /// List of validation errors.
70    pub errors: Option<Vec<ValidationError>>,
71}
72
73/// Paddle SDK Error type
74///
75/// If an error is generated anywhere in this crate, it will return this enum.
76#[derive(Debug)]
77pub enum Error {
78    Request(reqwest::Error),
79    Url(url::ParseError),
80    PaddleApi(ErrorResponse),
81    QueryString(serde_qs::Error),
82    PaddleSignature(SignatureError),
83    ParseIntError(std::num::ParseIntError),
84    MacError(hmac::digest::MacError),
85    JsonError(serde_json::Error),
86}
87
88impl fmt::Display for Error {
89    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
90        match self {
91            Self::Request(err) => write!(f, "Request error: {}", err),
92            Self::Url(err) => write!(f, "URL error: {}", err),
93            Self::PaddleApi(err) => write!(f, "Paddle error: {}", err.error.detail),
94            Self::QueryString(err) => write!(f, "Query string error: {}", err),
95            Self::PaddleSignature(err) => write!(f, "Paddle signature error: {}", err),
96            Self::ParseIntError(err) => write!(f, "Integer parsing error: {}", err),
97            Self::MacError(err) => write!(f, "Hmac error: {}", err),
98            Self::JsonError(err) => write!(f, "Serde json error: {}", err),
99        }
100    }
101}
102
103impl error::Error for Error {
104    fn source(&self) -> Option<&(dyn error::Error + 'static)> {
105        match self {
106            Self::Request(err) => Some(err),
107            Self::Url(err) => Some(err),
108            Self::PaddleApi(_) => None,
109            Self::QueryString(err) => Some(err),
110            Self::PaddleSignature(_) => None,
111            Self::ParseIntError(err) => Some(err),
112            Self::MacError(err) => Some(err),
113            Self::JsonError(err) => Some(err),
114        }
115    }
116}
117
118impl From<reqwest::Error> for Error {
119    fn from(err: reqwest::Error) -> Self {
120        Self::Request(err)
121    }
122}
123
124impl From<url::ParseError> for Error {
125    fn from(err: url::ParseError) -> Self {
126        Self::Url(err)
127    }
128}
129
130impl From<serde_qs::Error> for Error {
131    fn from(err: serde_qs::Error) -> Self {
132        Self::QueryString(err)
133    }
134}
135
136impl From<std::num::ParseIntError> for Error {
137    fn from(err: std::num::ParseIntError) -> Self {
138        Self::ParseIntError(err)
139    }
140}
141
142impl From<hmac::digest::MacError> for Error {
143    fn from(err: hmac::digest::MacError) -> Self {
144        Self::MacError(err)
145    }
146}
147
148impl From<serde_json::Error> for Error {
149    fn from(value: serde_json::Error) -> Self {
150        Self::JsonError(value)
151    }
152}