diff --git a/src/common.rs b/src/common.rs index e44dd33..cfd74a8 100644 --- a/src/common.rs +++ b/src/common.rs @@ -1,7 +1,6 @@ //! Common paypal object definitions used amon 2 or more APIs -use serde::{Serialize, Deserialize}; - +use serde::{Deserialize, Serialize}; /// The phone type. /// @@ -20,23 +19,23 @@ pub enum PhoneType { /// The non-portable additional address details #[derive(Debug, Default, Serialize, Deserialize)] pub struct AddressDetails { - /// The street number. + /// The street number. #[serde(skip_serializing_if = "Option::is_none")] pub street_number: Option, - /// The street name. Just Drury in Drury Lane. + /// The street name. Just Drury in Drury Lane. #[serde(skip_serializing_if = "Option::is_none")] pub street_name: Option, - /// The street type. For example, avenue, boulevard, road, or expressway. + /// The street type. For example, avenue, boulevard, road, or expressway. #[serde(skip_serializing_if = "Option::is_none")] pub street_type: Option, - /// The delivery service. Post office box, bag number, or post office name. + /// The delivery service. Post office box, bag number, or post office name. #[serde(skip_serializing_if = "Option::is_none")] pub delivery_service: Option, - /// A named locations that represents the premise. Usually a building name or number or collection of buildings with a common name or number. For example, Craven House. + /// A named locations that represents the premise. Usually a building name or number or collection of buildings with a common name or number. For example, Craven House. #[serde(skip_serializing_if = "Option::is_none")] pub building_name: Option, /// The first-order entity below a named building or location that represents the sub-premise. - /// Usually a single building within a collection of buildings with a common name. Can be a flat, story, floor, room, or apartment. + /// Usually a single building within a collection of buildings with a common name. Can be a flat, story, floor, room, or apartment. #[serde(skip_serializing_if = "Option::is_none")] pub sub_building: Option, } @@ -105,4 +104,5 @@ pub struct LinkDescription { /// The HTTP method required to make the related call. #[serde(skip_serializing_if = "Option::is_none")] pub method: Option, -} \ No newline at end of file +} + diff --git a/src/invoice.rs b/src/invoice.rs index b915b2f..e96b4c4 100644 --- a/src/invoice.rs +++ b/src/invoice.rs @@ -471,6 +471,12 @@ pub enum PaymentMethod { Other, } +impl Default for PaymentMethod { + fn default() -> Self { + PaymentMethod::Paypal + } +} + /// Payment detail #[derive(Debug, Serialize, Deserialize)] pub struct PaymentDetail { @@ -697,6 +703,20 @@ pub struct QRCodeParams { pub action: Option, } +#[derive(Debug, Serialize, Deserialize, Default)] +pub struct RecordPaymentPayload { + #[serde(skip_serializing_if = "Option::is_none")] + payment_id: Option, + #[serde(skip_serializing_if = "Option::is_none")] + payment_date: Option>, + method: PaymentMethod, + #[serde(skip_serializing_if = "Option::is_none")] + note: Option, + amount: Amount, + #[serde(skip_serializing_if = "Option::is_none")] + shipping_info: Option, +} + impl super::Client { /// Generates the next invoice number that is available to the merchant. /// @@ -727,8 +747,8 @@ impl super::Client { /// Include invoice details including merchant information. The invoice object must include an items array. pub async fn create_draft_invoice( &self, - header_params: crate::HeaderParams, invoice: InvoicePayload, + header_params: crate::HeaderParams, ) -> Result> { let build = self.setup_headers( self.client @@ -749,8 +769,8 @@ impl super::Client { /// Get an invoice by ID. pub async fn get_invoice( &self, - header_params: crate::HeaderParams, invoice_id: S, + header_params: crate::HeaderParams, ) -> Result> { let build = self.setup_headers( self.client @@ -772,9 +792,9 @@ impl super::Client { /// Page size has the following limits: [1, 100]. pub async fn list_invoices( &self, - header_params: crate::HeaderParams, page: i32, page_size: i32, + header_params: crate::HeaderParams, ) -> Result> { let build = self.setup_headers( self.client.get( @@ -802,8 +822,8 @@ impl super::Client { /// Delete a invoice pub async fn delete_invoice( &self, - header_params: crate::HeaderParams, invoice_id: S, + header_params: crate::HeaderParams, ) -> Result<(), Box> { let build = self.setup_headers( self.client @@ -823,10 +843,10 @@ impl super::Client { /// Update a invoice pub async fn update_invoice( &self, - header_params: crate::HeaderParams, invoice: Invoice, send_to_recipient: bool, send_to_invoicer: bool, + header_params: crate::HeaderParams, ) -> Result<(), Box> { let build = self.setup_headers( self.client.put( @@ -854,9 +874,9 @@ impl super::Client { /// Cancel a invoice pub async fn cancel_invoice( &self, - header_params: crate::HeaderParams, invoice_id: S, reason: CancelReason, + header_params: crate::HeaderParams, ) -> Result<(), Box> { let build = self.setup_headers( self.client @@ -876,9 +896,9 @@ impl super::Client { /// Generate a QR code pub async fn generate_qr_code( &self, - header_params: crate::HeaderParams, invoice_id: S, params: QRCodeParams, + header_params: crate::HeaderParams, ) -> Result> { let build = self.setup_headers( self.client @@ -896,5 +916,28 @@ impl super::Client { } } - // TODO: https://developer.paypal.com/docs/api/invoicing/v2/#invoices_payments + /// Records a payment for the invoice. If no payment is due, the invoice is marked as PAID. Otherwise, the invoice is marked as PARTIALLY PAID. + pub async fn record_invoice_payment( + &self, + invoice_id: S, + payload: RecordPaymentPayload, + header_params: crate::HeaderParams, + ) -> Result> { + let build = self.setup_headers( + self.client + .post(format!("{}/v2/invoicing/invoices/{}/payments", self.endpoint(), invoice_id).as_str()), + header_params, + ); + + let res = build.json(&payload).send().await?; + + if res.status().is_success() { + let x = res.json::>().await?; + Ok(x.get("payment_id").unwrap().to_owned()) + } else { + Err(Box::new(res.json::().await?)) + } + } + + // TODO: https://developer.paypal.com/docs/api/invoicing/v2/#invoices_payments-delete }