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};