paddle_rust_sdk/
customers.rs

1//! Builders for making requests to the Paddle API for customers.
2//!
3//! See the [Paddle API](https://developer.paddle.com/api-reference/customers/overview) documentation for more information.
4
5use std::collections::HashMap;
6
7use reqwest::Method;
8use serde::Serialize;
9use serde_with::skip_serializing_none;
10
11use crate::entities::{CreditBalance, Customer, CustomerPortalSession};
12use crate::enums::Status;
13use crate::ids::{CustomerID, SubscriptionID};
14use crate::paginated::Paginated;
15use crate::{Paddle, Result};
16
17/// Request builder for fetching customers from Paddle API.
18#[skip_serializing_none]
19#[derive(Serialize)]
20pub struct CustomersList<'a> {
21    #[serde(skip)]
22    client: &'a Paddle,
23    after: Option<CustomerID>,
24    #[serde(serialize_with = "crate::comma_separated")]
25    email: Option<Vec<String>>,
26    #[serde(serialize_with = "crate::comma_separated")]
27    id: Option<Vec<CustomerID>>,
28    order_by: Option<String>,
29    per_page: Option<usize>,
30    search: Option<String>,
31    status: Option<Status>,
32}
33
34impl<'a> CustomersList<'a> {
35    pub fn new(client: &'a Paddle) -> Self {
36        Self {
37            client,
38            after: None,
39            email: None,
40            id: None,
41            order_by: None,
42            per_page: None,
43            search: None,
44            status: None,
45        }
46    }
47
48    /// Return entities after the specified Paddle ID when working with paginated endpoints. Used in the `meta.pagination.next` URL in responses for list operations.
49    pub fn after(&mut self, customer_id: impl Into<CustomerID>) -> &mut Self {
50        self.after = Some(customer_id.into());
51        self
52    }
53
54    /// Return entities that exactly match the specified email addresses
55    pub fn emails(&mut self, emails: impl IntoIterator<Item = impl AsRef<str>>) -> &mut Self {
56        self.email = Some(emails.into_iter().map(|s| s.as_ref().to_string()).collect());
57        self
58    }
59
60    /// Return only the IDs specified.
61    pub fn ids(
62        &mut self,
63        customer_ids: impl IntoIterator<Item = impl Into<CustomerID>>,
64    ) -> &mut Self {
65        self.id = Some(customer_ids.into_iter().map(Into::into).collect());
66        self
67    }
68
69    /// Order returned entities by the specified field. Valid fields for ordering: id
70    pub fn order_by_asc(&mut self, field: &str) -> &mut Self {
71        self.order_by = Some(format!("{}[ASC]", field));
72        self
73    }
74
75    /// Order returned entities by the specified field. Valid fields for ordering: id
76    pub fn order_by_desc(&mut self, field: &str) -> &mut Self {
77        self.order_by = Some(format!("{}[DESC]", field));
78        self
79    }
80
81    /// Set how many entities are returned per page. Paddle returns the maximum number of results if a number greater than the maximum is requested.
82    /// Check `meta.pagination.per_page` in the response to see how many were returned.
83    ///
84    /// Default: `50`; Maximum: `200`.
85    pub fn per_page(&mut self, entities_per_page: usize) -> &mut Self {
86        self.per_page = Some(entities_per_page);
87        self
88    }
89
90    /// Return entities that match a search query. Searches `id`, `name`, and `email` fields. Use the email filter for precise matching of email addresses.
91    pub fn search(&mut self, term: impl Into<String>) -> &mut Self {
92        self.search = Some(term.into());
93        self
94    }
95
96    /// Return only prices with the specified status.
97    pub fn status(&mut self, status: Status) -> &mut Self {
98        self.status = Some(status);
99        self
100    }
101
102    /// Returns a paginator for fetching pages of entities from Paddle
103    pub fn send(&self) -> Paginated<Vec<Customer>> {
104        Paginated::new(self.client, "/customers", self)
105    }
106}
107
108/// Request builder for creating customers in Paddle API.
109#[skip_serializing_none]
110#[derive(Serialize)]
111pub struct CustomerCreate<'a> {
112    #[serde(skip)]
113    client: &'a Paddle,
114    email: String,
115    name: Option<String>,
116    custom_data: Option<HashMap<String, String>>,
117    locale: Option<String>,
118}
119
120impl<'a> CustomerCreate<'a> {
121    pub fn new(client: &'a Paddle, email: String) -> Self {
122        Self {
123            client,
124            email,
125            name: None,
126            custom_data: None,
127            locale: None,
128        }
129    }
130
131    /// Full name of this customer. Required when creating transactions where `collection_mode` is `manual` (invoices).
132    pub fn name(&mut self, name: impl Into<String>) -> &mut Self {
133        self.name = Some(name.into());
134        self
135    }
136
137    /// Your own structured key-value data.
138    pub fn custom_data(&mut self, custom_data: HashMap<String, String>) -> &mut Self {
139        self.custom_data = Some(custom_data);
140        self
141    }
142
143    /// Valid IETF BCP 47 short form locale tag. If omitted, defaults to `en`.
144    pub fn locale(&mut self, locale: impl Into<String>) -> &mut Self {
145        self.locale = Some(locale.into());
146        self
147    }
148
149    /// Send the request to Paddle and return the response.
150    pub async fn send(&self) -> Result<Customer> {
151        self.client.send(self, Method::POST, "/customers").await
152    }
153}
154
155/// Request builder for fetching a single customer from Paddle API.
156#[derive(Serialize)]
157pub struct CustomerGet<'a> {
158    #[serde(skip)]
159    client: &'a Paddle,
160    #[serde(skip)]
161    customer_id: CustomerID,
162}
163
164impl<'a> CustomerGet<'a> {
165    pub fn new(client: &'a Paddle, customer_id: impl Into<CustomerID>) -> Self {
166        Self {
167            client,
168            customer_id: customer_id.into(),
169        }
170    }
171
172    /// Send the request to Paddle and return the response.
173    pub async fn send(&self) -> Result<Customer> {
174        self.client
175            .send(
176                self,
177                Method::GET,
178                &format!("/customers/{}", self.customer_id.as_ref()),
179            )
180            .await
181    }
182}
183
184/// Request builder for updating a customer in Paddle API.
185#[skip_serializing_none]
186#[derive(Serialize)]
187pub struct CustomerUpdate<'a> {
188    #[serde(skip)]
189    client: &'a Paddle,
190    #[serde(skip)]
191    customer_id: CustomerID,
192    name: Option<String>,
193    email: Option<String>,
194    status: Option<Status>,
195    custom_data: Option<HashMap<String, String>>,
196    locale: Option<String>,
197}
198
199impl<'a> CustomerUpdate<'a> {
200    pub fn new(client: &'a Paddle, customer_id: impl Into<CustomerID>) -> Self {
201        Self {
202            client,
203            customer_id: customer_id.into(),
204            name: None,
205            email: None,
206            status: None,
207            custom_data: None,
208            locale: None,
209        }
210    }
211
212    /// Full name of this customer. Required when creating transactions where `collection_mode` is `manual` (invoices).
213    pub fn name(&mut self, name: impl Into<String>) -> &mut Self {
214        self.name = Some(name.into());
215        self
216    }
217
218    /// Email address for this customer.
219    pub fn email(&mut self, email: impl Into<String>) -> &mut Self {
220        self.email = Some(email.into());
221        self
222    }
223
224    /// Whether this entity can be used in Paddle.
225    pub fn status(&mut self, status: Status) -> &mut Self {
226        self.status = Some(status);
227        self
228    }
229
230    /// Your own structured key-value data.
231    pub fn custom_data(&mut self, custom_data: HashMap<String, String>) -> &mut Self {
232        self.custom_data = Some(custom_data);
233        self
234    }
235
236    /// Valid IETF BCP 47 short form locale tag.
237    pub fn locale(&mut self, locale: impl Into<String>) -> &mut Self {
238        self.locale = Some(locale.into());
239        self
240    }
241
242    /// Send the request to Paddle and return the response.
243    pub async fn send(&self) -> Result<Customer> {
244        self.client
245            .send(
246                self,
247                Method::PATCH,
248                &format!("/customers/{}", self.customer_id.as_ref()),
249            )
250            .await
251    }
252}
253
254/// Request builder for retrieving credit balances for each currency for a customer.
255#[skip_serializing_none]
256#[derive(Serialize)]
257pub struct CustomerCreditBalances<'a> {
258    #[serde(skip)]
259    client: &'a Paddle,
260    #[serde(skip)]
261    customer_id: CustomerID,
262}
263
264impl<'a> CustomerCreditBalances<'a> {
265    pub fn new(client: &'a Paddle, customer_id: impl Into<CustomerID>) -> Self {
266        Self {
267            client,
268            customer_id: customer_id.into(),
269        }
270    }
271
272    /// Send the request to Paddle and return the response.
273    pub async fn send(&self) -> Result<Vec<CreditBalance>> {
274        self.client
275            .send(
276                self,
277                Method::GET,
278                &format!("/customers/{}/credit-balances", self.customer_id.as_ref()),
279            )
280            .await
281    }
282}
283
284/// Request builder for creating customer portal sessions
285#[skip_serializing_none]
286#[derive(Serialize)]
287pub struct PortalSessionCreate<'a> {
288    #[serde(skip)]
289    client: &'a Paddle,
290    #[serde(skip)]
291    customer_id: CustomerID,
292    subscription_ids: Option<Vec<SubscriptionID>>,
293}
294
295impl<'a> PortalSessionCreate<'a> {
296    pub fn new(client: &'a Paddle, customer_id: impl Into<CustomerID>) -> Self {
297        Self {
298            client,
299            customer_id: customer_id.into(),
300            subscription_ids: None,
301        }
302    }
303
304    /// List of subscriptions to create authenticated customer portal deep links for.
305    pub fn subscription_ids(
306        &mut self,
307        subscription_ids: impl IntoIterator<Item = impl Into<SubscriptionID>>,
308    ) -> &mut Self {
309        self.subscription_ids = Some(subscription_ids.into_iter().map(Into::into).collect());
310        self
311    }
312
313    /// Send the request to Paddle and return the response.
314    pub async fn send(&self) -> Result<CustomerPortalSession> {
315        self.client
316            .send(
317                self,
318                Method::POST,
319                &format!("/customers/{}/portal-sessions", self.customer_id.as_ref()),
320            )
321            .await
322    }
323}