Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: move express-request and transaction reversal to builder pattern #88

Merged
merged 35 commits into from
Jan 28, 2024
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
7c53407
chore: move express-request to builder pattern
itsyaasir Nov 15, 2023
c85bea8
chore: migrate api, reorganise imports and remove redundant tests
itsyaasir Nov 18, 2023
1241c25
chore: remove unecessary deps
itsyaasir Nov 18, 2023
2e840db
chore: fix imports order
itsyaasir Nov 18, 2023
9bad181
chore: remove vscode files
itsyaasir Nov 18, 2023
f0fa2d7
Add more tests
itsyaasir Nov 18, 2023
9531c4f
Add validator module and implement phone number validation
itsyaasir Nov 18, 2023
30e1988
chore: rename method
itsyaasir Nov 19, 2023
12672cf
Fix phone number validation and remove unnecessary
itsyaasir Nov 22, 2023
fefa13c
Add more variants for phone validator
itsyaasir Nov 22, 2023
667a8c6
Merge branch 'master' into chore/move-express-request-tx-reversal
itsyaasir Nov 22, 2023
59c4e0c
Fix URL path in express_request.rs and
itsyaasir Nov 22, 2023
6029743
Fix import order in lib.rs
itsyaasir Nov 22, 2023
ffd7689
Update amount field from f64 to u32 in
itsyaasir Nov 23, 2023
357bf5a
Merge branch 'master' into chore/move-express-request-tx-reversal
itsyaasir Nov 30, 2023
a011ed6
Update dependencies and add receiver identifier
itsyaasir Nov 30, 2023
733e06d
Merge branch 'master' into chore/move-express-request-tx-reversal
itsyaasir Jan 6, 2024
90ab130
Fix merge conflicts
itsyaasir Jan 6, 2024
ae5fa3e
Fix doc tests
itsyaasir Jan 6, 2024
87e9eb8
Fix dotenvy crate
itsyaasir Jan 6, 2024
376e55b
Fix: dotenv failure to read .env messages
itsyaasir Jan 28, 2024
80038b3
fix: uninitialized pass key
itsyaasir Jan 28, 2024
30a1d1d
fix: timestamp
itsyaasir Jan 28, 2024
bc5b783
chore: clean up codes
itsyaasir Jan 28, 2024
6007cad
fix: compilation
itsyaasir Jan 28, 2024
bbef3b6
chore: update intiaitor password
itsyaasir Jan 28, 2024
94d9a46
chore: revert removal of identifier receiver
itsyaasir Jan 28, 2024
113c5aa
chore: revert removal of identifier receiver
itsyaasir Jan 28, 2024
ab23d7b
chore: revert removal of identifier receiver
itsyaasir Jan 28, 2024
3466e9e
fix: express request tests
itsyaasir Jan 28, 2024
6d81444
fix: express request tests
itsyaasir Jan 28, 2024
33641a8
fix: express request tests
itsyaasir Jan 28, 2024
1687128
fix: express request tests
itsyaasir Jan 28, 2024
32c11cd
chore: refactor codes
itsyaasir Jan 28, 2024
25dc220
further investigation
itsyaasir Jan 28, 2024
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
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,6 @@
/.idea
Cargo.lock
.env
.DS_Store
.DS_Store

.vscode
5 changes: 0 additions & 5 deletions .vscode/settings.json

This file was deleted.

49 changes: 26 additions & 23 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,28 +9,6 @@ repository = "https://github.com/collinsmuriuki/mpesa-rust"
readme = "./README.md"
license = "MIT"

[dependencies]
cached = { version = "0.46", features = ["wasm", "async", "proc_macro"] }
chrono = { version = "0.4", optional = true, default-features = false, features = [
"clock",
"serde",
] }
openssl = { version = "0.10", optional = true }
reqwest = { version = "0.11", features = ["json"] }
derive_builder = "0.12"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
serde_repr = "0.1"
thiserror = "1.0.37"
wiremock = "0.5"
secrecy = "0.8.0"
serde-aux = "4.2.0"

[dev-dependencies]
dotenv = "0.15"
tokio = { version = "1", features = ["rt", "rt-multi-thread", "macros"] }
wiremock = "0.5"

[features]
default = [
"account_balance",
Expand All @@ -42,7 +20,7 @@ default = [
"express_request",
"transaction_reversal",
"transaction_status",
"dynamic_qr"
"dynamic_qr",
]
dynamic_qr = []
account_balance = ["dep:openssl"]
Expand All @@ -54,3 +32,28 @@ c2b_simulate = []
express_request = ["dep:chrono"]
transaction_reversal = ["dep:openssl"]
transaction_status = ["dep:openssl"]


[dependencies]
cached = { version = "0.46", features = ["wasm", "async", "proc_macro"] }
chrono = { version = "0.4", optional = true, default-features = false, features = [
"clock",
"serde",
] }
openssl = { version = "0.10", optional = true }
reqwest = { version = "0.11", features = ["json"] }
derive_builder = "0.12"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
serde_repr = "0.1"
thiserror = "1.0"
secrecy = "0.8"
serde-aux = "4.2"
url = { version = "2", features = ["serde"] }
regex = { version = "1.10", default-features = false, features = ["std"] }


[dev-dependencies]
dotenv = "0.15"
tokio = { version = "1", features = ["rt", "rt-multi-thread", "macros"] }
wiremock = "0.5"
31 changes: 14 additions & 17 deletions src/client.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use std::cell::RefCell;
use std::time::Duration;

use cached::Cached;
use openssl::base64;
Expand All @@ -13,9 +14,10 @@ use crate::auth::AUTH;
use crate::environment::ApiEnvironment;
use crate::services::{
AccountBalanceBuilder, B2bBuilder, B2cBuilder, BulkInvoiceBuilder, C2bRegisterBuilder,
C2bSimulateBuilder, CancelInvoiceBuilder, DynamicQR, DynamicQRBuilder,
MpesaExpressRequestBuilder, OnboardBuilder, OnboardModifyBuilder, ReconciliationBuilder,
SingleInvoiceBuilder, TransactionReversalBuilder, TransactionStatusBuilder,
C2bSimulateBuilder, CancelInvoiceBuilder, DynamicQR, DynamicQRBuilder, MpesaExpress,
MpesaExpressBuilder, OnboardBuilder, OnboardModifyBuilder, ReconciliationBuilder,
SingleInvoiceBuilder, TransactionReversal, TransactionReversalBuilder,
TransactionStatusBuilder,
};
use crate::{auth, MpesaResult};

Expand Down Expand Up @@ -47,15 +49,15 @@ impl<'mpesa, Env: ApiEnvironment> Mpesa<Env> {
/// ```
///
/// # Panics
/// This method can panic if a TLS backend cannot be initialized for the internal http_client
/// This method can panic if a TLS backend cannot be initialized for the
/// internal http_client
pub fn new<S: Into<String>>(client_key: S, client_secret: S, environment: Env) -> Self {
let http_client = HttpClient::builder()
.connect_timeout(std::time::Duration::from_millis(10_000))
.connect_timeout(Duration::from_secs(10))
.user_agent(format!("mpesa-rust@{CARGO_PACKAGE_VERSION}"))
// TODO: Potentialy return a `Result` enum from Mpesa::new?
// Making assumption that creation of http client cannot fail
.build()
.expect("Error building http client");

Self {
client_key: client_key.into(),
client_secret: Secret::new(client_secret.into()),
Expand All @@ -71,6 +73,7 @@ impl<'mpesa, Env: ApiEnvironment> Mpesa<Env> {
let Some(p) = &*self.initiator_password.borrow() else {
return DEFAULT_INITIATOR_PASSWORD.to_owned();
};

p.expose_secret().into()
}

Expand Down Expand Up @@ -466,23 +469,17 @@ impl<'mpesa, Env: ApiEnvironment> Mpesa<Env> {
/// .send();
/// ```
#[cfg(feature = "express_request")]
pub fn express_request(
&'mpesa self,
business_short_code: &'mpesa str,
) -> MpesaExpressRequestBuilder<'mpesa, Env> {
MpesaExpressRequestBuilder::new(self, business_short_code)
pub fn express_request(&'mpesa self) -> MpesaExpressBuilder<'mpesa, Env> {
MpesaExpress::builder(self)
}

///**Transaction Reversal Builder**
/// Reverses a B2B, B2C or C2B M-Pesa transaction.
///
/// See more from the Safaricom API docs [here](https://developer.safaricom.co.ke/Documentation)
#[cfg(feature = "transaction_reversal")]
pub fn transaction_reversal(
&'mpesa self,
initiator_name: &'mpesa str,
) -> TransactionReversalBuilder<'mpesa, Env> {
TransactionReversalBuilder::new(self, initiator_name)
pub fn transaction_reversal(&'mpesa self) -> TransactionReversalBuilder<'mpesa, Env> {
TransactionReversal::builder(self)
}

///**Transaction Status Builder**
Expand Down
3 changes: 2 additions & 1 deletion src/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use serde_repr::{Deserialize_repr, Serialize_repr};
use crate::MpesaError;

/// Mpesa command ids
#[derive(Debug, Serialize, Deserialize)]
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
pub enum CommandId {
TransactionReversal,
SalaryPayment,
Expand Down Expand Up @@ -39,6 +39,7 @@ pub enum IdentifierTypes {
MSISDN = 1,
TillNumber = 2,
ShortCode = 4,
Reversal = 11,
}

impl Display for IdentifierTypes {
Expand Down
6 changes: 6 additions & 0 deletions src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,9 @@ impl From<derive_builder::UninitializedFieldError> for MpesaError {
Self::BuilderError(BuilderError::UninitializedField(e.field_name()))
}
}

impl From<url::ParseError> for MpesaError {
fn from(e: url::ParseError) -> Self {
Self::BuilderError(BuilderError::ValidationError(e.to_string()))
}
}
3 changes: 2 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ mod constants;
pub mod environment;
mod errors;
pub mod services;
pub mod validator;

pub use client::Mpesa;
pub use constants::{
Expand All @@ -14,4 +15,4 @@ pub use constants::{
};
pub use environment::ApiEnvironment;
pub use environment::Environment::{self, Production, Sandbox};
pub use errors::{MpesaError, MpesaResult, ResponseError};
pub use errors::{BuilderError, MpesaError, MpesaResult, ResponseError};
Loading
Loading