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