some fixes
This commit is contained in:
parent
89b1fdf113
commit
a4c4838aaf
|
@ -4,7 +4,7 @@
|
||||||
//! Customers with a PayPal account can log in and pay the invoice with PayPal. Alternatively,
|
//! Customers with a PayPal account can log in and pay the invoice with PayPal. Alternatively,
|
||||||
//! customers can pay as a guest with a debit card or credit card. For more information, see the Invoicing Overview and the Invoicing Integration Guide.
|
//! customers can pay as a guest with a debit card or credit card. For more information, see the Invoicing Overview and the Invoicing Integration Guide.
|
||||||
//!
|
//!
|
||||||
//! Reference: https://developer.paypal.com/docs/api/invoicing/v2/
|
//! Reference: <https://developer.paypal.com/docs/api/invoicing/v2/>
|
||||||
|
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
|
||||||
|
@ -53,8 +53,8 @@ impl Endpoint for GenerateInvoiceNumber {
|
||||||
reqwest::Method::POST
|
reqwest::Method::POST
|
||||||
}
|
}
|
||||||
|
|
||||||
fn body(&self) -> Option<&Self::Body> {
|
fn body(&self) -> Option<Self::Body> {
|
||||||
Some(&self.invoice_number)
|
Some(self.invoice_number.clone())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,8 +88,8 @@ impl Endpoint for CreateDraftInvoice {
|
||||||
reqwest::Method::POST
|
reqwest::Method::POST
|
||||||
}
|
}
|
||||||
|
|
||||||
fn body(&self) -> Option<&Self::Body> {
|
fn body(&self) -> Option<Self::Body> {
|
||||||
Some(&self.invoice)
|
Some(self.invoice.clone())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -153,8 +153,8 @@ impl Endpoint for ListInvoices {
|
||||||
reqwest::Method::GET
|
reqwest::Method::GET
|
||||||
}
|
}
|
||||||
|
|
||||||
fn query(&self) -> Option<&Self::Query> {
|
fn query(&self) -> Option<Self::Query> {
|
||||||
Some(&self.query)
|
Some(self.query.clone())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -234,12 +234,12 @@ impl Endpoint for UpdateInvoice {
|
||||||
reqwest::Method::PUT
|
reqwest::Method::PUT
|
||||||
}
|
}
|
||||||
|
|
||||||
fn body(&self) -> Option<&Self::Body> {
|
fn body(&self) -> Option<Self::Body> {
|
||||||
Some(&self.invoice)
|
Some(self.invoice.clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn query(&self) -> Option<&Self::Query> {
|
fn query(&self) -> Option<Self::Query> {
|
||||||
Some(&self.query)
|
Some(self.query.clone())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -274,8 +274,8 @@ impl Endpoint for CancelInvoice {
|
||||||
reqwest::Method::POST
|
reqwest::Method::POST
|
||||||
}
|
}
|
||||||
|
|
||||||
fn body(&self) -> Option<&Self::Body> {
|
fn body(&self) -> Option<Self::Body> {
|
||||||
Some(&self.reason)
|
Some(self.reason.clone())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -383,7 +383,7 @@ mod tests {
|
||||||
|
|
||||||
let invoice = CreateDraftInvoice::new(payload);
|
let invoice = CreateDraftInvoice::new(payload);
|
||||||
|
|
||||||
let res = client.execute(&invoice).await?;
|
let _res = client.execute(&invoice).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
//! An order represents a payment between two or more parties. Use the Orders API to create, update, retrieve, authorize, and capture orders.
|
//! An order represents a payment between two or more parties. Use the Orders API to create, update, retrieve, authorize, and capture orders.
|
||||||
//!
|
//!
|
||||||
//! https://developer.paypal.com/docs/api/orders/v2/
|
//! <https://developer.paypal.com/docs/api/orders/v2/>
|
||||||
|
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
|
||||||
|
@ -41,8 +41,8 @@ impl Endpoint for CreateOrder {
|
||||||
reqwest::Method::POST
|
reqwest::Method::POST
|
||||||
}
|
}
|
||||||
|
|
||||||
fn body(&self) -> Option<&Self::Body> {
|
fn body(&self) -> Option<Self::Body> {
|
||||||
Some(&self.order)
|
Some(self.order.clone())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,10 +97,11 @@ pub struct PaymentSource {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The capture order endpoint body.
|
/// The capture order endpoint body.
|
||||||
#[derive(Debug, Serialize, Clone)]
|
#[derive(Debug, Serialize, Clone, Default)]
|
||||||
pub struct PaymentSourceBody {
|
pub struct PaymentSourceBody {
|
||||||
/// The payment source definition.
|
/// The payment source definition.
|
||||||
pub payment_source: PaymentSource,
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub payment_source: Option<PaymentSource>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Captures payment for an order. To successfully capture payment for an order,
|
/// Captures payment for an order. To successfully capture payment for an order,
|
||||||
|
@ -111,7 +112,7 @@ pub struct CaptureOrder {
|
||||||
/// The id of the order.
|
/// The id of the order.
|
||||||
pub order_id: String,
|
pub order_id: String,
|
||||||
/// The endpoint body.
|
/// The endpoint body.
|
||||||
pub body: Option<PaymentSourceBody>,
|
pub body: PaymentSourceBody,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CaptureOrder {
|
impl CaptureOrder {
|
||||||
|
@ -119,7 +120,7 @@ impl CaptureOrder {
|
||||||
pub fn new(order_id: &str) -> Self {
|
pub fn new(order_id: &str) -> Self {
|
||||||
Self {
|
Self {
|
||||||
order_id: order_id.to_string(),
|
order_id: order_id.to_string(),
|
||||||
body: None,
|
body: PaymentSourceBody::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -139,8 +140,8 @@ impl Endpoint for CaptureOrder {
|
||||||
reqwest::Method::POST
|
reqwest::Method::POST
|
||||||
}
|
}
|
||||||
|
|
||||||
fn body(&self) -> Option<&Self::Body> {
|
fn body(&self) -> Option<Self::Body> {
|
||||||
self.body.as_ref()
|
Some(self.body.clone())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -152,7 +153,7 @@ pub struct AuthorizeOrder {
|
||||||
/// The order id.
|
/// The order id.
|
||||||
order_id: String,
|
order_id: String,
|
||||||
/// The endpoint body.
|
/// The endpoint body.
|
||||||
pub body: Option<PaymentSourceBody>,
|
pub body: PaymentSourceBody,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AuthorizeOrder {
|
impl AuthorizeOrder {
|
||||||
|
@ -160,7 +161,7 @@ impl AuthorizeOrder {
|
||||||
pub fn new(order_id: &str) -> Self {
|
pub fn new(order_id: &str) -> Self {
|
||||||
Self {
|
Self {
|
||||||
order_id: order_id.to_string(),
|
order_id: order_id.to_string(),
|
||||||
body: None,
|
body: PaymentSourceBody::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -180,8 +181,8 @@ impl Endpoint for AuthorizeOrder {
|
||||||
reqwest::Method::POST
|
reqwest::Method::POST
|
||||||
}
|
}
|
||||||
|
|
||||||
fn body(&self) -> Option<&Self::Body> {
|
fn body(&self) -> Option<Self::Body> {
|
||||||
self.body.as_ref()
|
Some(self.body.clone())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -194,7 +195,7 @@ mod tests {
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_order() -> anyhow::Result<()> {
|
async fn test_order() -> anyhow::Result<()> {
|
||||||
let mut client = create_client().await;
|
let mut client = create_client().await;
|
||||||
client.get_access_token().await?;
|
client.get_access_token().await.expect("get access token error");
|
||||||
|
|
||||||
let order = OrderPayloadBuilder::default()
|
let order = OrderPayloadBuilder::default()
|
||||||
.intent(Intent::Authorize)
|
.intent(Intent::Authorize)
|
||||||
|
@ -219,7 +220,11 @@ mod tests {
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.await?;
|
.await;
|
||||||
|
|
||||||
|
assert!(order_created.is_ok());
|
||||||
|
|
||||||
|
let order_created = order_created?;
|
||||||
|
|
||||||
assert_ne!(order_created.id, "");
|
assert_ne!(order_created.id, "");
|
||||||
assert_eq!(order_created.status, OrderStatus::Created);
|
assert_eq!(order_created.status, OrderStatus::Created);
|
||||||
|
@ -235,14 +240,19 @@ mod tests {
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.await?;
|
.await;
|
||||||
|
|
||||||
|
assert!(show_order_result.is_ok());
|
||||||
|
|
||||||
|
let show_order_result = show_order_result?;
|
||||||
|
|
||||||
assert_eq!(order_created.id, show_order_result.id);
|
assert_eq!(order_created.id, show_order_result.id);
|
||||||
assert_eq!(order_created.status, show_order_result.status);
|
assert_eq!(order_created.status, show_order_result.status);
|
||||||
|
|
||||||
let capture_order = CaptureOrder::new(&show_order_result.id);
|
let authorize_order = AuthorizeOrder::new(&show_order_result.id);
|
||||||
|
|
||||||
let _res = client.execute(&capture_order).await?;
|
let res = client.execute(&authorize_order).await;
|
||||||
|
assert!(res.is_err()); // Fails with ORDER_NOT_APPROVED
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
//! Call the Payments API to authorize payments, capture authorized payments, refund payments that have already been captured, and show payment information.
|
//! Call the Payments API to authorize payments, capture authorized payments, refund payments that have already been captured, and show payment information.
|
||||||
//!
|
//!
|
||||||
//! Reference: https://developer.paypal.com/docs/api/payments/v2/
|
//! Reference: <https://developer.paypal.com/docs/api/payments/v2/>
|
||||||
|
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
|
||||||
|
@ -42,8 +42,4 @@ impl Endpoint for GetAuthorizedPayment {
|
||||||
fn method(&self) -> reqwest::Method {
|
fn method(&self) -> reqwest::Method {
|
||||||
reqwest::Method::GET
|
reqwest::Method::GET
|
||||||
}
|
}
|
||||||
|
|
||||||
fn body(&self) -> Option<&Self::Body> {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,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)]
|
||||||
pub struct AccessToken {
|
pub struct AccessToken {
|
||||||
/// The OAuth2 scopes.
|
/// The OAuth2 scopes.
|
||||||
|
@ -196,7 +196,7 @@ impl Client {
|
||||||
let mut url = endpoint.full_path(self.sandbox);
|
let mut url = endpoint.full_path(self.sandbox);
|
||||||
|
|
||||||
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");
|
||||||
url.push_str(&query_string);
|
url.push_str(&query_string);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -204,7 +204,7 @@ impl Client {
|
||||||
request = self.setup_headers(request, headers).await?;
|
request = self.setup_headers(request, headers).await?;
|
||||||
|
|
||||||
if let Some(body) = endpoint.body() {
|
if let Some(body) = endpoint.body() {
|
||||||
request = request.json(body);
|
request = request.json(&body);
|
||||||
}
|
}
|
||||||
|
|
||||||
let res = request.send().await?;
|
let res = request.send().await?;
|
||||||
|
@ -225,7 +225,7 @@ impl Client {
|
||||||
|
|
||||||
/// Executes the given endpoints with the default headers.
|
/// Executes the given endpoints with the default headers.
|
||||||
///
|
///
|
||||||
/// You must remember to call `get_access_token` first or this may fail due to not being authed.
|
/// You must remember to call [Client::get_access_token] first or this may fail due to not being authed.
|
||||||
pub async fn execute<E>(&self, endpoint: &E) -> Result<E::Response, ResponseError>
|
pub async fn execute<E>(&self, endpoint: &E) -> Result<E::Response, ResponseError>
|
||||||
where
|
where
|
||||||
E: Endpoint,
|
E: Endpoint,
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
//! Generated using https://github.com/edg-l/payhelper
|
//! Generated using <https://github.com/edg-l/payhelper>
|
||||||
|
|
||||||
use crate::errors::InvalidCountryError;
|
use crate::errors::InvalidCountryError;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
|
@ -8,7 +8,7 @@ use std::str::FromStr;
|
||||||
|
|
||||||
/// The phone type.
|
/// The phone type.
|
||||||
///
|
///
|
||||||
/// https://developer.paypal.com/docs/api/orders/v2/#definition-phone_with_type
|
/// <https://developer.paypal.com/docs/api/orders/v2/#definition-phone_with_type>
|
||||||
#[derive(Debug, Serialize, Deserialize, Eq, PartialEq, Copy, Clone)]
|
#[derive(Debug, Serialize, Deserialize, Eq, PartialEq, Copy, Clone)]
|
||||||
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
|
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
|
||||||
#[allow(missing_docs)]
|
#[allow(missing_docs)]
|
||||||
|
|
|
@ -569,7 +569,7 @@ pub struct InvoicePayload {
|
||||||
pub refunds: Option<Refunds>,
|
pub refunds: Option<Refunds>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Definition: https://developer.paypal.com/docs/api/invoicing/v2/#invoices_get
|
/// Definition: <https://developer.paypal.com/docs/api/invoicing/v2/#invoices_get>
|
||||||
#[skip_serializing_none]
|
#[skip_serializing_none]
|
||||||
#[derive(Debug, Serialize, Deserialize, Clone, Builder)]
|
#[derive(Debug, Serialize, Deserialize, Clone, Builder)]
|
||||||
#[builder(setter(strip_option, into))]
|
#[builder(setter(strip_option, into))]
|
||||||
|
|
|
@ -27,7 +27,7 @@ impl Default for Intent {
|
||||||
|
|
||||||
/// Represents a payer name.
|
/// Represents a payer name.
|
||||||
///
|
///
|
||||||
/// https://developer.paypal.com/docs/api/orders/v2/#definition-payer.name
|
/// <https://developer.paypal.com/docs/api/orders/v2/#definition-payer.name>
|
||||||
#[derive(Debug, Serialize, Deserialize, Eq, PartialEq, Clone)]
|
#[derive(Debug, Serialize, Deserialize, Eq, PartialEq, Clone)]
|
||||||
pub struct PayerName {
|
pub struct PayerName {
|
||||||
/// When the party is a person, the party's given, or first, name.
|
/// When the party is a person, the party's given, or first, name.
|
||||||
|
@ -80,7 +80,7 @@ pub struct TaxInfo {
|
||||||
|
|
||||||
/// The customer who approves and pays for the order. The customer is also known as the payer.
|
/// The customer who approves and pays for the order. The customer is also known as the payer.
|
||||||
///
|
///
|
||||||
/// https://developer.paypal.com/docs/api/orders/v2/#definition-payer
|
/// <https://developer.paypal.com/docs/api/orders/v2/#definition-payer>
|
||||||
#[skip_serializing_none]
|
#[skip_serializing_none]
|
||||||
#[derive(Debug, Default, Serialize, Deserialize, Clone, Builder)]
|
#[derive(Debug, Default, Serialize, Deserialize, Clone, Builder)]
|
||||||
pub struct Payer {
|
pub struct Payer {
|
||||||
|
@ -428,7 +428,7 @@ pub struct PurchaseUnit {
|
||||||
pub id: Option<String>,
|
pub id: Option<String>,
|
||||||
/// The soft descriptor is the dynamic text used to construct the statement descriptor that appears on a payer's card statement.
|
/// The soft descriptor is the dynamic text used to construct the statement descriptor that appears on a payer's card statement.
|
||||||
///
|
///
|
||||||
/// More info here: https://developer.paypal.com/docs/api/orders/v2/#definition-purchase_unit_request
|
/// More info here: <https://developer.paypal.com/docs/api/orders/v2/#definition-purchase_unit_request>
|
||||||
pub soft_descriptor: Option<String>,
|
pub soft_descriptor: Option<String>,
|
||||||
/// An array of items that the customer purchases from the merchant.
|
/// An array of items that the customer purchases from the merchant.
|
||||||
pub items: Option<Vec<Item>>,
|
pub items: Option<Vec<Item>>,
|
||||||
|
|
|
@ -20,12 +20,12 @@ pub trait Endpoint {
|
||||||
fn method(&self) -> reqwest::Method;
|
fn method(&self) -> reqwest::Method;
|
||||||
|
|
||||||
/// The query to be used when calling this endpoint.
|
/// The query to be used when calling this endpoint.
|
||||||
fn query(&self) -> Option<&Self::Query> {
|
fn query(&self) -> Option<Self::Query> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The body to be used when calling this endpoint.
|
/// The body to be used when calling this endpoint.
|
||||||
fn body(&self) -> Option<&Self::Body> {
|
fn body(&self) -> Option<Self::Body> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,10 +33,14 @@ pub trait Endpoint {
|
||||||
///
|
///
|
||||||
/// Automatically implemented.
|
/// Automatically implemented.
|
||||||
fn full_path(&self, is_sandbox: bool) -> String {
|
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 {
|
if is_sandbox {
|
||||||
format!("{}{}", SANDBOX_ENDPOINT, self.relative_path())
|
format!("{}{}", SANDBOX_ENDPOINT, relative_path)
|
||||||
} else {
|
} else {
|
||||||
format!("{}{}", LIVE_ENDPOINT, self.relative_path())
|
format!("{}{}", LIVE_ENDPOINT, relative_path)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,8 @@
|
||||||
//!
|
//!
|
||||||
//! A rust library that wraps the [paypal api](https://developer.paypal.com/docs/api) asynchronously in a strongly typed manner.
|
//! A rust library that wraps the [paypal api](https://developer.paypal.com/docs/api) asynchronously in a strongly typed manner.
|
||||||
//!
|
//!
|
||||||
|
//! If there is a missing endpoint that you need, you may try to implement the [Endpoint](endpoint::Endpoint) and pass it to [Client::execute](client::Client::execute)
|
||||||
|
//!
|
||||||
//! Currently in early development.
|
//! Currently in early development.
|
||||||
//!
|
//!
|
||||||
|
|
||||||
|
@ -91,7 +93,7 @@ pub const LIVE_ENDPOINT: &str = "https://api-m.paypal.com";
|
||||||
pub const SANDBOX_ENDPOINT: &str = "https://api-m.sandbox.paypal.com";
|
pub const SANDBOX_ENDPOINT: &str = "https://api-m.sandbox.paypal.com";
|
||||||
/// Represents the query used in most GET api requests.
|
/// Represents the query used in most GET api requests.
|
||||||
///
|
///
|
||||||
/// Reference: https://developer.paypal.com/docs/api/reference/api-requests/#query-parameters
|
/// Reference: <https://developer.paypal.com/docs/api/reference/api-requests/#query-parameters>
|
||||||
///
|
///
|
||||||
/// Note: You can avoid most fields by the Default impl like so:
|
/// Note: You can avoid most fields by the Default impl like so:
|
||||||
/// ```
|
/// ```
|
||||||
|
@ -130,7 +132,7 @@ pub struct Query {
|
||||||
|
|
||||||
/// Represents the optional header values used on paypal requests.
|
/// Represents the optional header values used on paypal requests.
|
||||||
///
|
///
|
||||||
/// https://developer.paypal.com/docs/api/reference/api-requests/#paypal-auth-assertion
|
/// <https://developer.paypal.com/docs/api/reference/api-requests/#paypal-auth-assertion>
|
||||||
#[derive(Debug, Default, Builder, Clone)]
|
#[derive(Debug, Default, Builder, Clone)]
|
||||||
pub struct HeaderParams {
|
pub struct HeaderParams {
|
||||||
/// The merchant payer id used on PayPal-Auth-Assertion
|
/// The merchant payer id used on PayPal-Auth-Assertion
|
||||||
|
|
Loading…
Reference in a new issue