diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..96e78a6 --- /dev/null +++ b/.github/workflows/test.yml @@ -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 diff --git a/README.md b/README.md index 6e1d837..a380b72 100644 --- a/README.md +++ b/README.md @@ -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? diff --git a/src/paystack.rs b/src/paystack.rs index 3548718..e86afcd 100644 --- a/src/paystack.rs +++ b/src/paystack.rs @@ -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; @@ -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), } } } diff --git a/src/paystack/transactions.rs b/src/paystack/transactions.rs index cae4347..8c38f40 100644 --- a/src/paystack/transactions.rs +++ b/src/paystack/transactions.rs @@ -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. @@ -110,7 +110,7 @@ pub struct ListTransactionsParams { pub amount: Option, } -#[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, @@ -136,7 +136,7 @@ pub struct ChargeAuthorizationBody { pub queue: Option, } -#[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. @@ -153,7 +153,7 @@ pub struct TransactionsTotal { pub to: Option>, } -#[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, @@ -165,7 +165,7 @@ pub struct CheckAuthorizationBody { pub currency: Option, } -#[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, @@ -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: "randomemail@gmail.com".to_string(), + /// amount: 10000, + /// ..Default::default() + /// }; + /// paystack.transaction.initialize_transaction(body); + /// ``` pub fn initialize_transaction( &self, body: InitializeTransactionBody, @@ -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 { let full_url = format!( "{}/transaction/verify/:{}", @@ -236,11 +258,32 @@ 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 { 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 { let url = format!("{}/{}", TRANSACTION_URL, transaction_id); let res = make_get_request(&self.bearer_auth, &url, None::); @@ -248,6 +291,20 @@ impl Transaction { } /// 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: "randomemail@gmail.com".to_string(), + /// authorization_code: "2aeserqwdEAW".to_string(), + /// ..Default::default() + /// }; + /// paystack.transaction.charge_authorization(body); pub fn charge_authorization( &self, params: ChargeAuthorizationBody, @@ -268,12 +325,33 @@ 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: "randomemail@gmail.com".to_string(), + /// authorization_code: "2aeserqwdEAW".to_string(), + /// ..Default::default() + /// }; + /// paystack.transaction.check_authorization(body); pub fn check_authorization(&self, param: CheckAuthorizationBody) -> Result { 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 { let full_url = format!("{}/timeline/{}", TRANSACTION_URL, id).to_string(); let res = make_get_request(&self.bearer_auth, &full_url, None::); @@ -281,6 +359,14 @@ impl Transaction { } /// 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, @@ -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, @@ -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: "randomemail@gmail.com".to_string(), + /// authorization_code: "2aeserqwdEAW".to_string(), + /// ..Default::default() + /// }; + /// paystack.transaction.partial_debit(body); pub fn partial_debit(&self, body: PartialDebitBody) -> Result { let full_url = format!("{}/partial_debit", TRANSACTION_URL); let res = make_request(&self.bearer_auth, &full_url, Some(body), REQUEST::POST);