paystack/endpoints/
customers.rs

1//! Customers
2//! =========
3//! Thse Customers API allows you to create and maange customers on your integration
4
5use std::{marker::PhantomData, sync::Arc};
6
7use serde_json::json;
8
9use crate::{
10    CreateCustomerRequest, CustomerResponseData, HttpClient, PaystackAPIError, PaystackResult,
11    Response, RiskAction, UpdateCustomerRequest, ValidateCustomerRequest,
12};
13
14/// A struct to hold all the functions of the customers API endpoint
15#[derive(Debug, Clone)]
16pub struct CustomersEndpoints<T: HttpClient + Default> {
17    /// Paystack API key
18    key: String,
19    /// Base URL for the customer route
20    base_url: String,
21    /// Http client for the route
22    http: Arc<T>,
23}
24
25impl<T: HttpClient + Default> CustomersEndpoints<T> {
26    /// Constructor
27    pub fn new(key: Arc<String>, http: Arc<T>) -> CustomersEndpoints<T> {
28        let base_url = String::from("https://api.paystack.co/customer");
29        CustomersEndpoints {
30            key: key.to_string(),
31            base_url,
32            http,
33        }
34    }
35
36    /// Create customer on your integration
37    ///
38    /// It takes the following parameters:
39    ///     - create_customer_request: contains the information about the customer to be created.
40    ///     It should be built with `CreateCustomerRequestBuilder`.
41    pub async fn create_customer(
42        &self,
43        create_customer_request: CreateCustomerRequest,
44    ) -> PaystackResult<CustomerResponseData> {
45        let url = format!("{}", self.base_url);
46        let body = serde_json::to_value(create_customer_request)
47            .map_err(|e| PaystackAPIError::Customer(e.to_string()))?;
48
49        let response = self.http.post(&url, &self.key, &body).await;
50
51        match response {
52            Ok(response) => {
53                let parsed_response: Response<CustomerResponseData> =
54                    serde_json::from_str(&response)
55                        .map_err(|e| PaystackAPIError::Customer(e.to_string()))?;
56
57                Ok(parsed_response)
58            }
59            Err(e) => Err(PaystackAPIError::Customer(e.to_string())),
60        }
61    }
62
63    /// List customers available on your integration
64    ///
65    /// It takes the following parameters:
66    ///     - `per_page`: Specify how many records you want to retreive per page. If not specified, default value of 50.
67    ///     - `page`: Specify exactly waht page you want to retreive. If not specified, default value of 1.
68    pub async fn list_customers(
69        &self,
70        per_page: Option<u8>,
71        page: Option<u8>,
72    ) -> PaystackResult<Vec<CustomerResponseData>> {
73        let url = format!("{}", self.base_url);
74
75        let per_page = per_page.unwrap_or(50).to_string();
76        let page = page.unwrap_or(1).to_string();
77        let query = vec![("perPage", per_page.as_str()), ("page", page.as_str())];
78
79        let response = self.http.get(&url, &self.key, Some(&query)).await;
80
81        match response {
82            Ok(response) => {
83                let parsed_response: Response<Vec<CustomerResponseData>> =
84                    serde_json::from_str(&response)
85                        .map_err(|e| PaystackAPIError::Customer(e.to_string()))?;
86
87                Ok(parsed_response)
88            }
89            Err(e) => Err(PaystackAPIError::Customer(e.to_string())),
90        }
91    }
92
93    /// Get details of a customer on your integration.
94    ///
95    /// It takes the following parameters:
96    ///     - `email_or_code`: An `email`or `customer code` for the customer you want to fetch.
97    pub async fn fetch_customer(
98        &self,
99        email_or_code: String,
100    ) -> PaystackResult<CustomerResponseData> {
101        let url = format!("{}/{}", self.base_url, email_or_code);
102
103        let response = self.http.get(&url, &self.key, None).await;
104
105        match response {
106            Ok(response) => {
107                let parsed_response: Response<CustomerResponseData> =
108                    serde_json::from_str(&response)
109                        .map_err(|e| PaystackAPIError::Customer(e.to_string()))?;
110
111                Ok(parsed_response)
112            }
113            Err(e) => Err(PaystackAPIError::Customer(e.to_string())),
114        }
115    }
116
117    /// Update a customer's details on your integration
118    ///
119    /// It takes the following parameters:
120    ///     - `customer_code`: The customer's code
121    ///     - `update_customer_request`: The data to update the customer with.
122    ///     It should be created with the `UpdateCustomerRequestBuilder` struct.
123    pub async fn update_customer(
124        &self,
125        customer_code: String,
126        update_customer_request: UpdateCustomerRequest,
127    ) -> PaystackResult<CustomerResponseData> {
128        let url = format!("{}/{}", self.base_url, customer_code);
129        let body = serde_json::to_value(update_customer_request)
130            .map_err(|e| PaystackAPIError::Customer(e.to_string()))?;
131
132        let response = self.http.put(&url, &self.key, &body).await;
133
134        match response {
135            Ok(response) => {
136                let parsed_response: Response<CustomerResponseData> =
137                    serde_json::from_str(&response)
138                        .map_err(|e| PaystackAPIError::Customer(e.to_string()))?;
139
140                Ok(parsed_response)
141            }
142            Err(e) => Err(PaystackAPIError::Customer(e.to_string())),
143        }
144    }
145
146    /// Validate a customer's identity
147    ///
148    /// It takes in the following parameters:
149    ///     - `customer_code`: email, or customer code of customer to be identified.
150    ///     - `customer_validation_request`: The data to validate the customer with.
151    /// It should be created with the `ValidateCustomerRequestBuilder` struct.
152    pub async fn validate_customer(
153        &self,
154        customer_code: String,
155        customer_validation_request: ValidateCustomerRequest,
156    ) -> PaystackResult<PhantomData<String>> {
157        let url = format!("{}/{}/identification", self.base_url, customer_code);
158        let body = serde_json::to_value(customer_validation_request)
159            .map_err(|e| PaystackAPIError::Customer(e.to_string()))?;
160
161        let response = self.http.post(&url, &self.key, &body).await;
162
163        match response {
164            Ok(response) => {
165                let parsed_response: Response<PhantomData<String>> =
166                    serde_json::from_str(&response)
167                        .map_err(|e| PaystackAPIError::Customer(e.to_string()))?;
168
169                Ok(parsed_response)
170            }
171            Err(e) => Err(PaystackAPIError::Customer(e.to_string())),
172        }
173    }
174
175    /// Whitelist or blacklist a customer on your integration
176    ///
177    /// It takes in the following parameters:
178    ///     - `customer_code`: Customer's code, or email address.
179    ///     - `risk_action`: One of the possible risk actions for the customer.
180    pub async fn whitelist_or_blacklist_customer(
181        &self,
182        customer_code: String,
183        risk_action: RiskAction,
184    ) -> PaystackResult<CustomerResponseData> {
185        let url = format!("{}/set_risk_action", self.base_url);
186        let body = json!({
187            "customer": customer_code,
188            "risk_action": risk_action
189        });
190
191        let response = self.http.post(&url, &self.key, &body).await;
192
193        match response {
194            Ok(response) => {
195                let parsed_response: Response<CustomerResponseData> =
196                    serde_json::from_str(&response)
197                        .map_err(|e| PaystackAPIError::Customer(e.to_string()))?;
198
199                Ok(parsed_response)
200            }
201            Err(e) => Err(PaystackAPIError::Customer(e.to_string())),
202        }
203    }
204
205    /// Deactivate an authorization when the card needs to be forgotten
206    ///
207    /// It takes the following parameters:
208    ///     - `authorization_code`: Authorization code to be deactivated.
209    pub async fn deactivate_authorization(
210        &self,
211        authorization_code: String,
212    ) -> PaystackResult<PhantomData<String>> {
213        let url = format!("{}/authorization/deactivate", self.base_url);
214        let body = json!({
215            "authorization_code": authorization_code
216        });
217
218        let response = self.http.post(&url, &self.key, &body).await;
219
220        match response {
221            Ok(response) => {
222                let parsed_response: Response<PhantomData<String>> =
223                    serde_json::from_str(&response)
224                        .map_err(|e| PaystackAPIError::Customer(e.to_string()))?;
225
226                Ok(parsed_response)
227            }
228            Err(e) => Err(PaystackAPIError::Customer(e.to_string())),
229        }
230    }
231}