better error handling
This commit is contained in:
parent
48339228ce
commit
a120bf67cc
|
@ -21,5 +21,4 @@ jsonwebtoken = "7"
|
||||||
base64 = "0.12"
|
base64 = "0.12"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
dotenv = "0.15.0"
|
dotenv = "0.15.0"
|
||||||
chrono = { version = "0.4", features = ["serde"] }
|
chrono = { version = "0.4", features = ["serde"] }
|
||||||
thiserror = "1.0"
|
|
|
@ -1,11 +1,40 @@
|
||||||
//! Errors created by this crate.
|
//! Errors created by this crate.
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::fmt;
|
||||||
|
use std::error::Error;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use thiserror::Error;
|
/// Represents a error HATEOAS link
|
||||||
|
#[derive(Debug, Serialize, Deserialize, Eq, PartialEq)]
|
||||||
|
pub struct ErrorLink {
|
||||||
|
href: String,
|
||||||
|
rel: String,
|
||||||
|
method: String,
|
||||||
|
}
|
||||||
|
|
||||||
/// A enum that represents the possible errors.
|
/// A paypal api response error.
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
pub enum Errors {
|
pub struct ApiResponseError {
|
||||||
/// A error used when a api call fails.
|
/// The error name.
|
||||||
#[error("failure when calling the paypal api")]
|
name: String,
|
||||||
ApiCallFailure(String),
|
/// The error message.
|
||||||
}
|
message: String,
|
||||||
|
/// Paypal debug id
|
||||||
|
debug_id: String,
|
||||||
|
/// Error details
|
||||||
|
details: Vec<HashMap<String, String>>,
|
||||||
|
/// Only available on Identity errors
|
||||||
|
error: Option<String>,
|
||||||
|
/// Only available on Identity errors
|
||||||
|
error_description: Option<String>,
|
||||||
|
/// Links with more information about the error.
|
||||||
|
links: Vec<ErrorLink>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for ApiResponseError {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
write!(f, "{:#?}", self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Error for ApiResponseError {}
|
|
@ -279,11 +279,10 @@ impl Client {
|
||||||
let token = res.json::<AccessToken>().await?;
|
let token = res.json::<AccessToken>().await?;
|
||||||
self.auth.expires = Some((Instant::now(), Duration::new(token.expires_in, 0)));
|
self.auth.expires = Some((Instant::now(), Duration::new(token.expires_in, 0)));
|
||||||
self.auth.access_token = Some(token);
|
self.auth.access_token = Some(token);
|
||||||
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
return Err(Box::new(errors::Errors::ApiCallFailure(res.text().await?)));
|
Err(Box::new(res.json::<errors::ApiResponseError>().await?))
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Checks if the access token expired.
|
/// Checks if the access token expired.
|
||||||
|
|
|
@ -311,6 +311,7 @@ pub struct Item {
|
||||||
pub category: Option<ItemCategoryType>,
|
pub category: Option<ItemCategoryType>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The status of the payment authorization.
|
||||||
#[derive(Debug, Serialize, Deserialize, Eq, PartialEq)]
|
#[derive(Debug, Serialize, Deserialize, Eq, PartialEq)]
|
||||||
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
|
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
|
||||||
pub enum AuthorizationStatus {
|
pub enum AuthorizationStatus {
|
||||||
|
@ -332,6 +333,7 @@ pub enum AuthorizationStatus {
|
||||||
Pending,
|
Pending,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Details about the status of the authorization.
|
||||||
#[derive(Debug, Serialize, Deserialize, Eq, PartialEq)]
|
#[derive(Debug, Serialize, Deserialize, Eq, PartialEq)]
|
||||||
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
|
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
|
||||||
pub enum AuthorizationStatusDetails {
|
pub enum AuthorizationStatusDetails {
|
||||||
|
@ -339,6 +341,7 @@ pub enum AuthorizationStatusDetails {
|
||||||
PendingReview,
|
PendingReview,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A payment authorization.
|
||||||
#[derive(Debug, Serialize, Deserialize, Eq, PartialEq)]
|
#[derive(Debug, Serialize, Deserialize, Eq, PartialEq)]
|
||||||
pub struct AuthorizationWithData {
|
pub struct AuthorizationWithData {
|
||||||
/// The status for the authorized payment.
|
/// The status for the authorized payment.
|
||||||
|
@ -347,6 +350,7 @@ pub struct AuthorizationWithData {
|
||||||
pub status_details: AuthorizationStatusDetails,
|
pub status_details: AuthorizationStatusDetails,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The capture status.
|
||||||
#[derive(Debug, Serialize, Deserialize, Eq, PartialEq)]
|
#[derive(Debug, Serialize, Deserialize, Eq, PartialEq)]
|
||||||
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
|
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
|
||||||
pub enum CaptureStatus {
|
pub enum CaptureStatus {
|
||||||
|
@ -362,6 +366,7 @@ pub enum CaptureStatus {
|
||||||
Refunded,
|
Refunded,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Details about the captured payment status.
|
||||||
#[derive(Debug, Serialize, Deserialize, Eq, PartialEq)]
|
#[derive(Debug, Serialize, Deserialize, Eq, PartialEq)]
|
||||||
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
|
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
|
||||||
pub enum CaptureStatusDetails {
|
pub enum CaptureStatusDetails {
|
||||||
|
@ -393,6 +398,7 @@ pub enum CaptureStatusDetails {
|
||||||
VerificationRequired,
|
VerificationRequired,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A captured payment.
|
||||||
#[derive(Debug, Serialize, Deserialize, Eq, PartialEq)]
|
#[derive(Debug, Serialize, Deserialize, Eq, PartialEq)]
|
||||||
pub struct Capture {
|
pub struct Capture {
|
||||||
/// The status of the captured payment.
|
/// The status of the captured payment.
|
||||||
|
@ -401,6 +407,7 @@ pub struct Capture {
|
||||||
pub status_details: CaptureStatusDetails,
|
pub status_details: CaptureStatusDetails,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The status of the refund
|
||||||
#[derive(Debug, Serialize, Deserialize, Eq, PartialEq)]
|
#[derive(Debug, Serialize, Deserialize, Eq, PartialEq)]
|
||||||
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
|
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
|
||||||
pub enum RefundStatus {
|
pub enum RefundStatus {
|
||||||
|
@ -420,6 +427,7 @@ pub enum RefundStatusDetails {
|
||||||
Echeck,
|
Echeck,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A refund
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
pub struct Refund {
|
pub struct Refund {
|
||||||
/// The status of the refund.
|
/// The status of the refund.
|
||||||
|
@ -428,6 +436,7 @@ pub struct Refund {
|
||||||
pub status_details: RefundStatusDetails,
|
pub status_details: RefundStatusDetails,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The comprehensive history of payments for the purchase unit.
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
pub struct PaymentCollection {
|
pub struct PaymentCollection {
|
||||||
/// An array of authorized payments for a purchase unit. A purchase unit can have zero or more authorized payments.
|
/// An array of authorized payments for a purchase unit. A purchase unit can have zero or more authorized payments.
|
||||||
|
@ -438,6 +447,7 @@ pub struct PaymentCollection {
|
||||||
pub refunds: Vec<Refund>,
|
pub refunds: Vec<Refund>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Represents either a full or partial order that the payer intends to purchase from the payee.
|
||||||
#[derive(Debug, Default, Serialize, Deserialize)]
|
#[derive(Debug, Default, Serialize, Deserialize)]
|
||||||
pub struct PurchaseUnit {
|
pub struct PurchaseUnit {
|
||||||
/// The API caller-provided external ID for the purchase unit. Required for multiple purchase units when you must update the order through PATCH.
|
/// The API caller-provided external ID for the purchase unit. Required for multiple purchase units when you must update the order through PATCH.
|
||||||
|
@ -488,11 +498,13 @@ pub struct PurchaseUnit {
|
||||||
/// The name and address of the person to whom to ship the items.
|
/// The name and address of the person to whom to ship the items.
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
pub shipping: Option<ShippingDetail>,
|
pub shipping: Option<ShippingDetail>,
|
||||||
|
/// The comprehensive history of payments for the purchase unit.
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
pub payments: Option<PaymentCollection>,
|
pub payments: Option<PaymentCollection>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PurchaseUnit {
|
impl PurchaseUnit {
|
||||||
|
/// Creates a new PurchaseUnit with the required properties.
|
||||||
pub fn new(amount: Amount) -> Self {
|
pub fn new(amount: Amount) -> Self {
|
||||||
Self {
|
Self {
|
||||||
amount,
|
amount,
|
||||||
|
@ -798,7 +810,7 @@ impl super::Client {
|
||||||
let order = res.json::<Order>().await?;
|
let order = res.json::<Order>().await?;
|
||||||
Ok(order)
|
Ok(order)
|
||||||
} else {
|
} else {
|
||||||
Err(Box::new(errors::Errors::ApiCallFailure(res.text().await?)))
|
Err(Box::new(res.json::<errors::ApiResponseError>().await?))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -826,7 +838,7 @@ impl super::Client {
|
||||||
let order = res.json::<Order>().await?;
|
let order = res.json::<Order>().await?;
|
||||||
Ok(order)
|
Ok(order)
|
||||||
} else {
|
} else {
|
||||||
Err(Box::new(errors::Errors::ApiCallFailure(res.text().await?)))
|
Err(Box::new(res.json::<errors::ApiResponseError>().await?))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -912,7 +924,7 @@ impl super::Client {
|
||||||
if res.status().is_success() {
|
if res.status().is_success() {
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
Err(Box::new(errors::Errors::ApiCallFailure(res.text().await?)))
|
Err(Box::new(res.json::<errors::ApiResponseError>().await?))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue