Skip to Content
Mpesajs 1.0 is released šŸŽ‰

STK Push

The StkPush class provides functionality to initiate Lipa Na M-Pesa Online (STK Push) payments, allowing you to prompt customers to make payments directly from their M-Pesa accounts via their mobile phones.

Class: StkPush

class StkPush { constructor( auth: Auth, sandbox?: boolean ); public async sendStkPush( amount: number, transactionDesc: string, accountReference: string, businessShortCode?: string, passkey?: string, phoneNumber?: string, callbackUrl?: string ): Promise<StkPushResponse>; }

Constructor

Creates a new instance of the StkPush class for initiating M-Pesa STK Push payment requests.

Parameters

ParameterTypeRequiredDefaultDescription
authAuthYes-An instance of the Auth class for token generation
sandboxbooleanNoMPESA_SANDBOX env varWhether to use sandbox environment

Examples

// Using environment variables with default sandbox mode const auth = new Auth(); const stkPush = new StkPush(auth); // Explicit initialization for production const auth = new Auth( 'your-consumer-key', 'your-consumer-secret', false ); const stkPush = new StkPush(auth, false); // Mixed usage const auth = new Auth(); const stkPush = new StkPush( auth, process.env.NODE_ENV !== 'production' );

Methods

sendStkPush()

Initiates an STK Push transaction to request payment from a customer.

public async sendStkPush( amount: number, transactionDesc: string, accountReference: string, businessShortCode?: string, passkey?: string, phoneNumber?: string, callbackUrl?: string ): Promise<StkPushResponse>;

Parameters

ParameterTypeRequiredDefaultDescription
amountnumberYes-The amount to be paid (must be greater than 0)
transactionDescstringYes-Description of the transaction (max 13 chars)
accountReferencestringYes-Reference for the transaction (max 12 chars)
businessShortCodestringNoMPESA_BUSINESS_SHORTCODE env varThe business short code
passkeystringNoMPESA_PASSKEY env varThe passkey for generating the password
phoneNumberstringNoMPESA_PHONE_NUMBER env varThe customer’s phone number (must start with 251 and be 12 digits)
callbackUrlstringNoMPESA_CALLBACK_URL env varThe HTTPS URL where payment results will be sent

Returns

PropertyTypeDescription
MerchantRequestIDstringUnique identifier for the merchant request
CheckoutRequestIDstringUnique identifier for the checkout/payment request
ResponseCodestringResponse code from M-Pesa API (0 indicates success)
ResponseDescriptionstringDescription of the response status
CustomerMessagestringMessage that can be displayed to the customer

Examples

// Basic STK Push request try { const result = await stkPush.sendStkPush( 100, // amount 'Payment for services', // transaction description 'INV123456789', // account reference ); console.log('Payment initiated successfully!'); console.log('Checkout Request ID:', result.CheckoutRequestID); } catch (error) { console.error('Payment request failed:', error.message); } // With all parameters specified try { const result = await stkPush.sendStkPush( 500.50, 'Coffee payment', 'ORD98765', '174379', // business short code 'bfb279f9aa9bdbcf158e97dd71a467cd2e0c893059b10f78e6b72ada1ed2c919', // passkey '251712345678', // phone number 'https://example.com/mpesa/callback' // callback URL ); // Store the checkout request ID for later status check saveCheckoutRequestId(result.CheckoutRequestID); } catch (error) { handlePaymentError(error); }

Error Handling

The StkPush class can throw several types of errors:

ValidationError

Thrown when input parameters fail validation checks.

try { await stkPush.sendStkPush(amount, desc, ref, businessCode, passkey, phone, callback); } catch (error) { if (error instanceof ValidationError) { console.error(`Validation failed for ${error.field}: ${error.message}`); // Handle specific validation errors if (error.field === 'phoneNumber') { alert('Please provide a valid phone number in the format 251XXXXXXXXX'); } else if (error.field === 'amount') { alert('Amount must be greater than zero'); } } }

StkPushError

Thrown when the M-Pesa API returns an error response for the STK Push request.

try { await stkPush.sendStkPush(amount, desc, ref); } catch (error) { if (error instanceof StkPushError) { console.error(`STK Push error: ${error.message}`); console.error(`Error code: ${error.errorCode}`); // Handle specific STK Push errors if (error.errorCode === '500.001.1001') { console.error('Invalid credentials'); } } }

NetworkError

Thrown when network connectivity issues occur.

try { await stkPush.sendStkPush(amount, desc, ref); } catch (error) { if (error instanceof NetworkError) { console.error('Network issue - implementing retry logic'); // Implement retry with exponential backoff setTimeout(() => retryPayment(amount, desc, ref), 5000); } }

MpesaError

Base error type for all other M-Pesa related errors.

try { await stkPush.sendStkPush(amount, desc, ref); } catch (error) { if (error instanceof MpesaError) { console.error('M-Pesa error occurred:', error.message); } else { console.error('Unexpected error:', error); } }

Best Practices

1. Proper Error Handling

Implement robust error handling to provide clear feedback:

const initiatePayment = async (amount, description, reference, phone) => { try { const result = await stkPush.sendStkPush( amount, description, reference, undefined, // Use environment variable for business code undefined, // Use environment variable for passkey phone ); return { success: true, checkoutRequestId: result.CheckoutRequestID, message: 'Payment request sent successfully' }; } catch (error) { if (error instanceof ValidationError) { return { success: false, field: error.field, message: error.message }; } else if (error instanceof NetworkError) { return { success: false, retry: true, message: 'Network issue occurred. Please try again.' }; } else if (error instanceof StkPushError) { return { success: false, errorCode: error.errorCode, message: 'Payment service error: ' + error.message }; } else { return { success: false, message: 'An unexpected error occurred' }; } } };

2. Environment-Based Configuration

Use different configurations for development and production:

const auth = new Auth(); const stkPush = new StkPush( auth, process.env.NODE_ENV !== 'production' );

3. Secure Parameter Handling

Use environment variables for sensitive information:

// In your .env file MPESA_BUSINESS_SHORTCODE=174379 MPESA_PASSKEY=bfb279f9aa9bdbcf158e97dd71a467cd2e0c893059b10f78e6b72ada1ed2c919 MPESA_CALLBACK_URL=https://example.com/mpesa/callback // In your code const stkPush = new StkPush(auth); const result = await stkPush.sendStkPush( amount, description, reference );

4. Rate Limiting

The StkPush class includes built-in rate limiting to prevent API abuse. Payment requests are automatically rate-limited based on M-Pesa’s guidelines.

Integration Examples

Express.js Route Handler

Example of using StkPush in an Express.js route:

// payment.controller.ts import { Request, Response } from 'express'; import { Auth, StkPush, ValidationError, StkPushError, NetworkError } from 'mpesajs'; const auth = new Auth(); const stkPush = new StkPush(auth); export const initiatePayment = async (req: Request, res: Response) => { const { amount, phoneNumber, description, reference } = req.body; try { const result = await stkPush.sendStkPush( amount, description, reference, undefined, undefined, phoneNumber ); res.status(200).json({ success: true, checkoutRequestId: result.CheckoutRequestID, message: 'Payment request sent successfully' }); } catch (error) { if (error instanceof ValidationError) { res.status(400).json({ success: false, field: error.field, message: error.message }); } else if (error instanceof NetworkError) { res.status(503).json({ success: false, message: 'Service temporarily unavailable. Please try again.' }); } else if (error instanceof StkPushError) { res.status(400).json({ success: false, errorCode: error.errorCode, message: error.message }); } else { res.status(500).json({ success: false, message: 'An unexpected error occurred' }); } } };

React Hook

Example of a React hook for using STK Push:

// useMpesaPayment.ts import { useState } from 'react'; import { Auth, StkPush } from 'mpesajs'; const auth = new Auth(process.env.REACT_APP_MPESA_CONSUMER_KEY, process.env.REACT_APP_MPESA_CONSUMER_SECRET); const stkPush = new StkPush(auth); export const useMpesaPayment = () => { const [loading, setLoading] = useState(false); const [error, setError] = useState(null); const [result, setResult] = useState(null); const initiatePayment = async (amount, phoneNumber, description, reference) => { setLoading(true); setError(null); try { const response = await fetch('/api/mpesa/initiate', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ amount, phoneNumber, description, reference }), }); const data = await response.json(); if (!response.ok) { throw new Error(data.message || 'Payment initiation failed'); } setResult(data); return data; } catch (err) { setError(err.message); throw err; } finally { setLoading(false); } }; return { initiatePayment, loading, error, result }; };
Last updated on