diff --git a/src/client.rs b/src/client.rs index 47570e4..f39f88d 100644 --- a/src/client.rs +++ b/src/client.rs @@ -2,8 +2,9 @@ //! ========= //! This file contains the Paystack API client, and it associated endpoints. use crate::{ - CustomersEndpoints, DedicatedVirtualAccountEndpoints, HttpClient, SubaccountEndpoints, - TerminalEndpoints, TransactionEndpoints, TransactionSplitEndpoints, VirtualTerminalEndpoints, + ApplePayEndpoints, CustomersEndpoints, DedicatedVirtualAccountEndpoints, HttpClient, + SubaccountEndpoints, TerminalEndpoints, TransactionEndpoints, TransactionSplitEndpoints, + VirtualTerminalEndpoints, }; use std::sync::Arc; @@ -24,6 +25,8 @@ pub struct PaystackClient { pub customers: CustomersEndpoints, /// Dedicated Virtual Account API route pub dedicated_virtual_account: DedicatedVirtualAccountEndpoints, + /// Apple Pay API route + pub apple_pay: ApplePayEndpoints, } impl PaystackClient { @@ -41,6 +44,7 @@ impl PaystackClient { Arc::clone(&key), Arc::clone(&http), ), + apple_pay: ApplePayEndpoints::new(Arc::clone(&key), Arc::clone(&http)), } } } diff --git a/src/endpoints/apple_pay.rs b/src/endpoints/apple_pay.rs new file mode 100644 index 0000000..fee6e6b --- /dev/null +++ b/src/endpoints/apple_pay.rs @@ -0,0 +1,112 @@ +//! Apple Pay +//! THe Apple Pay API allows you register your application's top-level domain or subdomain. + +use std::{marker::PhantomData, sync::Arc}; + +use serde_json::json; + +use crate::{ApplePayResponseData, HttpClient, PaystackAPIError, PaystackResult, Response}; + +#[derive(Debug, Clone)] +pub struct ApplePayEndpoints { + /// Paystack API key + key: String, + /// Base URL for the apple pay route + base_url: String, + /// Http client for the route + http: Arc, +} + +impl ApplePayEndpoints { + /// Creates a new ApplePayEndpoints instance + ///Creates a new ApplePayEndpoints instance + /// + /// # Arguments + /// * `key` - The Paystack API key + /// * `http` - The HTTP client implementation to use for API requests + /// + /// # Returns + /// A new ApplePayEndpoints instance + pub fn new(key: Arc, http: Arc) -> ApplePayEndpoints { + let base_url = String::from("https://api.paystack.co/apple-pay/domain"); + ApplePayEndpoints { + key: key.to_string(), + base_url, + http, + } + } + + /// Register a top-level domain or subdomain for your Apple Pay integration. + /// + /// # Arguments + /// * `domain_name` - The domain name to be registered with Apple Pay + /// + /// # Returns + /// A Result containing the registration response or an error + pub async fn register_domain( + &self, + domain_name: String, + ) -> PaystackResult> { + let url = format!("{}", self.base_url); + let body = json!({ + "domainName": domain_name + }); + + let response = self.http.post(&url, &self.key, &body).await; + + match response { + Ok(response) => { + let parsed_response: Response> = + serde_json::from_str(&response) + .map_err(|e| PaystackAPIError::ApplePay(e.to_string()))?; + + Ok(parsed_response) + } + Err(e) => Err(PaystackAPIError::ApplePay(e.to_string())), + } + } + + /// Lists all domains registered on your integration + /// + /// # Returns + /// A Result containing the list of registered domains or an error + pub async fn list_domains(&self) -> PaystackResult { + let url = format!("{}", self.base_url); + + let response = self.http.get(&url, &self.key, None).await; + + match response { + Ok(response) => { + let parsed_response: Response = + serde_json::from_str(&response) + .map_err(|e| PaystackAPIError::ApplePay(e.to_string()))?; + + Ok(parsed_response) + } + Err(e) => Err(PaystackAPIError::ApplePay(e.to_string())), + } + } + + pub async fn unregister_domain( + &self, + domain_name: String, + ) -> PaystackResult> { + let url = format!("{}", self.base_url); + let body = json!({ + "domainName": domain_name + }); + + let response = self.http.delete(&url, &self.key, &body).await; + + match response { + Ok(response) => { + let parsed_response: Response> = + serde_json::from_str(&response) + .map_err(|e| PaystackAPIError::ApplePay(e.to_string()))?; + + Ok(parsed_response) + } + Err(e) => Err(PaystackAPIError::ApplePay(e.to_string())), + } + } +} diff --git a/src/endpoints/mod.rs b/src/endpoints/mod.rs index a9940db..f52dbb7 100644 --- a/src/endpoints/mod.rs +++ b/src/endpoints/mod.rs @@ -1,3 +1,4 @@ +pub mod apple_pay; pub mod customers; pub mod dedicated_virtual_account; pub mod subaccount; @@ -7,6 +8,7 @@ pub mod transaction_split; pub mod virtual_terminal; // public re-export +pub use apple_pay::*; pub use customers::*; pub use dedicated_virtual_account::*; pub use subaccount::*; diff --git a/src/errors.rs b/src/errors.rs index 768e468..6a280d0 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -31,6 +31,8 @@ pub enum PaystackAPIError { /// Error associated with customer #[error("Customer Error: {0}")] Customer(String), - #[error("Dedicated Virtual Account: {0}")] + #[error("Dedicated Virtual Account Error: {0}")] DedicatedVirtualAccount(String), + #[error("Apple Pay Error: {0}")] + ApplePay(String), } diff --git a/src/models/apple_pay.rs b/src/models/apple_pay.rs new file mode 100644 index 0000000..4605d27 --- /dev/null +++ b/src/models/apple_pay.rs @@ -0,0 +1,7 @@ +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Serialize, Deserialize, Clone, Default)] +pub struct ApplePayResponseData { + #[serde(rename = "domainNames")] + pub domain_names: Vec, +} diff --git a/src/models/mod.rs b/src/models/mod.rs index e67e337..3af72eb 100644 --- a/src/models/mod.rs +++ b/src/models/mod.rs @@ -1,3 +1,4 @@ +pub mod apple_pay; pub mod authorization; pub mod bearer; pub mod channel; @@ -16,6 +17,7 @@ pub mod transaction_split; pub mod virtual_terminal; // public re-export +pub use apple_pay::*; pub use authorization::*; pub use bearer::*; pub use channel::*; diff --git a/tests/api/apple_pay.rs b/tests/api/apple_pay.rs new file mode 100644 index 0000000..dc27025 --- /dev/null +++ b/tests/api/apple_pay.rs @@ -0,0 +1,41 @@ +use crate::helpers::get_paystack_client; + +#[tokio::test] +async fn can_list_domains() { + let client = get_paystack_client(); + + let res = client + .apple_pay + .list_domains() + .await + .expect("unable to list domains"); + + assert!(res.status); + assert!(res + .message + .contains("Apple Pay registered domains retrieved")) +} + +#[tokio::test] +async fn can_unregister_domain() { + // Arrange + let client = get_paystack_client(); + + // Act + let domain_name = "example.com".to_string(); + let res = client + .apple_pay + .unregister_domain(domain_name) + .await + .expect("unable to unregister domain"); + + // Assert + assert!(res.status); + assert!(res + .message + .contains("Domain successfully unregistered on Apple Pay")); +} + +// TODO: need elevated permission for some tests on this route +#[tokio::test] +async fn can_register_domain() {} diff --git a/tests/api/main.rs b/tests/api/main.rs index 8444b56..dedc5e2 100644 --- a/tests/api/main.rs +++ b/tests/api/main.rs @@ -1,3 +1,4 @@ +pub mod apple_pay; pub mod charge; pub mod customer; pub mod dedicated_virtual_account;