paystack/endpoints/
subaccount.rs

1//! Subaccounts
2//! ===========
3//! The Subaccounts API allows you to create and manage subaccounts on your integration.
4//! Subaccounts can be used to split payment between two accounts (your main account and a subaccount).
5
6use super::PAYSTACK_BASE_URL;
7use crate::{
8    CreateSubaccountRequest, HttpClient, PaystackAPIError, PaystackResult, Response,
9    SubaccountsResponseData,
10};
11use std::sync::Arc;
12
13/// A struct to hold all functions in the subaccount API route
14#[derive(Debug, Clone)]
15pub struct SubaccountEndpoints<T: HttpClient + Default> {
16    /// Paystack API Key
17    key: String,
18    /// Base URL for the subaccount route
19    base_url: String,
20    /// Http client for the route
21    http: Arc<T>,
22}
23
24impl<T: HttpClient + Default> SubaccountEndpoints<T> {
25    /// Creates a new SubaccountEndpoints 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 SubaccountEndpoints instance
33    pub fn new(key: Arc<String>, http: Arc<T>) -> SubaccountEndpoints<T> {
34        let base_url = format!("{PAYSTACK_BASE_URL}/subaccount");
35        SubaccountEndpoints {
36            key: key.to_string(),
37            base_url,
38            http,
39        }
40    }
41
42    /// Create a subaccount on your integration
43    ///
44    /// # Arguments
45    /// * `subaccount_request` - The request data to create the subaccount.
46    ///   It should be created with the `CreateSubaccountRequestBuilder` struct.
47    ///
48    /// # Returns
49    /// A Result containing the subaccount response data or an error
50    pub async fn create_subaccount(
51        &self,
52        subaccount_request: CreateSubaccountRequest,
53    ) -> PaystackResult<SubaccountsResponseData> {
54        let url = &self.base_url;
55        let body = serde_json::to_value(subaccount_request)
56            .map_err(|e| PaystackAPIError::Subaccount(e.to_string()))?;
57
58        let response = self
59            .http
60            .post(url, &self.key, &body)
61            .await
62            .map_err(|e| PaystackAPIError::Subaccount(e.to_string()))?;
63
64        let parsed_response: Response<SubaccountsResponseData> = serde_json::from_str(&response)
65            .map_err(|e| PaystackAPIError::Subaccount(e.to_string()))?;
66        Ok(parsed_response)
67    }
68
69    /// List subaccounts available on your integration.
70    ///
71    /// # Arguments
72    /// * `per_page` - Optional number of subaccounts to return per page. Defaults to 50 if None.
73    /// * `page` - Specify exactly what page you want to retrieve. Defaults to 1 if None.
74    ///
75    /// # Returns
76    /// A Result containing a vector of subaccount data or an error.
77    pub async fn list_subaccounts(
78        &self,
79        per_page: Option<u32>,
80        page: Option<u32>,
81    ) -> PaystackResult<Vec<SubaccountsResponseData>> {
82        let url = self.base_url.to_string();
83
84        let per_page = per_page.unwrap_or(50).to_string();
85        let page = page.unwrap_or(1).to_string();
86        let query = vec![("perPage", per_page.as_str()), ("page", page.as_str())];
87
88        let response = self
89            .http
90            .get(&url, &self.key, Some(&query))
91            .await
92            .map_err(|e| PaystackAPIError::Subaccount(e.to_string()))?;
93
94        let parsed_response: Response<Vec<SubaccountsResponseData>> =
95            serde_json::from_str(&response)
96                .map_err(|e| PaystackAPIError::Subaccount(e.to_string()))?;
97
98        Ok(parsed_response)
99    }
100
101    /// Get the details of a subaccount on your integration
102    ///
103    /// # Arguments
104    /// * `id_or_code` - The subaccount ID or code you want to fetch
105    ///
106    /// # Returns
107    /// A Result containing the details of the subaccount or an error.
108    pub async fn fetch_subaccount(
109        &self,
110        id_or_code: String,
111    ) -> PaystackResult<SubaccountsResponseData> {
112        let url = format!("{}/{}", self.base_url, id_or_code);
113
114        let response = self
115            .http
116            .get(&url, &self.key, None)
117            .await
118            .map_err(|e| PaystackAPIError::Subaccount(e.to_string()))?;
119
120        let parsed_response: Response<SubaccountsResponseData> = serde_json::from_str(&response)
121            .map_err(|e| PaystackAPIError::Subaccount(e.to_string()))?;
122
123        Ok(parsed_response)
124    }
125
126    /// Update a subaccount details in your integration
127    ///
128    /// # Arguments
129    /// * `id_or_code` - Subaccount's ID or code
130    /// * `update_request` - The request data to update the subaccount.
131    ///   It should be created with the `CreateSubaccountRequestBuilder` struct.
132    ///
133    /// # Returns
134    /// A Result containing the updated subaccount response data or an error
135    pub async fn update_subaccount(
136        &self,
137        id_or_code: String,
138        update_request: CreateSubaccountRequest,
139    ) -> PaystackResult<SubaccountsResponseData> {
140        let url = format!("{}/{}", self.base_url, id_or_code);
141        let body = serde_json::to_value(update_request)
142            .map_err(|e| PaystackAPIError::Subaccount(e.to_string()))?;
143
144        let response = self
145            .http
146            .put(&url, &self.key, &body)
147            .await
148            .map_err(|e| PaystackAPIError::Subaccount(e.to_string()))?;
149
150        let parsed_response: Response<SubaccountsResponseData> = serde_json::from_str(&response)
151            .map_err(|e| PaystackAPIError::Subaccount(e.to_string()))?;
152
153        Ok(parsed_response)
154    }
155}