Skip to content

Commit

Permalink
Merge pull request #10 from deven96/master
Browse files Browse the repository at this point in the history
Implementing basic doctests for transactions to start #8
  • Loading branch information
OAyomide authored Sep 17, 2024
2 parents 2134324 + 723d216 commit d1d96ef
Show file tree
Hide file tree
Showing 4 changed files with 167 additions and 66 deletions.
21 changes: 21 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
name: Build and Test

on:
push:
branches: [ master ]
pull_request:
branches: [ master ]

env:
PAYSTACK_SECRET_KEY: ${{secrets.PAYSTACK_SECRET_KEY}}

jobs:
build:
runs-on: ubuntu-18.04

steps:
- uses: actions/checkout@v2
- name: Build
run: cargo clippy && cargo build --verbose
- name: Run tests
run: cargo test -- --nocapture
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# Paystack-rs

[![Build Status](https://github.com/OAyomide/paystack-rs/workflows/Build%20and%20Test/badge.svg)](https://github.com/OAyomide/paystack-rs/actions)

A rust crate that wraps around the paystack REST API.

## Whats working and whats yet to be done?
Expand Down
92 changes: 31 additions & 61 deletions src/paystack.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,17 @@ pub mod transfers;
pub mod transfers_control;
pub mod verification;

/// Initialize a struct with bearer auth key
#[macro_export]
macro_rules! auth_init {
($Foo: ident, $auth: expr) => {
$Foo {
bearer_auth: $auth.to_string(),
..Default::default()
}
};
}

use bulk_charges::BulkCharges;
use charge::Charge;
use control_panel::ControlPanel;
Expand Down Expand Up @@ -69,67 +80,26 @@ impl Paystack {
pub fn new(key: String) -> Paystack {
let formatted_bearer = format!("Bearer {}", key);
Paystack {
transaction: Transaction {
bearer_auth: formatted_bearer.to_string(),
..Default::default()
},
transaction_split: TransactionSplit {
bearer_auth: formatted_bearer.to_string(),
},
refund: Refunds {
bearer_auth: formatted_bearer.to_string(),
},
subaccounts: Subaccount {
bearer_auth: formatted_bearer.to_string(),
},
dedicated_nuban: DedicatedNuban {
bearer_auth: formatted_bearer.to_string(),
},
plans: Plans {
bearer_auth: formatted_bearer.to_string(),
},
subscription: Subscription {
bearer_auth: formatted_bearer.to_string(),
},
products: Products {
bearer_auth: formatted_bearer.to_string(),
},
payment_pages: PaymentPages {
bearer_auth: formatted_bearer.to_string(),
},
invoices: Invoices {
bearer_auth: formatted_bearer.to_string(),
},
settlements: Settlements {
bearer_auth: formatted_bearer.to_string(),
},
transfer_recipients: TransferRecipients {
bearer_auth: formatted_bearer.to_string(),
},
transfers: Transfers {
bearer_auth: formatted_bearer.to_string(),
},
transfers_control: TransfersControl {
bearer_auth: formatted_bearer.to_string(),
},
bulk_charges: BulkCharges {
bearer_auth: formatted_bearer.to_string(),
},
control_panel: ControlPanel {
bearer_auth: formatted_bearer.to_string(),
},
charge: Charge {
bearer_auth: formatted_bearer.to_string(),
},
disputes: Disputes {
bearer_auth: formatted_bearer.to_string(),
},
verification: Verification {
bearer_auth: formatted_bearer.to_string(),
},
miscellaneous: Miscellaneous {
bearer_auth: formatted_bearer.to_string(),
},
transaction: auth_init!(Transaction, formatted_bearer),
transaction_split: auth_init!(TransactionSplit, formatted_bearer),
refund: auth_init!(Refunds, formatted_bearer),
subaccounts: auth_init!(Subaccount, formatted_bearer),
dedicated_nuban: auth_init!(DedicatedNuban, formatted_bearer),
plans: auth_init!(Plans, formatted_bearer),
subscription: auth_init!(Subscription, formatted_bearer),
products: auth_init!(Products, formatted_bearer),
invoices: auth_init!(Invoices, formatted_bearer),
settlements: auth_init!(Settlements, formatted_bearer),
transfer_recipients: auth_init!(TransferRecipients, formatted_bearer),
transfers: auth_init!(Transfers, formatted_bearer),
transfers_control: auth_init!(TransfersControl, formatted_bearer),
bulk_charges: auth_init!(BulkCharges, formatted_bearer),
control_panel: auth_init!(ControlPanel, formatted_bearer),
disputes: auth_init!(Disputes, formatted_bearer),
verification: auth_init!(Verification, formatted_bearer),
miscellaneous: auth_init!(Miscellaneous, formatted_bearer),
charge: auth_init!(Charge, formatted_bearer),
payment_pages: auth_init!(PaymentPages, formatted_bearer),
}
}
}
118 changes: 113 additions & 5 deletions src/paystack/transactions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ pub struct InitializeTransactionBody {
}

/// struct ListTransactionsQuery
#[derive(Debug, Serialize)]
#[derive(Debug, Default, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct ListTransactionsParams {
/// Specify how many records you want to retrieve per page. If not specify we use a default value of 50.
Expand All @@ -110,7 +110,7 @@ pub struct ListTransactionsParams {
pub amount: Option<i128>,
}

#[derive(Serialize, Debug)]
#[derive(Serialize, Default, Debug)]
pub struct ChargeAuthorizationBody {
/// Amount should be in kobo if currency is NGN, pesewas, if currency is GHS, and cents, if currency is ZAR
pub amount: String,
Expand All @@ -136,7 +136,7 @@ pub struct ChargeAuthorizationBody {
pub queue: Option<bool>,
}

#[derive(Debug, Serialize)]
#[derive(Debug, Default, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct TransactionsTotal {
/// Specify how many records you want to retrieve per page. If not specify we use a default value of 50.
Expand All @@ -153,7 +153,7 @@ pub struct TransactionsTotal {
pub to: Option<DateTime<Utc>>,
}

#[derive(Debug, Serialize)]
#[derive(Debug, Default, Serialize)]
pub struct CheckAuthorizationBody {
/// Amount should be in kobo if currency is NGN, pesewas, if currency is GHS, and cents, if currency is ZAR
pub amount: String,
Expand All @@ -165,7 +165,7 @@ pub struct CheckAuthorizationBody {
pub currency: Option<Currency>,
}

#[derive(Debug, Serialize)]
#[derive(Debug, Default, Serialize)]
pub struct PartialDebitBody {
/// Amount should be in kobo if currency is NGN, pesewas, if currency is GHS, and cents, if currency is ZAR
pub amount: String,
Expand Down Expand Up @@ -211,6 +211,20 @@ pub struct ExportTransactionsBody {

impl Transaction {
/// Initialize a transaction from your backend
/// ```rust
/// # use std::env;
/// # use paystack_rs::prelude::Paystack;
/// use paystack_rs::prelude::InitializeTransactionBody;
///
/// # let key = env::var("PAYSTACK_SECRET_KEY").unwrap();
/// let paystack = Paystack::new(key);
/// let body = InitializeTransactionBody{
/// email: "[email protected]".to_string(),
/// amount: 10000,
/// ..Default::default()
/// };
/// paystack.transaction.initialize_transaction(body);
/// ```
pub fn initialize_transaction(
&self,
body: InitializeTransactionBody,
Expand All @@ -225,6 +239,14 @@ impl Transaction {
}

/// verify a transaction. it takes an argument reference which is the reference_id of a transaction you want to verify
/// ```rust
/// # use std::env;
/// # use paystack_rs::prelude::Paystack;
///
/// # let key = env::var("PAYSTACK_SECRET_KEY").unwrap();
/// let paystack = Paystack::new(key);
/// paystack.transaction.verify_transaction("DG4uishudoq90LD".to_string());
/// ```
pub fn verify_transaction(&self, reference: String) -> Result<Response, String> {
let full_url = format!(
"{}/transaction/verify/:{}",
Expand All @@ -236,18 +258,53 @@ impl Transaction {
}

/// list_transactions lists all the transactions available
/// ```rust
/// # use std::env;
/// # use paystack_rs::prelude::Paystack;
/// use paystack_rs::prelude::ListTransactionsParams;
///
/// # let key = env::var("PAYSTACK_SECRET_KEY").unwrap();
/// let paystack = Paystack::new(key);
/// /// Retrieve 50 transactions per page
/// let body = ListTransactionsParams{
/// per_page: Some(50),
/// ..Default::default()
/// };
/// paystack.transaction.list_transactions(body);
pub fn list_transactions(&self, body: ListTransactionsParams) -> Result<Response, String> {
let res = make_get_request(&self.bearer_auth, TRANSACTION_URL, Some(body));
return res;
}

/// ```rust
/// # use std::env;
/// # use paystack_rs::prelude::Paystack;
///
/// # let key = env::var("PAYSTACK_SECRET_KEY").unwrap();
/// let paystack = Paystack::new(key);
/// paystack.transaction.fetch_transaction(123412);
/// ```
pub fn fetch_transaction(&self, transaction_id: i64) -> Result<Response, String> {
let url = format!("{}/{}", TRANSACTION_URL, transaction_id);
let res = make_get_request(&self.bearer_auth, &url, None::<String>);
return res;
}

/// All authorizations marked as reusable can be charged with this endpoint whenever you need to receive payments.
/// ```rust
/// # use std::env;
/// # use paystack_rs::prelude::Paystack;
/// use paystack_rs::prelude::ChargeAuthorizationBody;
///
/// # let key = env::var("PAYSTACK_SECRET_KEY").unwrap();
/// let paystack = Paystack::new(key);
/// let body = ChargeAuthorizationBody{
/// amount: "5000".to_string(),
/// email: "[email protected]".to_string(),
/// authorization_code: "2aeserqwdEAW".to_string(),
/// ..Default::default()
/// };
/// paystack.transaction.charge_authorization(body);
pub fn charge_authorization(
&self,
params: ChargeAuthorizationBody,
Expand All @@ -268,19 +325,48 @@ impl Transaction {
///
///
/// ⚠️ Warning You shouldn't use this endpoint to check a card for sufficient funds if you are going to charge the user immediately. This is because we hold funds when this endpoint is called which can lead to an insufficient funds error.
/// ```rust
/// # use std::env;
/// # use paystack_rs::prelude::Paystack;
/// use paystack_rs::prelude::CheckAuthorizationBody;
///
/// # let key = env::var("PAYSTACK_SECRET_KEY").unwrap();
/// let paystack = Paystack::new(key);
/// let body = CheckAuthorizationBody{
/// amount: "5000".to_string(),
/// email: "[email protected]".to_string(),
/// authorization_code: "2aeserqwdEAW".to_string(),
/// ..Default::default()
/// };
/// paystack.transaction.check_authorization(body);
pub fn check_authorization(&self, param: CheckAuthorizationBody) -> Result<Response, String> {
let full_url = CHARGE_AUTHORIZATION_URL;
let res = make_request(&self.bearer_auth, full_url, Some(param), REQUEST::POST);
return res;
}

/// ```rust
/// # use std::env;
/// # use paystack_rs::prelude::Paystack;
///
/// # let key = env::var("PAYSTACK_SECRET_KEY").unwrap();
/// let paystack = Paystack::new(key);
/// paystack.transaction.view_transaction_timeline("DG4uishudoq90LD".to_string());
pub fn view_transaction_timeline(&self, id: String) -> Result<Response, String> {
let full_url = format!("{}/timeline/{}", TRANSACTION_URL, id).to_string();
let res = make_get_request(&self.bearer_auth, &full_url, None::<String>);
return res;
}

/// Total amount received on your account
/// ```rust
/// # use std::env;
/// # use paystack_rs::prelude::Paystack;
///
/// # let key = env::var("PAYSTACK_SECRET_KEY").unwrap();
/// let paystack = Paystack::new(key);
/// /// Retrieve total transactions
/// paystack.transaction.transactions_total(None);
pub fn transactions_total(
&self,
params: Option<TransactionsTotal>,
Expand All @@ -291,6 +377,14 @@ impl Transaction {
}

/// Export transactions carried out on your integration.
/// ```rust
/// # use std::env;
/// # use paystack_rs::prelude::Paystack;
///
/// # let key = env::var("PAYSTACK_SECRET_KEY").unwrap();
/// let paystack = Paystack::new(key);
/// /// Retrieve total transactions
/// paystack.transaction.export_transactions(None);
pub fn export_transactions(
&self,
params: Option<ExportTransactionsBody>,
Expand All @@ -301,6 +395,20 @@ impl Transaction {
}

/// Retrieve part of a payment from a customer
/// ```rust
/// # use std::env;
/// # use paystack_rs::prelude::Paystack;
/// use paystack_rs::prelude::PartialDebitBody;
///
/// # let key = env::var("PAYSTACK_SECRET_KEY").unwrap();
/// let paystack = Paystack::new(key);
/// let body = PartialDebitBody{
/// amount: "5000".to_string(),
/// email: "[email protected]".to_string(),
/// authorization_code: "2aeserqwdEAW".to_string(),
/// ..Default::default()
/// };
/// paystack.transaction.partial_debit(body);
pub fn partial_debit(&self, body: PartialDebitBody) -> Result<Response, String> {
let full_url = format!("{}/partial_debit", TRANSACTION_URL);
let res = make_request(&self.bearer_auth, &full_url, Some(body), REQUEST::POST);
Expand Down

0 comments on commit d1d96ef

Please sign in to comment.