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 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 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 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 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 pub invoice_id: Option<String>,
82
83 pub note_to_payer: Option<String>,
86
87 pub amount: Option<Money>,
92
93 pub is_final_capture: Option<bool>,
97
98 pub payment_instruction: Option<PaymentInstruction>,
101
102 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 pub status: Option<CaptureStatus>,
153
154 pub status_details: Option<CaptureStatusDetails>,
156
157 pub id: Option<String>,
159
160 pub amount: Option<Money>,
162
163 pub invoice_id: Option<String>,
166
167 pub custom_id: Option<String>,
170
171 pub seller_protection: Option<SellerProtection>,
173
174 pub final_capture: Option<bool>,
178
179 pub seller_receivable_breakdown: Option<SellerReceivableBreakdown>,
182
183 pub disbursement_mode: Option<DisbursementMode>,
185
186 pub links: Option<Vec<LinkDescription>>,
188
189 pub processor_response: Option<ProcessorResponse>,
192
193 pub create_time: Option<String>,
195
196 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 pub amount: Option<Money>,
243
244 pub invoice_id: Option<String>,
247
248 pub note_to_payer: Option<String>,
250}
251
252#[skip_serializing_none]
253#[derive(Clone, Debug, Deserialize)]
254pub struct RefundCapturedPaymentResponse {
255 pub id: String,
257
258 pub status: RefundStatus,
260
261 pub links: Option<Vec<LinkDescription>>,
263
264 pub amount: Option<Money>,
266
267 pub create_time: Option<String>,
269
270 pub invoice_id: Option<String>,
273
274 pub note_to_payer: Option<String>,
276
277 pub seller_payable_breakdown: Option<SellerPayableBreakdown>,
279
280 pub status_details: Option<RefundStatusDetails>,
282
283 pub update_time: Option<String>,
285}
286
287#[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 pub amount: Option<Money>,
335}
336
337#[skip_serializing_none]
338#[derive(Clone, Debug, Deserialize)]
339pub struct ReauthorizeAuthorizedPaymentResponse {
340 pub status: Option<PaymentStatus>,
342
343 pub status_details: Option<AuthorizationStatusDetails>,
345
346 pub id: Option<String>,
348
349 pub amount: Option<Money>,
351
352 pub invoice_id: Option<String>,
355
356 pub custom_id: Option<String>,
359
360 pub seller_protection: Option<SellerProtection>,
362
363 pub expiration_time: Option<String>,
365
366 pub links: Option<Vec<LinkDescription>>,
368
369 pub create_time: Option<String>,
371
372 pub update_time: Option<String>,
374}
375
376#[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}