Skip to main content

daraja_sdk/
lib.rs

1//! # Daraja SDK
2//!
3//! A memory-safe Rust SDK for [Safaricom Daraja](https://developer.safaricom.co.ke/) (M-Pesa API 3.0),
4//! focused on correctness and type safety.
5//!
6//! **Experimental:** This crate is an early experiment. The API is unstable, coverage is limited,
7//! and it is not ready for production use.
8//!
9//! ## Environments
10//!
11//! API builders default to the [Daraja sandbox](DarajaEnvironment::Sandbox). Call
12//! [`.production()`](DarajaApi::production) on each builder that will send a request when you
13//! are ready to use live credentials and passkeys.
14//!
15//! Environment is configured per endpoint builder — there is no shared global setting.
16//! If you obtain an access token and then call another API, call `.production()` on both
17//! builders so the token and the downstream request target the same environment.
18//!
19//! ## OAuth
20//!
21//! ```no_run
22//! use daraja_sdk::{DarajaApi, mpesa};
23//!
24//! #[tokio::main]
25//! async fn main() -> Result<(), reqwest::Error> {
26//!     let client = mpesa::Client::with_credentials("your-consumer-key", "your-consumer-secret");
27//!     let token = client.generate_access_token().await?;
28//!     println!("{}", token.access_token);
29//!
30//!     Ok(())
31//! }
32//! ```
33//!
34//! Production:
35//!
36//! ```no_run
37//! use daraja_sdk::{DarajaApi, mpesa};
38//!
39//! #[tokio::main]
40//! async fn main() -> Result<(), reqwest::Error> {
41//!     let client = mpesa::Client::with_credentials("your-consumer-key", "your-consumer-secret")
42//!         .production();
43//!     let token = client.generate_access_token().await?;
44//!     println!("{}", token.access_token);
45//!
46//!     Ok(())
47//! }
48//! ```
49//!
50//! ## M-Pesa Express (STK Push)
51//!
52//! Obtain an access token first (see OAuth above), then:
53//!
54//! ```no_run
55//! use daraja_sdk::mpesa::{ExpressError, MpesaExpress};
56//!
57//! #[tokio::main]
58//! async fn main() -> Result<(), ExpressError> {
59//!     let response = MpesaExpress::new()
60//!         .access_token("your-access-token")
61//!         .passkey("your-lipa-na-mpesa-passkey")
62//!         .business_short_code(174379)
63//!         .party_a(254700000000)
64//!         .party_b(174379)
65//!         .phone_number(254700000000)
66//!         .amount(1)
67//!         .account_reference("Order123")
68//!         .tx_description("Payment")
69//!         .call_back_url("https://your-domain.com/callback")
70//!         .send_prompt()
71//!         .await?;
72//!
73//!     println!("{}", response.customer_message);
74//!     Ok(())
75//! }
76//! ```
77//!
78//! Production:
79//!
80//! ```no_run
81//! use daraja_sdk::{DarajaApi, mpesa::{ExpressError, MpesaExpress}};
82//!
83//! #[tokio::main]
84//! async fn main() -> Result<(), ExpressError> {
85//!     let response = MpesaExpress::new()
86//!         .production()
87//!         .access_token("your-production-access-token")
88//!         .passkey("your-production-passkey")
89//!         .business_short_code(174379)
90//!         .party_a(254700000000)
91//!         .party_b(174379)
92//!         .phone_number(254700000000)
93//!         .amount(1)
94//!         .account_reference("Order123")
95//!         .tx_description("Payment")
96//!         .call_back_url("https://your-domain.com/callback")
97//!         .send_prompt()
98//!         .await?;
99//!
100//!     println!("{}", response.customer_message);
101//!     Ok(())
102//! }
103//! ```
104//!
105//! Transaction results are posted to your callback URL. Handle those in your application;
106//! this crate only initiates the STK Push prompt.
107
108pub mod mpesa;
109pub mod types;
110
111pub use types::{DarajaApi, DarajaEnvironment};