Skip to content

Commit

Permalink
Merge pull request #5 from OAyomide/finish-modules
Browse files Browse the repository at this point in the history
finish modules
  • Loading branch information
OAyomide authored May 23, 2021
2 parents 90ff490 + ec25be1 commit 5f38854
Show file tree
Hide file tree
Showing 14 changed files with 973 additions and 6 deletions.
54 changes: 54 additions & 0 deletions src/paystack.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
pub mod bulk_charges;
pub mod charge;
pub mod control_panel;
pub mod customers;
pub mod dedicated_nuban;
pub mod disputes;
pub mod invoices;
pub mod miscellaneous;
pub mod payment_pages;
pub mod plans;
pub mod products;
Expand All @@ -10,9 +15,18 @@ pub mod subaccounts;
pub mod subscription;
pub mod transactions;
pub mod transactions_split;
pub mod transfer_recipients;
pub mod transfers;
pub mod transfers_control;
pub mod verification;

use bulk_charges::BulkCharges;
use charge::Charge;
use control_panel::ControlPanel;
use dedicated_nuban::DedicatedNuban;
use disputes::Disputes;
use invoices::Invoices;
use miscellaneous::Miscellaneous;
use payment_pages::PaymentPages;
use plans::Plans;
use products::Products;
Expand All @@ -22,6 +36,10 @@ use subaccounts::Subaccount;
use subscription::Subscription;
use transactions::Transaction;
use transactions_split::TransactionSplit;
use transfer_recipients::TransferRecipients;
use transfers::Transfers;
use transfers_control::TransfersControl;
use verification::Verification;

#[derive(Default)]
pub struct Paystack {
Expand All @@ -36,6 +54,15 @@ pub struct Paystack {
pub payment_pages: PaymentPages,
pub invoices: Invoices,
pub settlements: Settlements,
pub transfer_recipients: TransferRecipients,
pub transfers: Transfers,
pub transfers_control: TransfersControl,
pub bulk_charges: BulkCharges,
pub control_panel: ControlPanel,
pub charge: Charge,
pub disputes: Disputes,
pub verification: Verification,
pub miscellaneous: Miscellaneous,
}

impl Paystack {
Expand Down Expand Up @@ -76,6 +103,33 @@ impl Paystack {
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(),
},
}
}
}
114 changes: 114 additions & 0 deletions src/paystack/bulk_charges.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
use crate::utils::make_get_request;
use chrono::{DateTime, Local};
use reqwest::blocking::Response;
use serde::Serialize;

/// The Bulk Charges API allows you create and manage multiple recurring payments from your customers
#[derive(Debug, Default)]
pub struct BulkCharges {
pub(crate) bearer_auth: String,
}

// #[derive(Debug, Serialize)]
// pub struct InitiateBulkChargesBody {
// pub
// }

#[derive(Debug, Serialize)]
#[serde(rename_all = "lowercase")]
pub enum BulkChargesStatus {
FAILED,
SUCCESS,
PENDING,
}

#[derive(Debug, Serialize)]
pub struct ListBulkChargesParams {
/// Specify how many records you want to retrieve per page. If not specify we use a default value of 50.
#[serde(rename = "perPage")]
pub per_page: Option<i128>,
/// Specify exactly what page you want to retrieve. If not specify we use a default value of 1.
pub page: Option<i128>,
/// A timestamp from which to start listing product e.g. 2016-09-24T00:00:05.000Z, 2016-09-21
pub from: Option<DateTime<Local>>,
/// A timestamp at which to stop listing product e.g. 2016-09-24T00:00:05.000Z, 2016-09-21
pub to: Option<DateTime<Local>>,
}

#[derive(Debug, Serialize)]
pub struct FetchChargesInABatchParams {
/// Either one of these values: pending, success or failed
pub status: BulkChargesStatus,
/// Specify how many records you want to retrieve per page. If not specify we use a default value of 50.
#[serde(rename = "perPage")]
pub per_page: Option<i128>,
/// Specify exactly what page you want to retrieve. If not specify we use a default value of 1.
pub page: Option<i128>,
/// A timestamp from which to start listing product e.g. 2016-09-24T00:00:05.000Z, 2016-09-21
pub from: Option<DateTime<Local>>,
/// A timestamp at which to stop listing product e.g. 2016-09-24T00:00:05.000Z, 2016-09-21
pub to: Option<DateTime<Local>>,
}
const BULK_CHARGES_URL: &str = "https://api.paystack.co/bulkcharge";
impl BulkCharges {
// FIXME: the docs dont say what it is here, hence I wont be implementing this method until the docs are clear
// pub fn initiate_bulk_charges(&self, body: InitiateBulkChargesBody) -> Result<Response, String> {
// let res = make_request(
// &self.bearer_auth,
// BULK_CHARGES_URL,
// Some(body),
// REQUEST::POST,
// );
// return res;
// }

/// This lists all bulk charge batches created by the integration. Statuses can be active, paused, or complete.
pub fn list_bulk_charges(
&self,
params: Option<ListBulkChargesParams>,
) -> Result<Response, String> {
let res = make_get_request(&self.bearer_auth, BULK_CHARGES_URL, params);
return res;
}

/// This endpoint retrieves a specific batch code.
/// It also returns useful information on its progress by way of the `total_charges` and `pending_charges` attributes.
/// - id_or_code:
/// An ID or code for the charge whose batches you want to retrieve.
pub fn fetch_bulk_charge_batch(&self, id_or_code: &str) -> Result<Response, String> {
let url = format!("{}/{}", BULK_CHARGES_URL, id_or_code);
let res = make_get_request(&self.bearer_auth, &url, None::<String>);
return res;
}
/// This endpoint retrieves the charges associated with a specified batch code. Pagination parameters are available.
/// You can also filter by status. Charge statuses can be pending, success or failed.
/// - id_or_code:
/// An ID or code for the charge whose batches you want to retrieve.
pub fn fetch_charges_in_a_batch(
&self,
id_or_code: &str,
params: FetchChargesInABatchParams,
) -> Result<Response, String> {
let url = format!("{}/{}", BULK_CHARGES_URL, id_or_code);
let res = make_get_request(&self.bearer_auth, &url, Some(params));
return res;
}

/// Use this endpoint to pause processing a batch
/// - batch_code:
/// The batch code for the bulk charge you want to pause
pub fn pause_bulk_charge_batch(&self, batch_code: &str) -> Result<Response, String> {
let url = format!("{}/pause/{}", BULK_CHARGES_URL, batch_code);
let res = make_get_request(&self.bearer_auth, &url, None::<String>);
return res;
}

/// Use this endpoint to pause processing a batch
/// - batch_code:
/// The batch code for the bulk charge you want to pause
pub fn resume_bulk_charge_batch(&self, batch_code: &str) -> Result<Response, String> {
let url = format!("{}/resume/{}", BULK_CHARGES_URL, batch_code);
let res = make_get_request(&self.bearer_auth, &url, None::<String>);
return res;
}
}
136 changes: 136 additions & 0 deletions src/paystack/charge.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
use chrono::{DateTime, Local};
use reqwest::blocking::Response;
use serde::Serialize;
use serde_json::Value as JSON;

use crate::utils::{make_get_request, make_request, REQUEST};

#[derive(Debug, Default)]
pub struct Charge {
pub(crate) bearer_auth: String,
}

#[derive(Debug, Serialize)]
pub struct CreateChargeBody<'a> {
/// Customer's email address
pub email: &'a str,
/// Amount should be in kobo if currency is `NGN`, pesewas, if currency is `GHS`, and cents, if currency is `ZAR`
pub amount: &'a str,
/// Bank account to charge (don't send if charging an authorization code)
pub bank: Option<JSON>,
/// An authorization code to charge (don't send if charging a bank account)
pub authorization_code: Option<&'a str>,
/// 4-digit PIN (send with a non-reusable authorization code)
pub pin: Option<&'a str>,
/// A JSON object
pub metadata: Option<JSON>,
/// Unique transaction reference. Only -, .`, = and alphanumeric characters allowed.
pub reference: Option<&'a str>,
/// USSD type to charge (don't send if charging an authorization code, bank or card)
pub ussd: Option<JSON>,
/// Mobile details (don't send if charging an authorization code, bank or card)
pub mobile_money: Option<JSON>,
/// This is the unique identifier of the device a user uses in making payment.
/// Only -, .`, = and alphanumeric characters allowed.
pub device_id: Option<&'a str>,
}

#[derive(Debug, Serialize)]
pub struct SubmitPinBody<'a> {
/// PIN submitted by user
pub pin: &'a str,
/// Reference for transaction that requested pin
pub reference: &'a str,
}

#[derive(Debug, Serialize)]
pub struct SubmitOTPBody<'a> {
/// OTP submitted by user
pub otp: &'a str,
/// Reference for ongoing transaction
pub reference: &'a str,
}

#[derive(Debug, Serialize)]
pub struct SubmitPhoneBody<'a> {
/// Phone submitted by user
pub phone: &'a str,
/// Reference for ongoing transaction
pub reference: &'a str,
}

#[derive(Debug, Serialize)]
pub struct SubmitBirthdayBody<'a> {
/// Birthday submitted by user e.g. 2016-09-21
pub birthday: DateTime<Local>,
/// Reference for ongoing transaction
pub reference: &'a str,
}

#[derive(Debug, Serialize)]
pub struct SubmitAddressBody<'a> {
/// Address submitted by user
pub address: &'a str,
/// Reference for ongoing transaction
pub reference: &'a str,
/// City submitted by user
pub city: &'a str,
/// State submitted by user
pub state: &'a str,
/// Zipcode submitted by user
pub zipcode: &'a str,
}

const CHARGE_URL: &str = "https://api.paystack.co/charge";
impl Charge {
// TODO: link payment channel here
/// Initiate a payment by integrating the [][payment channel] of your choice.
pub fn create_charge(&self, body: CreateChargeBody) -> Result<Response, String> {
let res = make_request(&self.bearer_auth, CHARGE_URL, Some(body), REQUEST::POST);
return res;
}

/// Submit PIN to continue a charge
pub fn submit_pin(&self, body: SubmitPinBody) -> Result<Response, String> {
let url = format!("{}/submit_pin", CHARGE_URL);
let res = make_request(&self.bearer_auth, &url, Some(body), REQUEST::POST);
return res;
}

/// Submit OTP to complete a charge
pub fn submit_otp(&self, body: SubmitOTPBody) -> Result<Response, String> {
let url = format!("{}/submit_otp", CHARGE_URL);
let res = make_request(&self.bearer_auth, &url, Some(body), REQUEST::POST);
return res;
}

/// Submit phone when requested
pub fn submit_phone(&self, body: SubmitPhoneBody) -> Result<Response, String> {
let url = format!("{}/submit_phone", CHARGE_URL);
let res = make_request(&self.bearer_auth, &url, Some(body), REQUEST::POST);
return res;
}

/// Submit birthday when requested
pub fn submit_birthday(&self, body: SubmitBirthdayBody) -> Result<Response, String> {
let url = format!("{}/submit_birthday", CHARGE_URL);
let res = make_request(&self.bearer_auth, &url, Some(body), REQUEST::POST);
return res;
}

/// Submit address to continue a charge
pub fn submit_address(&self, body: SubmitAddressBody) -> Result<Response, String> {
let url = format!("{}/submit_address", CHARGE_URL);
let res = make_request(&self.bearer_auth, &url, Some(body), REQUEST::POST);
return res;
}

/// When you get "pending" as a charge status or if there was an exception when calling any of the /charge endpoints,
/// wait 10 seconds or more, then make a check to see if its status has changed.
/// Don't call too early as you may get a lot more pending than you should.
pub fn check_pending_charge(&self, reference: &str) -> Result<Response, String> {
let url = format!("{}/{}", CHARGE_URL, reference);
let res = make_get_request(&self.bearer_auth, &url, None::<String>);
return res;
}
}
36 changes: 36 additions & 0 deletions src/paystack/control_panel.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
use reqwest::blocking::Response;
use serde::Serialize;

use crate::utils::{make_get_request, make_request, REQUEST};

/// The Control Panel API allows you manage some settings on your integration
#[derive(Debug, Default)]
pub struct ControlPanel {
pub(crate) bearer_auth: String,
}

#[derive(Debug, Serialize)]
pub struct UpdatePaymentSessionTimeoutBody {
/// Time before stopping session (in seconds). Set to 0 to cancel session timeouts
pub timeout: i64,
}

const CONTROL_PANEL_URL: &str = "https://api.paystack.co/integration";
impl ControlPanel {
/// Fetch the payment session timeout on your integration
pub fn fetch_payment_session_timeout(&self) -> Result<Response, String> {
let url = format!("{}/payment_session_timeout", CONTROL_PANEL_URL);
let res = make_get_request(&self.bearer_auth, &url, None::<String>);
return res;
}

/// Update the payment session timeout on your integration
pub fn update_payment_session_timeout(
&self,
body: UpdatePaymentSessionTimeoutBody,
) -> Result<Response, String> {
let url = format!("{}/payment_session_timeout", CONTROL_PANEL_URL);
let res = make_request(&self.bearer_auth, &url, Some(body), REQUEST::PUT);
return res;
}
}
Loading

0 comments on commit 5f38854

Please sign in to comment.