Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -24,6 +25,8 @@ pub struct PaystackClient<T: HttpClient + Default> {
pub customers: CustomersEndpoints<T>,
/// Dedicated Virtual Account API route
pub dedicated_virtual_account: DedicatedVirtualAccountEndpoints<T>,
/// Apple Pay API route
pub apple_pay: ApplePayEndpoints<T>,
}

impl<T: HttpClient + Default> PaystackClient<T> {
Expand All @@ -41,6 +44,7 @@ impl<T: HttpClient + Default> PaystackClient<T> {
Arc::clone(&key),
Arc::clone(&http),
),
apple_pay: ApplePayEndpoints::new(Arc::clone(&key), Arc::clone(&http)),
}
}
}
112 changes: 112 additions & 0 deletions src/endpoints/apple_pay.rs
Original file line number Diff line number Diff line change
@@ -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<T: HttpClient + Default> {
/// Paystack API key
key: String,
/// Base URL for the apple pay route
base_url: String,
/// Http client for the route
http: Arc<T>,
}

impl<T: HttpClient + Default> ApplePayEndpoints<T> {
/// 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<String>, http: Arc<T>) -> ApplePayEndpoints<T> {
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<PhantomData<String>> {
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<PhantomData<String>> =
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<ApplePayResponseData> {
let url = format!("{}", self.base_url);

let response = self.http.get(&url, &self.key, None).await;

match response {
Ok(response) => {
let parsed_response: Response<ApplePayResponseData> =
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<PhantomData<String>> {
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<PhantomData<String>> =
serde_json::from_str(&response)
.map_err(|e| PaystackAPIError::ApplePay(e.to_string()))?;

Ok(parsed_response)
}
Err(e) => Err(PaystackAPIError::ApplePay(e.to_string())),
}
}
}
2 changes: 2 additions & 0 deletions src/endpoints/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
pub mod apple_pay;
pub mod customers;
pub mod dedicated_virtual_account;
pub mod subaccount;
Expand All @@ -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::*;
Expand Down
4 changes: 3 additions & 1 deletion src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),
}
7 changes: 7 additions & 0 deletions src/models/apple_pay.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
use serde::{Deserialize, Serialize};

#[derive(Debug, Serialize, Deserialize, Clone, Default)]
pub struct ApplePayResponseData {
#[serde(rename = "domainNames")]
pub domain_names: Vec<String>,
}
2 changes: 2 additions & 0 deletions src/models/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
pub mod apple_pay;
pub mod authorization;
pub mod bearer;
pub mod channel;
Expand All @@ -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::*;
Expand Down
41 changes: 41 additions & 0 deletions tests/api/apple_pay.rs
Original file line number Diff line number Diff line change
@@ -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() {}
1 change: 1 addition & 0 deletions tests/api/main.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
pub mod apple_pay;
pub mod charge;
pub mod customer;
pub mod dedicated_virtual_account;
Expand Down