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