Skip to main content

paddle_rust_sdk/
addresses.rs

1//! Builders for making requests to the Paddle API for customer addresses.
2//!
3//! See the [Paddle API](https://developer.paddle.com/api-reference/addresses/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::Address;
12use crate::enums::{CountryCodeSupported, Status};
13use crate::ids::{AddressID, CustomerID};
14use crate::paginated::Paginated;
15use crate::nullable::Nullable;
16use crate::{Paddle, Result};
17
18/// Request builder for fetching addresses from Paddle API.
19#[skip_serializing_none]
20#[derive(Serialize)]
21pub struct AddressesList<'a> {
22    #[serde(skip)]
23    client: &'a Paddle,
24    #[serde(skip)]
25    customer_id: CustomerID,
26    after: Option<AddressID>,
27    #[serde(serialize_with = "crate::comma_separated")]
28    id: Option<Vec<AddressID>>,
29    order_by: Option<String>,
30    per_page: Option<usize>,
31    search: Option<String>,
32    status: Option<Status>,
33}
34
35impl<'a> AddressesList<'a> {
36    pub fn new(client: &'a Paddle, customer_id: impl Into<CustomerID>) -> Self {
37        Self {
38            client,
39            customer_id: customer_id.into(),
40            after: None,
41            id: None,
42            order_by: None,
43            per_page: None,
44            search: None,
45            status: None,
46        }
47    }
48
49    /// Return entities after the specified Paddle ID when working with paginated endpoints. Used in the `meta.pagination.next` URL in responses for list operations.
50    pub fn after(&mut self, address_id: impl Into<AddressID>) -> &mut Self {
51        self.after = Some(address_id.into());
52        self
53    }
54
55    /// Return only the IDs specified.
56    pub fn ids(
57        &mut self,
58        address_ids: impl IntoIterator<Item = impl Into<AddressID>>,
59    ) -> &mut Self {
60        self.id = Some(address_ids.into_iter().map(Into::into).collect());
61        self
62    }
63
64    /// Order returned entities by the specified field. Valid fields for ordering: id
65    pub fn order_by_asc(&mut self, field: &str) -> &mut Self {
66        self.order_by = Some(format!("{}[ASC]", field));
67        self
68    }
69
70    /// Order returned entities by the specified field. Valid fields for ordering: id
71    pub fn order_by_desc(&mut self, field: &str) -> &mut Self {
72        self.order_by = Some(format!("{}[DESC]", field));
73        self
74    }
75
76    /// Set how many entities are returned per page. Paddle returns the maximum number of results if a number greater than the maximum is requested.
77    /// Check `meta.pagination.per_page` in the response to see how many were returned.
78    ///
79    /// Default: `50`; Maximum: `200`.
80    pub fn per_page(&mut self, entities_per_page: usize) -> &mut Self {
81        self.per_page = Some(entities_per_page);
82        self
83    }
84
85    /// Return entities that match a search query. Searches `status`, `created_at`, and `updated_at`.
86    pub fn search(&mut self, term: impl Into<String>) -> &mut Self {
87        self.search = Some(term.into());
88        self
89    }
90
91    /// Return only prices with the specified status.
92    pub fn status(&mut self, status: Status) -> &mut Self {
93        self.status = Some(status);
94        self
95    }
96
97    /// Send the request to Paddle and return the response.
98    pub fn send(&self) -> Paginated<'_, Vec<Address>> {
99        let url = format!("/customers/{}/addresses", self.customer_id.as_ref());
100
101        Paginated::new(self.client, &url, self)
102    }
103}
104
105/// Request builder for creating customer addresses in Paddle API.
106#[skip_serializing_none]
107#[derive(Serialize)]
108pub struct AddressCreate<'a> {
109    #[serde(skip)]
110    client: &'a Paddle,
111    #[serde(skip)]
112    customer_id: CustomerID,
113    country_code: CountryCodeSupported,
114    description: Option<String>,
115    first_line: Option<String>,
116    second_line: Option<String>,
117    city: Option<String>,
118    postal_code: Option<String>,
119    region: Option<String>,
120    custom_data: Option<HashMap<String, String>>,
121}
122
123impl<'a> AddressCreate<'a> {
124    pub fn new(
125        client: &'a Paddle,
126        customer_id: impl Into<CustomerID>,
127        country_code: CountryCodeSupported,
128    ) -> Self {
129        Self {
130            client,
131            customer_id: customer_id.into(),
132            country_code,
133            description: None,
134            first_line: None,
135            second_line: None,
136            city: None,
137            postal_code: None,
138            region: None,
139            custom_data: None,
140        }
141    }
142
143    /// Memorable description for this address.
144    pub fn description(&mut self, description: impl Into<String>) -> &mut Self {
145        self.description = Some(description.into());
146        self
147    }
148
149    /// First line of the address.
150    pub fn first_line(&mut self, first_line: impl Into<String>) -> &mut Self {
151        self.first_line = Some(first_line.into());
152        self
153    }
154
155    /// Second line of the address.
156    pub fn second_line(&mut self, second_line: impl Into<String>) -> &mut Self {
157        self.second_line = Some(second_line.into());
158        self
159    }
160
161    /// City name.
162    pub fn city(&mut self, city: impl Into<String>) -> &mut Self {
163        self.city = Some(city.into());
164        self
165    }
166
167    /// Postal code. Required for US addresses
168    pub fn postal_code(&mut self, postal_code: impl Into<String>) -> &mut Self {
169        self.postal_code = Some(postal_code.into());
170        self
171    }
172
173    /// Region name.
174    pub fn region(&mut self, region: impl Into<String>) -> &mut Self {
175        self.region = Some(region.into());
176        self
177    }
178
179    /// Custom data to be stored with this address.
180    pub fn custom_data(&mut self, custom_data: HashMap<String, String>) -> &mut Self {
181        self.custom_data = Some(custom_data);
182        self
183    }
184
185    /// Send the request to Paddle and return the response.
186    pub async fn send(&self) -> Result<Address> {
187        self.client
188            .send(
189                self,
190                Method::POST,
191                &format!("/customers/{}/addresses", self.customer_id.as_ref()),
192            )
193            .await
194    }
195}
196
197/// Request builder for fetching a single address from Paddle API.
198#[skip_serializing_none]
199#[derive(Serialize)]
200pub struct AddressGet<'a> {
201    #[serde(skip)]
202    client: &'a Paddle,
203    #[serde(skip)]
204    customer_id: CustomerID,
205    #[serde(skip)]
206    address_id: AddressID,
207}
208
209impl<'a> AddressGet<'a> {
210    pub fn new(
211        client: &'a Paddle,
212        customer_id: impl Into<CustomerID>,
213        address_id: impl Into<AddressID>,
214    ) -> Self {
215        Self {
216            client,
217            customer_id: customer_id.into(),
218            address_id: address_id.into(),
219        }
220    }
221
222    /// Send the request to Paddle and return the response.
223    pub async fn send(&self) -> Result<Address> {
224        self.client
225            .send(
226                self,
227                Method::GET,
228                &format!(
229                    "/customers/{}/addresses/{}",
230                    self.customer_id.as_ref(),
231                    self.address_id.as_ref()
232                ),
233            )
234            .await
235    }
236}
237
238/// Request builder for updating an address in Paddle API.
239#[derive(Serialize)]
240pub struct AddressUpdate<'a> {
241    #[serde(skip)]
242    client: &'a Paddle,
243    #[serde(skip)]
244    customer_id: CustomerID,
245    #[serde(skip)]
246    address_id: AddressID,
247    #[serde(skip_serializing_if = "Nullable::is_unchanged")]
248    description: Nullable<String>,
249    #[serde(skip_serializing_if = "Nullable::is_unchanged")]
250    first_line: Nullable<String>,
251    #[serde(skip_serializing_if = "Nullable::is_unchanged")]
252    second_line: Nullable<String>,
253    #[serde(skip_serializing_if = "Nullable::is_unchanged")]
254    city: Nullable<String>,
255    #[serde(skip_serializing_if = "Nullable::is_unchanged")]
256    postal_code: Nullable<String>,
257    #[serde(skip_serializing_if = "Nullable::is_unchanged")]
258    region: Nullable<String>,
259    #[serde(skip_serializing_if = "Nullable::is_unchanged")]
260    country_code: Nullable<CountryCodeSupported>,
261    #[serde(skip_serializing_if = "Nullable::is_unchanged")]
262    custom_data: Nullable<HashMap<String, String>>,
263    #[serde(skip_serializing_if = "Nullable::is_unchanged")]
264    status: Nullable<Status>,
265}
266
267impl<'a> AddressUpdate<'a> {
268    pub fn new(
269        client: &'a Paddle,
270        customer_id: impl Into<CustomerID>,
271        address_id: impl Into<AddressID>,
272    ) -> Self {
273        Self {
274            client,
275            customer_id: customer_id.into(),
276            address_id: address_id.into(),
277            description: Nullable::Unchanged,
278            first_line: Nullable::Unchanged,
279            second_line: Nullable::Unchanged,
280            city: Nullable::Unchanged,
281            postal_code: Nullable::Unchanged,
282            region: Nullable::Unchanged,
283            country_code: Nullable::Unchanged,
284            custom_data: Nullable::Unchanged,
285            status: Nullable::Unchanged,
286        }
287    }
288
289    /// Memorable description for this address.
290    pub fn description(&mut self, description: impl Into<Nullable<String>>) -> &mut Self {
291        self.description = description.into();
292        self
293    }
294
295    /// First line of the address.
296    pub fn first_line(&mut self, first_line: impl Into<Nullable<String>>) -> &mut Self {
297        self.first_line = first_line.into();
298        self
299    }
300
301    /// Second line of the address.
302    pub fn second_line(&mut self, second_line: impl Into<Nullable<String>>) -> &mut Self {
303        self.second_line = second_line.into();
304        self
305    }
306
307    /// City name.
308    pub fn city(&mut self, city: impl Into<Nullable<String>>) -> &mut Self {
309        self.city = city.into();
310        self
311    }
312
313    /// Postal code. Required for US addresses
314    pub fn postal_code(&mut self, postal_code: impl Into<Nullable<String>>) -> &mut Self {
315        self.postal_code = postal_code.into();
316        self
317    }
318
319    /// Region name.
320    pub fn region(&mut self, region: impl Into<Nullable<String>>) -> &mut Self {
321        self.region = region.into();
322        self
323    }
324
325    /// Country code.
326    pub fn country_code(
327        &mut self,
328        country_code: impl Into<Nullable<CountryCodeSupported>>,
329    ) -> &mut Self {
330        self.country_code = country_code.into();
331        self
332    }
333
334    /// Custom data to be stored with this address.
335    pub fn custom_data(
336        &mut self,
337        custom_data: impl Into<Nullable<HashMap<String, String>>>,
338    ) -> &mut Self {
339        self.custom_data = custom_data.into();
340        self
341    }
342
343    /// Status of the address.
344    pub fn status(&mut self, status: impl Into<Nullable<Status>>) -> &mut Self {
345        self.status = status.into();
346        self
347    }
348
349    /// Send the request to Paddle and return the response.
350    pub async fn send(&self) -> Result<Address> {
351        self.client
352            .send(
353                self,
354                Method::PATCH,
355                &format!(
356                    "/customers/{}/addresses/{}",
357                    self.customer_id.as_ref(),
358                    self.address_id.as_ref()
359                ),
360            )
361            .await
362    }
363}