
Security News
Attackers Are Hunting High-Impact Node.js Maintainers in a Coordinated Social Engineering Campaign
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.
A robust Node.js library for Safaricom's Daraja API with complete TypeScript support and modern async/await patterns
A robust, modern Node.js library for integrating with Safaricom's M-Pesa Daraja API. Built with TypeScript, comprehensive error handling, and extensive testing.
npm install mpesalib
⚠️ Upgrading from v1.x? This is a complete rewrite with breaking changes. See the Migration Guide for detailed upgrade instructions.
Create a .env file based on .env.example:
MPESA_CONSUMER_KEY=your_consumer_key
MPESA_CONSUMER_SECRET=your_consumer_secret
MPESA_ENVIRONMENT=sandbox
MPESA_SHORT_CODE=174379
MPESA_PASSKEY=your_passkey
import { Mpesa } from 'mpesalib';
// Initialize from environment variables
const mpesa = Mpesa.fromEnv();
// Or initialize with config object
const mpesa = new Mpesa({
consumerKey: 'your_consumer_key',
consumerSecret: 'your_consumer_secret',
environment: 'sandbox',
shortCode: '174379',
passkey: 'your_passkey',
});
// STK Push (Customer Payment)
const response = await mpesa.paybillPayment(
1000, // Amount
'254712345678', // Phone number
'INV001', // Account reference
'Payment for services', // Description
'https://yourdomain.com/callback' // Callback URL
);
console.log(response);
Initiate a payment request to customer's phone:
// Paybill payment
const response = await mpesa.paybillPayment(
amount,
phoneNumber,
accountReference,
description,
callbackURL
);
// Buy goods payment
const response = await mpesa.buyGoodsPayment(
amount,
phoneNumber,
accountReference,
description,
callbackURL
);
// Custom STK Push
const response = await mpesa.stkPush({
BusinessShortCode: '174379',
TransactionType: 'CustomerPayBillOnline',
Amount: 1000,
PartyA: '254712345678',
PartyB: '174379',
PhoneNumber: '254712345678',
CallBackURL: 'https://yourdomain.com/callback',
AccountReference: 'TEST001',
TransactionDesc: 'Test payment',
});
Check the status of an STK Push request:
const status = await mpesa.stkPushQuery('ws_CO_12345678');
Register callback URLs and simulate C2B transactions:
// Register URLs
await mpesa.registerC2BUrls({
ShortCode: '600000',
ResponseType: 'Completed',
ConfirmationURL: 'https://yourdomain.com/confirmation',
ValidationURL: 'https://yourdomain.com/validation',
});
// Simulate C2B payment
await mpesa.simulateC2B({
ShortCode: '600000',
CommandID: 'CustomerPayBillOnline',
Amount: 1000,
Msisdn: '254712345678',
BillRefNumber: 'INV001',
});
Send money to customers:
// Business payment
await mpesa.businessPayment(
5000,
'254712345678',
'Business payment',
'https://yourdomain.com/timeout',
'https://yourdomain.com/result'
);
// Salary payment
await mpesa.salaryPayment(
50000,
'254712345678',
'Monthly salary',
'https://yourdomain.com/timeout',
'https://yourdomain.com/result'
);
// Custom B2C
await mpesa.b2cPayment({
InitiatorName: 'testapi',
SecurityCredential: 'credential',
CommandID: 'BusinessPayment',
Amount: 1000,
PartyA: '600000',
PartyB: '254712345678',
Remarks: 'Payment',
QueueTimeOutURL: 'https://yourdomain.com/timeout',
ResultURL: 'https://yourdomain.com/result',
});
Transfer money between businesses:
await mpesa.b2bPayment({
InitiatorName: 'testapi',
SecurityCredential: 'credential',
CommandID: 'BusinessPayBill',
Amount: 1000,
PartyA: '600000',
PartyB: '600001',
RecieverIdentifierType: 4,
Remarks: 'B2B Payment',
QueueTimeOutURL: 'https://yourdomain.com/timeout',
ResultURL: 'https://yourdomain.com/result',
AccountReference: 'TEST001',
});
Check account balance:
await mpesa.getAccountBalance({
InitiatorName: 'testapi',
SecurityCredential: 'credential',
CommandID: 'AccountBalance',
PartyA: '600000',
IdentifierType: '4',
Remarks: 'Balance inquiry',
QueueTimeOutURL: 'https://yourdomain.com/timeout',
ResultURL: 'https://yourdomain.com/result',
});
Query transaction status:
await mpesa.getTransactionStatus({
InitiatorName: 'testapi',
SecurityCredential: 'credential',
CommandID: 'TransactionStatusQuery',
TransactionID: 'OEI2AK4Q16',
PartyA: '600000',
IdentifierType: '4',
ResultURL: 'https://yourdomain.com/result',
QueueTimeOutURL: 'https://yourdomain.com/timeout',
Remarks: 'Status query',
});
Reverse a transaction:
await mpesa.reverseTransaction({
InitiatorName: 'testapi',
SecurityCredential: 'credential',
CommandID: 'TransactionReversal',
TransactionID: 'OEI2AK4Q16',
Amount: 1000,
ReceiverParty: '600000',
RecieverIdentifierType: '4',
ResultURL: 'https://yourdomain.com/result',
QueueTimeOutURL: 'https://yourdomain.com/timeout',
Remarks: 'Reversal',
});
Handle M-Pesa callbacks in your Express.js application:
import express from 'express';
const app = express();
app.use(express.json());
// STK Push callback
app.post('/mpesa/stkpush/callback', (req, res) => {
const callbackData = req.body;
if (callbackData.Body?.stkCallback?.ResultCode === 0) {
console.log('Payment successful!');
// Update your database
} else {
console.log('Payment failed:', callbackData.Body.stkCallback.ResultDesc);
}
res.status(200).json({ status: 'OK' });
});
// B2C result callback
app.post('/mpesa/b2c/result', (req, res) => {
const result = req.body.Result;
if (result.ResultCode === 0) {
console.log('B2C payment successful:', result.TransactionID);
} else {
console.log('B2C payment failed:', result.ResultDesc);
}
res.status(200).json({ status: 'OK' });
});
The library includes helpful utilities:
import { MpesaUtils } from 'mpesalib';
// Format phone numbers
const formatted = MpesaUtils.formatPhoneNumber('0712345678');
// Returns: '254712345678'
// Generate timestamp
const timestamp = MpesaUtils.generateTimestamp();
// Returns: '20231201120000'
// Generate password for STK Push
const password = MpesaUtils.generatePassword(
shortCode,
passkey,
timestamp
);
// Generate security credential
const credential = MpesaUtils.generateSecurityCredential(
initiatorPassword,
certificatePath
);
// Retry failed operations
const result = await MpesaUtils.retry(
async () => mpesa.stkPush(request),
3, // max retries
1000 // delay in ms
);
The library provides comprehensive error handling:
try {
const response = await mpesa.stkPush(request);
console.log('Success:', response);
} catch (error) {
if (error.status === 401) {
console.error('Authentication failed');
} else if (error.status === 400) {
console.error('Bad request:', error.data);
} else {
console.error('Network error:', error.message);
}
}
MPESA_CONSUMER_KEY=your_consumer_key
MPESA_CONSUMER_SECRET=your_consumer_secret
MPESA_ENVIRONMENT=sandbox|production
MPESA_SHORT_CODE=your_shortcode
MPESA_INITIATOR_NAME=your_initiator_name
MPESA_SECURITY_CREDENTIAL=your_security_credential
MPESA_CERTIFICATE_PATH=./path/to/certificate.cer
MPESA_PASSKEY=your_passkey
After creating the app, you'll get:
For sandbox testing, use these test credentials:
For production:
Run the test suite:
npm test
Run tests with coverage:
npm run test:coverage
Run tests in watch mode:
npm run test:watch
git checkout -b feature/amazing-featurenpm testgit commit -m 'Add amazing feature'git push origin feature/amazing-featureThis project is licensed under the MIT License - see the LICENSE file for details.
Made with ❤️ by John Simiyu
FAQs
A robust Node.js library for Safaricom's Daraja API with complete TypeScript support and modern async/await patterns
We found that mpesalib demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.