1use crate::client::ChipClient;
2use crate::error::ChipError;
3use crate::model::{PaymentMethods, Purchase};
4
5#[derive(Debug, Default)]
6pub struct PaymentMethodsOptions {
7 pub country: Option<String>,
8 pub recurring: Option<bool>,
9 pub skip_capture: Option<bool>,
10 pub preauthorization: Option<bool>,
11}
12
13impl ChipClient {
14 pub async fn payment_methods(
15 &self,
16 brand_id: &str,
17 currency: &str,
18 opts: Option<PaymentMethodsOptions>,
19 ) -> Result<PaymentMethods, ChipError> {
20 let url = format!("{}/payment_methods/", self.base_url);
21 let mut request = self
22 .http
23 .get(&url)
24 .query(&[("brand_id", brand_id), ("currency", currency)]);
25 if let Some(opts) = opts {
26 if let Some(country) = &opts.country {
27 request = request.query(&[("country", country.as_str())]);
28 }
29 if let Some(true) = opts.recurring {
30 request = request.query(&[("recurring", "true")]);
31 }
32 if let Some(true) = opts.skip_capture {
33 request = request.query(&[("skip_capture", "true")]);
34 }
35 if let Some(true) = opts.preauthorization {
36 request = request.query(&[("preauthorization", "true")]);
37 }
38 }
39 let response = request.send().await?;
40 handle_response(response).await
41 }
42
43 pub async fn create_purchase(&self, purchase: &Purchase) -> Result<Purchase, ChipError> {
44 let url = format!("{}/purchases/", self.base_url);
45 let response = self.http.post(&url).json(purchase).send().await?;
46 handle_response(response).await
47 }
48
49 pub async fn get_purchase(&self, id: &str) -> Result<Purchase, ChipError> {
50 let url = format!("{}/purchases/{}/", self.base_url, id);
51 let response = self.http.get(&url).send().await?;
52 handle_response(response).await
53 }
54
55 pub async fn cancel_purchase(&self, id: &str) -> Result<Purchase, ChipError> {
56 let url = format!("{}/purchases/{}/cancel/", self.base_url, id);
57 let response = self.http.post(&url).send().await?;
58 handle_response(response).await
59 }
60
61 pub async fn capture_purchase(
62 &self,
63 id: &str,
64 amount: Option<f64>,
65 ) -> Result<Purchase, ChipError> {
66 let url = format!("{}/purchases/{}/capture/", self.base_url, id);
67 let body = match amount {
68 Some(amt) => serde_json::json!({ "amount": amt }),
69 None => serde_json::json!({}),
70 };
71 let response = self.http.post(&url).json(&body).send().await?;
72 handle_response(response).await
73 }
74
75 pub async fn charge_purchase(
76 &self,
77 id: &str,
78 recurring_token: &str,
79 ) -> Result<Purchase, ChipError> {
80 let url = format!("{}/purchases/{}/charge/", self.base_url, id);
81 let body = serde_json::json!({ "recurring_token": recurring_token });
82 let response = self.http.post(&url).json(&body).send().await?;
83 handle_response(response).await
84 }
85
86 pub async fn refund_purchase(
87 &self,
88 id: &str,
89 amount: Option<f64>,
90 ) -> Result<Purchase, ChipError> {
91 let url = format!("{}/purchases/{}/refund/", self.base_url, id);
92 let body = match amount {
93 Some(amt) => serde_json::json!({ "amount": amt }),
94 None => serde_json::json!({}),
95 };
96 let response = self.http.post(&url).json(&body).send().await?;
97 handle_response(response).await
98 }
99
100 pub async fn release_purchase(&self, id: &str) -> Result<Purchase, ChipError> {
101 let url = format!("{}/purchases/{}/release/", self.base_url, id);
102 let response = self.http.post(&url).send().await?;
103 handle_response(response).await
104 }
105
106 pub async fn delete_recurring_token(&self, id: &str) -> Result<Purchase, ChipError> {
107 let url = format!("{}/purchases/{}/delete_recurring_token/", self.base_url, id);
108 let response = self.http.post(&url).send().await?;
109 handle_response(response).await
110 }
111}
112
113async fn handle_response<T: serde::de::DeserializeOwned>(
114 response: reqwest::Response,
115) -> Result<T, ChipError> {
116 let status = response.status();
117 if status.is_success() {
118 let data = response.json::<T>().await?;
119 Ok(data)
120 } else {
121 let message = response
122 .text()
123 .await
124 .unwrap_or_else(|_| "Unknown error".to_string());
125 Err(ChipError::Api {
126 status: status.as_u16(),
127 message,
128 })
129 }
130}