paystack/endpoints/
transaction_split.rs

1//! Transaction Split
2//! =================
3//! The Transaction Splits API enables merchants split the settlement for a
4//! transaction across their payout account, and one or more subaccounts.
5
6use super::PAYSTACK_BASE_URL;
7use crate::{
8    DeleteSubAccountBody, HttpClient, PaystackAPIError, PaystackResult, Response, SubaccountBody,
9    TransactionSplitRequest, TransactionSplitResponseData, UpdateTransactionSplitRequest,
10};
11use std::sync::Arc;
12
13/// A struct to hold all the functions of the transaction split API endpoint
14#[derive(Debug, Clone)]
15pub struct TransactionSplitEndpoints<T: HttpClient + Default> {
16    /// Paystack API Key
17    key: String,
18    /// Base URL for the transaction route
19    base_url: String,
20    /// Http client for the route
21    http: Arc<T>,
22}
23
24impl<T: HttpClient + Default> TransactionSplitEndpoints<T> {
25    /// Creates a new TransactionSplitEndpoints instance
26    ///
27    /// # Arguments
28    /// * `key` - The Paystack API key
29    /// * `http` - The HTTP client implementation to use for API requests
30    ///
31    /// # Returns
32    /// A new TransactionSplitEndpoints instance
33    pub fn new(key: Arc<String>, http: Arc<T>) -> TransactionSplitEndpoints<T> {
34        let base_url = format!("{}/split", PAYSTACK_BASE_URL);
35        TransactionSplitEndpoints {
36            key: key.to_string(),
37            base_url,
38            http,
39        }
40    }
41
42    /// Creates a split payment on your integration
43    ///
44    /// # Arguments
45    /// * `split_body` - The request data to create the split payment.
46    ///   It should be created with a `TransactionSplitRequest` struct.
47    ///
48    /// # Returns
49    /// A Result containing the transaction split response data or an error
50    pub async fn create_transaction_split(
51        &self,
52        split_body: TransactionSplitRequest,
53    ) -> PaystackResult<TransactionSplitResponseData> {
54        let url = &self.base_url;
55        let body = serde_json::to_value(split_body)
56            .map_err(|e| PaystackAPIError::TransactionSplit(e.to_string()))?;
57
58        let response = self
59            .http
60            .post(&url, &self.key, &body)
61            .await
62            .map_err(|e| PaystackAPIError::TransactionSplit(e.to_string()))?;
63
64        let parsed_response: Response<TransactionSplitResponseData> =
65            serde_json::from_str(&response)
66                .map_err(|e| PaystackAPIError::TransactionSplit(e.to_string()))?;
67        Ok(parsed_response)
68    }
69
70    /// Lists transaction splits available on your integration
71    ///
72    /// # Arguments
73    /// * `split_name` - Optional name of the split to retrieve
74    /// * `split_active` - Optional status of the split to retrieve
75    ///
76    /// # Returns
77    /// A Result containing a vector of transaction split response data or an error
78    pub async fn list_transaction_splits(
79        &self,
80        split_name: Option<&str>,
81        split_active: Option<bool>,
82    ) -> PaystackResult<Vec<TransactionSplitResponseData>> {
83        let url = &self.base_url;
84
85        // Specify a default option for active splits
86        let split_active = match split_active {
87            Some(active) => active.to_string(),
88            None => "".to_string(),
89        };
90
91        let query = vec![
92            ("name", split_name.unwrap_or("")),
93            ("active", &split_active),
94        ];
95
96        let response = self
97            .http
98            .get(&url, &self.key, Some(&query))
99            .await
100            .map_err(|e| PaystackAPIError::TransactionSplit(e.to_string()))?;
101
102        let parsed_response: Response<Vec<TransactionSplitResponseData>> =
103            serde_json::from_str(&response)
104                .map_err(|e| PaystackAPIError::TransactionSplit(e.to_string()))?;
105
106        Ok(parsed_response)
107    }
108
109    /// Gets details of a split on your integration
110    ///
111    /// # Arguments
112    /// * `split_id` - ID of the transaction split to fetch
113    ///
114    /// # Returns
115    /// A Result containing the transaction split response data or an error
116    pub async fn fetch_transaction_split(
117        &self,
118        split_id: &str,
119    ) -> PaystackResult<TransactionSplitResponseData> {
120        let url = format!("{}/{}", self.base_url, split_id);
121
122        let response = self
123            .http
124            .get(&url, &self.key, None)
125            .await
126            .map_err(|e| PaystackAPIError::TransactionSplit(e.to_string()))?;
127
128        let parsed_response: Response<TransactionSplitResponseData> =
129            serde_json::from_str(&response)
130                .map_err(|e| PaystackAPIError::TransactionSplit(e.to_string()))?;
131
132        Ok(parsed_response)
133    }
134
135    /// Updates a transaction split's details on your integration
136    ///
137    /// # Arguments
138    /// * `split_id` - ID of the split to update
139    /// * `update_body` - The update data for the transaction split.
140    ///   It should be created with the `UpdateTransactionSplitRequestBuilder` struct.
141    ///
142    /// # Returns
143    /// A Result containing the updated transaction split response data or an error
144    pub async fn update_transaction_split(
145        &self,
146        split_id: &str,
147        update_body: UpdateTransactionSplitRequest,
148    ) -> PaystackResult<TransactionSplitResponseData> {
149        let url = format!("{}/{}", self.base_url, split_id);
150        let body = serde_json::to_value(update_body)
151            .map_err(|e| PaystackAPIError::TransactionSplit(e.to_string()))?;
152
153        let response = self
154            .http
155            .put(&url, &self.key, &body)
156            .await
157            .map_err(|e| PaystackAPIError::TransactionSplit(e.to_string()))?;
158
159        let parsed_response: Response<TransactionSplitResponseData> =
160            serde_json::from_str(&response)
161                .map_err(|e| PaystackAPIError::TransactionSplit(e.to_string()))?;
162        Ok(parsed_response)
163    }
164
165    /// Adds a subaccount to a transaction split or updates an existing subaccount's share
166    ///
167    /// # Arguments
168    /// * `split_id` - ID of the transaction split to update
169    /// * `body` - The subaccount data to add or update.
170    ///   It should be created with a `SubaccountBody` struct.
171    ///
172    /// # Returns
173    /// A Result containing the transaction split response data or an error
174    pub async fn add_or_update_subaccount_split(
175        &self,
176        split_id: &str,
177        body: SubaccountBody,
178    ) -> PaystackResult<TransactionSplitResponseData> {
179        let url = format!("{}/{}/subaccount/add", self.base_url, split_id);
180        let body = serde_json::to_value(body)
181            .map_err(|e| PaystackAPIError::TransactionSplit(e.to_string()))?;
182
183        let response = self
184            .http
185            .post(&url, &self.key, &body)
186            .await
187            .map_err(|e| PaystackAPIError::TransactionSplit(e.to_string()))?;
188
189        let parsed_response: Response<TransactionSplitResponseData> =
190            serde_json::from_str(&response)
191                .map_err(|e| PaystackAPIError::TransactionSplit(e.to_string()))?;
192
193        Ok(parsed_response)
194    }
195
196    /// Removes a subaccount from a transaction split
197    ///
198    /// # Arguments
199    /// * `split_id` - ID of the transaction split.
200    /// * `subaccount` - The subaccount data to remove.
201    ///   It should be created with a `DeleteSubAccountBody` struct.
202    ///
203    /// # Returns
204    /// A Result containing a success message or an error
205    pub async fn remove_subaccount_from_transaction_split(
206        &self,
207        split_id: &str,
208        subaccount: DeleteSubAccountBody,
209    ) -> PaystackResult<String> {
210        let url = format!("{}/{}/subaccount/remove", self.base_url, split_id);
211        let body = serde_json::to_value(subaccount)
212            .map_err(|e| PaystackAPIError::TransactionSplit(e.to_string()))?;
213
214        let response = self
215            .http
216            .post(&url, &self.key, &body)
217            .await
218            .map_err(|e| PaystackAPIError::TransactionSplit(e.to_string()))?;
219
220        let parsed_response: Response<String> = serde_json::from_str(&response)
221            .map_err(|e| PaystackAPIError::TransactionSplit(e.to_string()))?;
222
223        Ok(parsed_response)
224    }
225}