A robust and premium Node.js integration for Safaricom's Daraja API (MPESA). This project provides a ready-to-use server for handling STK Push, C2B (Customer to Business), and B2C (Business to Customer) transactions.
- ⚡ STK Push (Lipa na M-Pesa Online): Initiate payment requests directly to a user's phone.
- 🏢 C2B Register URL: Register confirmation and validation URLs for till/paybill payments.
- 💸 B2C Payments: Automate withdrawals from your business account to customers.
- 🔗 Webhook Callbacks: Pre-configured endpoints to handle transaction results from Safaricom.
- 🛡️ Secure Authentication: Automatic OAuth2 token generation and management.
- 🔄 Dynamic Configuration: Fully configurable via environment variables.
- Node.js (v14 or higher)
- PNPM
- Ngrok (for local testing of callbacks)
- Daraja Developer Account
-
Clone the repository:
git clone https://github.com/masangakevin256/Daraja-API-MPESA.git cd Daraja-API-MPESA -
Install dependencies:
pnpm install
-
Configure Environment Variables: Create a
.envfile in the root directory (see Configuration below). -
Run the server:
# Development mode (with nodemon) pnpm run dev # Production mode pnpm start
Create a .env file and populate it with your Daraja credentials:
# Server Configuration
PORT=3000
# Daraja API Credentials
MPESA_CONSUMER_KEY=your_consumer_key
MPESA_CONSUMER_SECRET=your_consumer_secret
MPESA_PASSKEY=your_lipa_na_mpesa_passkey
MPESA_SHORTCODE=your_shortcode
# Callback & Ngrok Configuration
NGROK_URL=https://your-ngrok-id.ngrok-free.dev
MPESA_CALLBACK_URL=https://your-ngrok-id.ngrok-free.dev/api/mpesa/callback
# B2C configuration
MPESA_SECURITY_CREDENTIALS=your_security_credential| Method | Endpoint | Description |
|---|---|---|
GET |
/stkpush |
Initiates an STK Push payment request. |
GET |
/register_url |
Registers C2B validation and confirmation URLs. |
GET |
/b2c/url_request |
Initiates a Business to Customer payment. |
POST |
/confirmation |
Webhook for C2B Confirmation. |
POST |
/validation |
Webhook for C2B Validation. |
POST |
/api/mpesa/callback |
Webhook for STK Push results. |
This document explains how MPESA communicates with your server when someone makes a payment using your Paybill or Till Number.
A customer goes to M-PESA and enters:
- Paybill Number (e.g.,
600996) - Account Number
- Amount
- M-PESA PIN
Then they press Send.
At this point, the request is handled by Safaricom's MPESA servers.
Safaricom:
- Validates the transaction
- Deducts the money from the user's account
- Confirms the transaction internally
After that, Safaricom needs to notify your system about the transaction.
Safaricom sends an HTTP POST request to the callback URL you registered.
Example callback URL:
https://yourdomain.com/mpesa/callback
Safaricom sends transaction details like:
- Transaction ID
- Amount
- Phone number
- Paybill
- Account reference
- Transaction time
Example JSON sent to your server:
{
"TransactionType": "Pay Bill",
"TransID": "RKTQDM7W6S",
"TransTime": "20260306123045",
"TransAmount": "1000",
"BusinessShortCode": "600996",
"BillRefNumber": "INV001",
"MSISDN": "254712345678"
}Your backend must have an endpoint to receive the request.
Example (Node.js + Express):
app.post("/mpesa/callback", (req, res) => {
console.log("MPESA Callback:", req.body);
// Save transaction to database
// Update user wallet
// Confirm order
res.status(200).json({ message: "Callback received successfully" });
});After receiving the callback, your system can:
- Save the transaction
- Activate a wallet
- Confirm a purchase
- Update a database
- Send a receipt
This is where your business logic happens.
Safaricom must know where to send the payment data.
You register your callback URL using the Register URL API.
Example:
POST /mpesa/c2b/v1/registerurl
You provide:
- Confirmation URL
- Validation URL
- Shortcode
Example:
{
"ShortCode": "600996",
"ResponseType": "Completed",
"ConfirmationURL": "https://yourdomain.com/mpesa/confirmation",
"ValidationURL": "https://yourdomain.com/mpesa/validation"
}- User pays using MPESA
- Safaricom processes payment
- Safaricom calls your callback URL
- Your server receives transaction data
- Your system processes the payment
Flow diagram:
User Phone
│
▼
MPESA (Safaricom)
│
▼
Your Registered Callback URL
│
▼
Your Backend Server
│
▼
Database / Business Logic
During development, your local server is not public.
You can use ngrok to expose it:
ngrok http 3000
Example public URL:
https://abc123.ngrok.io/mpesa/callback
Safaricom can now reach your local server.
In production, you should use:
- A real domain
- HTTPS
- A hosted server (VPS / cloud)
Example production URL:
https://api.yourdomain.com/mpesa/callback
MPESA does not wait for you to ask for the payment details.
Instead:
Safaricom pushes the payment information to your server automatically using the callback URL you registered.
Safaricom → Your Server → Your Database
Contributions are welcome! Feel free to open issues or submit pull requests to improve the integration.
- Fork the Project
- Create your Feature Branch (
git checkout -b feature/AmazingFeature) - Commit your Changes (
git commit -m 'Add some AmazingFeature') - Push to the Branch (
git push origin feature/AmazingFeature) - Open a Pull Request
Distributed under the ISC License. See package.json for details.
When testing in Sandbox, always remember:
- Use Test Shortcode:
174379for STK Push. - Use Test Shortcode:
600996for C2B Register URL. - Test Phone Number:
254708374149(or any valid Safaricom number subscribed to sandbox).
Developed with ❤️ by Masanga Kevin