paypal_rust/resources/
payments.rs

1use std::borrow::Cow;
2
3use reqwest::Method;
4use serde::{Deserialize, Serialize};
5use serde_with::skip_serializing_none;
6
7use crate::client::{Client, Endpoint, PayPalError};
8use crate::{
9    AuthorizationStatusDetails, CaptureStatus, CaptureStatusDetails, DisbursementMode,
10    LinkDescription, Money, PaymentInstruction, PaymentStatus, ProcessorResponse, RefundStatus,
11    RefundStatusDetails, SellerPayableBreakdown, SellerProtection, SellerReceivableBreakdown,
12};
13
14pub struct Payment;
15
16impl Payment {
17    /// Captures an authorized payment, by ID.
18    pub async fn capture_authorized(
19        client: &Client,
20        authorization_id: String,
21        dto: CaptureAuthorizedPaymentDto,
22    ) -> Result<CaptureAuthorizedPaymentResponse, PayPalError> {
23        client
24            .post(&CaptureAuthorizedPayment::new(authorization_id, dto))
25            .await
26    }
27
28    /// Refunds a captured payment, by ID. For a full refund, include an empty payload in the JSON
29    /// request body. For a partial refund, include an amount object in the JSON request body.
30    pub async fn refund_captured(
31        client: &Client,
32        capture_id: String,
33        dto: RefundCapturedPaymentDto,
34    ) -> Result<RefundCapturedPaymentResponse, PayPalError> {
35        client
36            .post(&RefundCapturedPayment::new(capture_id, dto))
37            .await
38    }
39
40    /// Reauthorizes an authorized PayPal account payment, by ID. To ensure that funds are still
41    /// available, reauthorize a payment after its initial three-day honor period expires. Within
42    /// the 29-day authorization period, you can issue multiple re-authorizations after the honor
43    /// period expires.
44    ///
45    /// If 30 days have transpired since the date of the original authorization, you must create an
46    /// authorized payment instead of reauthorizing the original authorized payment.
47    ///
48    /// A reauthorized payment itself has a new honor period of three days.
49    ///
50    /// You can reauthorize an authorized payment once for up to 115% of the original authorized
51    /// amount, not to exceed an increase of $75 USD.
52    ///
53    /// Supports only the amount request parameter.
54    pub async fn reauthorize_authorized(
55        client: &Client,
56        authorization_id: String,
57        dto: ReauthorizeAuthorizedPaymentDto,
58    ) -> Result<ReauthorizeAuthorizedPaymentResponse, PayPalError> {
59        client
60            .post(&ReauthorizeAuthorizedPayment::new(authorization_id, dto))
61            .await
62    }
63
64    /// Voids, or cancels, an authorized payment, by ID. You cannot void an authorized payment that
65    /// has been fully captured.
66    pub async fn void_authorized(
67        client: &Client,
68        authorization_id: String,
69    ) -> Result<VoidAuthorizedPaymentResponse, PayPalError> {
70        client
71            .post(&VoidAuthorizedPayment::new(authorization_id))
72            .await
73    }
74}
75
76#[skip_serializing_none]
77#[derive(Clone, Debug, Serialize, Default)]
78pub struct CaptureAuthorizedPaymentDto {
79    /// The API caller-provided external invoice number for this order. Appears in both the payer's
80    /// transaction history and the emails that the payer receives.
81    pub invoice_id: Option<String>,
82
83    /// An informational note about this settlement. Appears in both the payer's transaction history
84    /// and the emails that the payer receives.
85    pub note_to_payer: Option<String>,
86
87    /// The amount to capture. To capture a portion of the full authorized amount, specify an amount.
88    /// If amount is not specified, the full authorized amount is captured. The amount must be a
89    /// positive number and in the same currency as the authorization against which the payment is
90    /// being captured.
91    pub amount: Option<Money>,
92
93    ///  Indicates whether you can make additional captures against the authorized payment.
94    /// Set to true if you do not intend to capture additional payments against the authorization.
95    /// Set to false if you intend to capture additional payments against the authorization.
96    pub is_final_capture: Option<bool>,
97
98    ///  Any additional payment instructions to be considered during payment processing.
99    /// This processing instruction is applicable for Capturing an order or Authorizing an Order.
100    pub payment_instruction: Option<PaymentInstruction>,
101
102    /// The payment descriptor on the payer's account statement.
103    pub soft_descriptor: Option<String>,
104}
105
106impl CaptureAuthorizedPaymentDto {
107    pub fn new() -> Self {
108        Self::default()
109    }
110
111    #[must_use]
112    pub fn invoice_id(mut self, invoice_id: String) -> Self {
113        self.invoice_id = Some(invoice_id);
114        self
115    }
116
117    #[must_use]
118    pub fn note_to_payer(mut self, note_to_payer: String) -> Self {
119        self.note_to_payer = Some(note_to_payer);
120        self
121    }
122
123    #[must_use]
124    pub fn amount(mut self, amount: Money) -> Self {
125        self.amount = Some(amount);
126        self
127    }
128
129    #[must_use]
130    pub const fn is_final_capture(mut self, is_final_capture: bool) -> Self {
131        self.is_final_capture = Some(is_final_capture);
132        self
133    }
134
135    #[must_use]
136    pub fn payment_instruction(mut self, payment_instruction: PaymentInstruction) -> Self {
137        self.payment_instruction = Some(payment_instruction);
138        self
139    }
140
141    #[must_use]
142    pub fn soft_descriptor(mut self, soft_descriptor: String) -> Self {
143        self.soft_descriptor = Some(soft_descriptor);
144        self
145    }
146}
147
148#[skip_serializing_none]
149#[derive(Clone, Debug, Serialize, Deserialize, Default)]
150pub struct CaptureAuthorizedPaymentResponse {
151    /// The status of the captured payment.
152    pub status: Option<CaptureStatus>,
153
154    /// The details of the captured payment status.
155    pub status_details: Option<CaptureStatusDetails>,
156
157    /// The PayPal-generated ID for the captured payment.
158    pub id: Option<String>,
159
160    /// The amount for this captured payment.
161    pub amount: Option<Money>,
162
163    /// The API caller-provided external invoice number for this order. Appears in both the payer's
164    /// transaction history and the emails that the payer receives.
165    pub invoice_id: Option<String>,
166
167    /// The API caller-provided external ID. Used to reconcile API caller-initiated transactions
168    /// with PayPal transactions. Appears in transaction and settlement reports.
169    pub custom_id: Option<String>,
170
171    /// The level of protection offered as defined by PayPal Seller Protection for Merchants.
172    pub seller_protection: Option<SellerProtection>,
173
174    /// Indicates whether you can make additional captures against the authorized payment. Set to
175    /// true if you do not intend to capture additional payments against the authorization.
176    /// Set to false if you intend to capture additional payments against the authorization.
177    pub final_capture: Option<bool>,
178
179    /// The detailed breakdown of the capture activity. This is not available for transactions
180    /// that are in pending state.
181    pub seller_receivable_breakdown: Option<SellerReceivableBreakdown>,
182
183    /// The funds that are held on behalf of the merchant.
184    pub disbursement_mode: Option<DisbursementMode>,
185
186    /// An array of related HATEOAS links.
187    pub links: Option<Vec<LinkDescription>>,
188
189    /// An object that provides additional processor information for a direct credit card
190    /// transaction.
191    pub processor_response: Option<ProcessorResponse>,
192
193    /// The date and time when the transaction occurred, in Internet date and time format.
194    pub create_time: Option<String>,
195
196    /// The date and time when the transaction was last updated, in Internet date and time format.
197    pub update_time: Option<String>,
198}
199
200#[derive(Debug, Clone)]
201struct CaptureAuthorizedPayment {
202    authorization_id: String,
203    dto: CaptureAuthorizedPaymentDto,
204}
205
206impl Endpoint for CaptureAuthorizedPayment {
207    type QueryParams = ();
208    type RequestBody = CaptureAuthorizedPaymentDto;
209    type ResponseBody = CaptureAuthorizedPaymentResponse;
210
211    fn path(&self) -> Cow<str> {
212        Cow::Owned(format!(
213            "v2/payments/authorizations/{}/capture",
214            self.authorization_id
215        ))
216    }
217
218    fn request_body(&self) -> Option<Self::RequestBody> {
219        Some(self.dto.clone())
220    }
221
222    fn request_method(&self) -> Method {
223        Method::POST
224    }
225}
226
227impl CaptureAuthorizedPayment {
228    const fn new(authorization_id: String, dto: CaptureAuthorizedPaymentDto) -> Self {
229        Self {
230            authorization_id,
231            dto,
232        }
233    }
234}
235
236#[skip_serializing_none]
237#[derive(Clone, Debug, Serialize)]
238pub struct RefundCapturedPaymentDto {
239    /// The amount to refund. To refund a portion of the captured amount, specify an amount.
240    /// If amount is not specified, an amount equal to captured amount - previous refunds is refunded.
241    /// The amount must be a positive number and in the same currency as the one in which the payment was captured.
242    pub amount: Option<Money>,
243
244    /// The API caller-provided external invoice number for this order.
245    /// Appears in both the payer's transaction history and the emails that the payer receives.
246    pub invoice_id: Option<String>,
247
248    /// The reason for the refund. Appears in both the payer's transaction history and the emails that the payer receives.
249    pub note_to_payer: Option<String>,
250}
251
252#[skip_serializing_none]
253#[derive(Clone, Debug, Deserialize)]
254pub struct RefundCapturedPaymentResponse {
255    /// The PayPal-generated ID for the refund.
256    pub id: String,
257
258    /// The status of the refund.
259    pub status: RefundStatus,
260
261    /// An array of related HATEOAS links.
262    pub links: Option<Vec<LinkDescription>>,
263
264    /// The amount that the payee refunded to the payer.
265    pub amount: Option<Money>,
266
267    /// The date and time when the transaction occurred, in Internet date and time format.
268    pub create_time: Option<String>,
269
270    /// The API caller-provided external invoice number for this order.
271    ///  Appears in both the payer's transaction history and the emails that the payer receives.
272    pub invoice_id: Option<String>,
273
274    /// The reason for the refund. Appears in both the payer's transaction history and the emails that the payer receives.
275    pub note_to_payer: Option<String>,
276
277    /// The breakdown of the refund.
278    pub seller_payable_breakdown: Option<SellerPayableBreakdown>,
279
280    /// The details of the refund status.
281    pub status_details: Option<RefundStatusDetails>,
282
283    /// The date and time when the transaction was last updated, in Internet date and time format.
284    pub update_time: Option<String>,
285}
286
287/// Refunds a captured payment, by ID. For a full refund, include an empty payload in the JSON
288/// request body. For a partial refund, include an amount object in the JSON request body.
289#[derive(Debug)]
290struct RefundCapturedPayment {
291    capture_id: String,
292    amount: Option<Money>,
293    invoice_id: Option<String>,
294    note_to_payer: Option<String>,
295}
296
297impl RefundCapturedPayment {
298    pub fn new(capture_id: String, body: RefundCapturedPaymentDto) -> Self {
299        Self {
300            capture_id,
301            amount: body.amount,
302            invoice_id: body.invoice_id,
303            note_to_payer: body.note_to_payer,
304        }
305    }
306}
307
308impl Endpoint for RefundCapturedPayment {
309    type QueryParams = ();
310    type RequestBody = RefundCapturedPaymentDto;
311    type ResponseBody = RefundCapturedPaymentResponse;
312
313    fn path(&self) -> Cow<str> {
314        Cow::Owned(format!("v2/payments/captures/{}/refund", self.capture_id))
315    }
316
317    fn request_body(&self) -> Option<Self::RequestBody> {
318        Some(RefundCapturedPaymentDto {
319            amount: self.amount.clone(),
320            invoice_id: self.invoice_id.clone(),
321            note_to_payer: self.note_to_payer.clone(),
322        })
323    }
324
325    fn request_method(&self) -> Method {
326        Method::POST
327    }
328}
329
330#[skip_serializing_none]
331#[derive(Clone, Debug, Serialize)]
332pub struct ReauthorizeAuthorizedPaymentDto {
333    /// The amount to reauthorize for an authorized payment.
334    pub amount: Option<Money>,
335}
336
337#[skip_serializing_none]
338#[derive(Clone, Debug, Deserialize)]
339pub struct ReauthorizeAuthorizedPaymentResponse {
340    /// The status for the authorized payment.
341    pub status: Option<PaymentStatus>,
342
343    /// The details of the authorized order pending status.
344    pub status_details: Option<AuthorizationStatusDetails>,
345
346    /// The PayPal-generated ID for the authorized payment.
347    pub id: Option<String>,
348
349    /// The amount for this authorized payment.
350    pub amount: Option<Money>,
351
352    /// The API caller-provided external invoice number for this order. Appears in both the payer's transaction history and the emails
353    /// that the payer receives.
354    pub invoice_id: Option<String>,
355
356    /// The API caller-provided external ID. Used to reconcile API caller-initiated transactions with PayPal transactions. Appears in
357    /// transaction and settlement reports.
358    pub custom_id: Option<String>,
359
360    /// The level of protection offered as defined by PayPal Seller Protection for Merchants.
361    pub seller_protection: Option<SellerProtection>,
362
363    /// The date and time when the authorized payment expires, in Internet date and time format
364    pub expiration_time: Option<String>,
365
366    /// An array of related HATEOAS links.  
367    pub links: Option<Vec<LinkDescription>>,
368
369    /// The date and time when the transaction occurred, in Internet date and time format.
370    pub create_time: Option<String>,
371
372    /// The date and time when the transaction was last updated, in Internet date and time format.
373    pub update_time: Option<String>,
374}
375
376/// Reauthorizes an authorized PayPal account payment, by ID. To ensure that funds are still
377/// available, reauthorize a payment after its initial three-day honor period expires.
378/// Within the 29-day authorization period, you can issue multiple re-authorizations after the honor
379/// period expires.
380///
381/// If 30 days have transpired since the date of the original authorization, you must create an
382/// authorized payment instead of reauthorizing the original authorized payment.
383///
384/// A reauthorized payment itself has a new honor period of three days.
385///
386/// You can reauthorize an authorized payment once for up to 115% of the original authorized amount,
387/// not to exceed an increase of $75 USD.
388///
389/// Supports only the amount request parameter.
390#[derive(Debug)]
391struct ReauthorizeAuthorizedPayment {
392    authorization_id: String,
393    amount: Option<Money>,
394}
395
396impl ReauthorizeAuthorizedPayment {
397    pub fn new(authorization_id: String, body: ReauthorizeAuthorizedPaymentDto) -> Self {
398        Self {
399            authorization_id,
400            amount: body.amount,
401        }
402    }
403}
404
405impl Endpoint for ReauthorizeAuthorizedPayment {
406    type QueryParams = ();
407    type RequestBody = ReauthorizeAuthorizedPaymentDto;
408    type ResponseBody = ReauthorizeAuthorizedPaymentResponse;
409
410    fn path(&self) -> Cow<str> {
411        Cow::Owned(format!(
412            "v2/payments/authorizations/{}/reauthorize",
413            self.authorization_id
414        ))
415    }
416
417    fn request_body(&self) -> Option<Self::RequestBody> {
418        Some(ReauthorizeAuthorizedPaymentDto {
419            amount: self.amount.clone(),
420        })
421    }
422
423    fn request_method(&self) -> Method {
424        Method::POST
425    }
426}
427
428struct VoidAuthorizedPayment {
429    authorization_id: String,
430}
431
432impl VoidAuthorizedPayment {
433    pub const fn new(authorization_id: String) -> Self {
434        Self { authorization_id }
435    }
436}
437
438#[derive(Debug, Deserialize)]
439pub struct VoidAuthorizedPaymentResponse {}
440
441impl Endpoint for VoidAuthorizedPayment {
442    type QueryParams = ();
443    type RequestBody = ();
444    type ResponseBody = VoidAuthorizedPaymentResponse;
445
446    fn path(&self) -> Cow<str> {
447        Cow::Owned(format!(
448            "v2/payments/authorizations/{}/void",
449            self.authorization_id
450        ))
451    }
452
453    fn request_body(&self) -> Option<Self::RequestBody> {
454        None
455    }
456
457    fn request_method(&self) -> Method {
458        Method::POST
459    }
460}