change the way sandbox is handled, allow to provide a mock server url
This commit is contained in:
parent
556ec2edeb
commit
2b23f6a8db
11
Cargo.toml
11
Cargo.toml
|
@ -1,12 +1,12 @@
|
||||||
[package]
|
[package]
|
||||||
name = "paypal-rs"
|
name = "paypal-rs"
|
||||||
version = "0.2.2"
|
version = "0.2.3"
|
||||||
authors = ["Edgar <git@edgarluque.com>"]
|
authors = ["Edgar <git@edgarluque.com>"]
|
||||||
description = "A library that wraps the paypal api asynchronously."
|
description = "A library that wraps the paypal api asynchronously."
|
||||||
repository = "https://github.com/edg-l/paypal-rs/"
|
repository = "https://github.com/edg-l/paypal-rs/"
|
||||||
license = "MIT OR Apache-2.0"
|
license = "MIT OR Apache-2.0"
|
||||||
keywords = ["paypal", "api", "async"]
|
keywords = ["paypal", "paypal-api"]
|
||||||
categories = ["api-bindings"]
|
categories = ["api-bindings", "web-programming::http-client"]
|
||||||
documentation = "https://docs.rs/paypal-rs"
|
documentation = "https://docs.rs/paypal-rs"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
@ -14,7 +14,7 @@ edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
reqwest = { version = "0.11.12", default-features = false, features = ["json"] }
|
reqwest = { version = "0.11.12", default-features = false, features = ["json"] }
|
||||||
serde = { version = "1.0.144", features = ["derive"] }
|
serde = { version = "1.0.145", features = ["derive"] }
|
||||||
serde_json = "1.0.85"
|
serde_json = "1.0.85"
|
||||||
serde_with = "2.0.1"
|
serde_with = "2.0.1"
|
||||||
chrono = { version = "0.4.22", features = ["serde"] }
|
chrono = { version = "0.4.22", features = ["serde"] }
|
||||||
|
@ -26,10 +26,11 @@ derive_builder = "0.11.2"
|
||||||
serde_qs = "0.10.1"
|
serde_qs = "0.10.1"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
tokio = { version = "1.21.1", features = ["macros", "rt-multi-thread"] }
|
tokio = { version = "1.21.2", features = ["macros", "rt-multi-thread"] }
|
||||||
dotenv = "0.15.0"
|
dotenv = "0.15.0"
|
||||||
anyhow = "1.0.65"
|
anyhow = "1.0.65"
|
||||||
color-eyre = "0.6.2"
|
color-eyre = "0.6.2"
|
||||||
|
wiremock = "0.5.14"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["reqwest/native-tls"]
|
default = ["reqwest/native-tls"]
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use color_eyre::Result;
|
use color_eyre::Result;
|
||||||
use paypal_rs::data::invoice::*;
|
use paypal_rs::data::invoice::*;
|
||||||
use paypal_rs::{api::invoice::*, data::common::Money};
|
use paypal_rs::{api::invoice::*, data::common::Money, PaypalEnv};
|
||||||
use paypal_rs::{data::common::Currency, Client};
|
use paypal_rs::{data::common::Currency, Client};
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
|
@ -11,7 +11,7 @@ async fn main() -> Result<()> {
|
||||||
let clientid = std::env::var("PAYPAL_CLIENTID")?;
|
let clientid = std::env::var("PAYPAL_CLIENTID")?;
|
||||||
let secret = std::env::var("PAYPAL_SECRET")?;
|
let secret = std::env::var("PAYPAL_SECRET")?;
|
||||||
|
|
||||||
let mut client = Client::new(clientid, secret, true);
|
let mut client = Client::new(clientid, secret, PaypalEnv::Sandbox);
|
||||||
client.get_access_token().await?;
|
client.get_access_token().await?;
|
||||||
|
|
||||||
let payload = InvoicePayloadBuilder::default()
|
let payload = InvoicePayloadBuilder::default()
|
||||||
|
|
|
@ -401,7 +401,7 @@ mod tests {
|
||||||
let clientid = std::env::var("PAYPAL_CLIENTID").unwrap();
|
let clientid = std::env::var("PAYPAL_CLIENTID").unwrap();
|
||||||
let secret = std::env::var("PAYPAL_SECRET").unwrap();
|
let secret = std::env::var("PAYPAL_SECRET").unwrap();
|
||||||
|
|
||||||
let mut client = Client::new(clientid, secret, true);
|
let mut client = Client::new(clientid, secret, crate::PaypalEnv::Sandbox);
|
||||||
client.get_access_token().await.unwrap();
|
client.get_access_token().await.unwrap();
|
||||||
client
|
client
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ use crate::{
|
||||||
/// Represents the access token returned by the OAuth2 authentication.
|
/// Represents the access token returned by the OAuth2 authentication.
|
||||||
///
|
///
|
||||||
/// <https://developer.paypal.com/docs/api/get-an-access-token-postman/>
|
/// <https://developer.paypal.com/docs/api/get-an-access-token-postman/>
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
pub struct AccessToken {
|
pub struct AccessToken {
|
||||||
/// The OAuth2 scopes.
|
/// The OAuth2 scopes.
|
||||||
pub scope: String,
|
pub scope: String,
|
||||||
|
@ -31,7 +31,7 @@ pub struct AccessToken {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Stores OAuth2 information.
|
/// Stores OAuth2 information.
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
pub struct Auth {
|
pub struct Auth {
|
||||||
/// Your client id.
|
/// Your client id.
|
||||||
pub client_id: String,
|
pub client_id: String,
|
||||||
|
@ -44,16 +44,44 @@ pub struct Auth {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Represents a client used to interact with the paypal api.
|
/// Represents a client used to interact with the paypal api.
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Client {
|
pub struct Client {
|
||||||
/// Internal http client
|
/// Internal http client
|
||||||
pub(crate) client: reqwest::Client,
|
pub(crate) client: reqwest::Client,
|
||||||
/// Whether you are or not in a sandbox enviroment.
|
/// Whether you are or not in a sandbox enviroment.
|
||||||
pub sandbox: bool,
|
pub env: PaypalEnv,
|
||||||
/// Api Auth information
|
/// Api Auth information
|
||||||
pub auth: Auth,
|
pub auth: Auth,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The paypal api environment.
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
|
pub enum PaypalEnv {
|
||||||
|
/// The live environment.
|
||||||
|
Live,
|
||||||
|
/// The sandbox environment.
|
||||||
|
Sandbox,
|
||||||
|
/// For mocking.
|
||||||
|
Mock(String),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PaypalEnv {
|
||||||
|
/// Returns the endpoint of this environment.
|
||||||
|
pub fn endpoint(&self) -> &str {
|
||||||
|
match &self {
|
||||||
|
PaypalEnv::Live => LIVE_ENDPOINT,
|
||||||
|
PaypalEnv::Sandbox => SANDBOX_ENDPOINT,
|
||||||
|
PaypalEnv::Mock(endpoint) => endpoint.as_str(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Constructs a url from the target.
|
||||||
|
pub fn make_url(&self, target: &str) -> String {
|
||||||
|
assert!(target.starts_with('/'), "target path must start with '/'");
|
||||||
|
format!("{}{}", self.endpoint(), target)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Client {
|
impl Client {
|
||||||
/// Returns a new client, you must get_access_token afterwards to interact with the api.
|
/// Returns a new client, you must get_access_token afterwards to interact with the api.
|
||||||
///
|
///
|
||||||
|
@ -76,10 +104,10 @@ impl Client {
|
||||||
/// client.get_access_token().await.unwrap();
|
/// client.get_access_token().await.unwrap();
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
pub fn new(client_id: String, secret: String, sandbox: bool) -> Client {
|
pub fn new(client_id: String, secret: String, env: PaypalEnv) -> Client {
|
||||||
Client {
|
Client {
|
||||||
client: reqwest::Client::new(),
|
client: reqwest::Client::new(),
|
||||||
sandbox,
|
env,
|
||||||
auth: Auth {
|
auth: Auth {
|
||||||
client_id,
|
client_id,
|
||||||
secret,
|
secret,
|
||||||
|
@ -89,14 +117,6 @@ impl Client {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn endpoint(&self) -> &str {
|
|
||||||
if self.sandbox {
|
|
||||||
SANDBOX_ENDPOINT
|
|
||||||
} else {
|
|
||||||
LIVE_ENDPOINT
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Sets up the request headers as required on https://developer.paypal.com/docs/api/reference/api-requests/#http-request-headers
|
/// Sets up the request headers as required on https://developer.paypal.com/docs/api/reference/api-requests/#http-request-headers
|
||||||
async fn setup_headers(
|
async fn setup_headers(
|
||||||
&self,
|
&self,
|
||||||
|
@ -158,7 +178,7 @@ impl Client {
|
||||||
}
|
}
|
||||||
let res = self
|
let res = self
|
||||||
.client
|
.client
|
||||||
.post(format!("{}/v1/oauth2/token", self.endpoint()).as_str())
|
.post(self.env.make_url("/v1/oauth2/token"))
|
||||||
.basic_auth(&self.auth.client_id, Some(&self.auth.secret))
|
.basic_auth(&self.auth.client_id, Some(&self.auth.secret))
|
||||||
.header("Content-Type", "x-www-form-urlencoded")
|
.header("Content-Type", "x-www-form-urlencoded")
|
||||||
.header("Accept", "application/json")
|
.header("Accept", "application/json")
|
||||||
|
@ -193,7 +213,7 @@ impl Client {
|
||||||
where
|
where
|
||||||
E: Endpoint,
|
E: Endpoint,
|
||||||
{
|
{
|
||||||
let mut url = endpoint.full_path(self.sandbox);
|
let mut url = self.env.make_url(&endpoint.relative_path());
|
||||||
|
|
||||||
if let Some(query) = endpoint.query() {
|
if let Some(query) = endpoint.query() {
|
||||||
let query_string = serde_qs::to_string(&query).expect("serialize the query correctly");
|
let query_string = serde_qs::to_string(&query).expect("serialize the query correctly");
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
//! This module contains the endpoint trait used to implemented api endpoints.
|
//! This module contains the endpoint trait used to implemented api endpoints.
|
||||||
|
|
||||||
use crate::{LIVE_ENDPOINT, SANDBOX_ENDPOINT};
|
use crate::{LIVE_ENDPOINT, SANDBOX_ENDPOINT, PaypalEnv};
|
||||||
use serde::{de::DeserializeOwned, Serialize};
|
use serde::{de::DeserializeOwned, Serialize};
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
|
||||||
|
@ -28,19 +28,4 @@ pub trait Endpoint {
|
||||||
fn body(&self) -> Option<Self::Body> {
|
fn body(&self) -> Option<Self::Body> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The full path of this endpoint.
|
|
||||||
///
|
|
||||||
/// Automatically implemented.
|
|
||||||
fn full_path(&self, is_sandbox: bool) -> String {
|
|
||||||
let relative_path = self.relative_path();
|
|
||||||
|
|
||||||
assert!(relative_path.starts_with('/'), "relative path must start with '/'");
|
|
||||||
|
|
||||||
if is_sandbox {
|
|
||||||
format!("{}{}", SANDBOX_ENDPOINT, relative_path)
|
|
||||||
} else {
|
|
||||||
format!("{}{}", LIVE_ENDPOINT, relative_path)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -184,7 +184,7 @@ mod tests {
|
||||||
let clientid = env::var("PAYPAL_CLIENTID").unwrap();
|
let clientid = env::var("PAYPAL_CLIENTID").unwrap();
|
||||||
let secret = env::var("PAYPAL_SECRET").unwrap();
|
let secret = env::var("PAYPAL_SECRET").unwrap();
|
||||||
|
|
||||||
Client::new(clientid, secret, true)
|
Client::new(clientid, secret, crate::PaypalEnv::Sandbox)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
Loading…
Reference in a new issue