MpesaLib

Build Status NuGet version (MpesaLib)

A .NET Standard M-PESA API Helper Library for .NET Developers.

Supported Platforms

Platform .NET Core .NET Framework Mono Xamarin.iOS Xamarin.Android Xamarin.Mac UWP
Min. Version 2.0 4.6.1 5.4 10.14 8.0 3.8 10.0.16299

Installation

Setting yourself up for success

Before you proceed kindly aquaint yourself with Mpesa Apis by going through the Docs in Safaricom’s developer portal or Daraja if you like.

  1. Obtain consumerKey, consumerSecret and Passkey (for Lipa Na Mpesa Online APIs) from daraja portal.

  2. Ensure your project is running on the minimun supported versions of .Net

  3. MpesaLib is dependency injection (DI) friendly and can be readily injected into your classes. You can read more on DI in Asp.Net core here. If you can’t use DI you can always manually create a new instance of MpesaClient and pass in an httpClient instance in it’s constructor. eg.

// When DI is not possible for your case don't give up just yet...

//create httpclient instance
var httpClient = new HttpClient();

httpClient.BaseAddress = RequestEndPoint.SandboxBaseAddress; //Use RequestEndPoint.LiveBaseAddress in production
	
//create Mpesa API client instance
var mpesaClient = new MpesaClient(httpClient); //make sure to pass httpclient intance as an argument
	

I would recommend the DI way of doing things though…

Registering MpesaClient & Set the BaseAddress -Dependency Injection Method

using MpesaLib;
services.AddHttpClient<IMpesaClient, MpesaClient>(options => options.BaseAddress = RequestEndPoint.SandboxBaseAddress);

Use RequestEndPoint.LiveBaseAddress as base address/base url in production. You can do an environment check using the IHostingEnvironment property in asp.net core.

Requesting for the Accesstoken

Mpesa APIs require authorization to use the APIs. The accesstoken (auth token) has to be used with each api call. The accesstoken expire after an hour so it is recommended that you use a caching strategy to refresh the token after every hour or less depending on how much traffic your site has.

//Async 
var accesstoken = await _mpesaClient.GetAuthTokenAsync(ConsumerKey, ConsumerSecret, RequestEndPoint.AuthToken);

Note that you have to pass in a consusmerKey, ConsumerSecret provided by Mpesa.

C2B Register Urls Request

var RegisterC2BUrlObject = new CustomerToBusinessRegisterUrlDto(
	"https://blablabala/api/confirm",
	"https://blablabala/api/validate",
	"Cancelled",
	"603047"
);

var c2bRegisterUrlrequest = await _mpesaClient.RegisterC2BUrlAsync(RegisterC2BUrlObject, accesstoken, RequestEndPoint.RegisterC2BUrl);

C2B Payment Request

//C2B Object
Var CustomerToBusinessSimulateObject = new CustomerToBusinessSimulateDto
(
	"603047",
	"10",
	"account",
	"254708374149",
	"CustomerPayBillOnline"
);

var c2brequest = await _mpesaClient.MakeC2BPaymentAsync(CustomerToBusinessSimulateObject, accesstoken, RequestEndPoint.CustomerToBusinessSimulate);

LipaNaMpesaOnline/MpesaExpress (STK Push) Payment Request

// initialize object with data
var MpesaExpressObject = new LipaNaMpesaOnlineDto
(
	"BusinessShortCode",// businessShortCode
    	Timestamp, //Timestamp
        "TransactionType",  //transactionType
        "Amount", // amount
        "PartyA" ,// partyA
        "PartyB" ,// partyB
        "PhoneNumber", // phoneNumber
        "CallBackURL", // callBackUrl
        "AccountReference" ,//accountReference
        "TransactionDesc" ,//transactionDescription
        "Passkey" //passkey
);

//Make payment request 
var paymentrequest = await _mpesaClient.MakeLipaNaMpesaOnlinePaymentAsync(MpesaExpressObject, accesstoken, RequestEndPoint.LipaNaMpesaOnline));

LipaNaMpesaOnline/MpesaExpress Transaction Query Request

var QueryLipaNaMpesaTransactionObject = new LipaNaMpesaQueryDto
(
	 "174379", //BusinessShortCode
	 "CheckoutRequestID", //CheckoutRequestID
	 "Password", //Password
	 "Timestamp" //Timestamp

);

var stkpushquery = await _mpesaClient.QueryLipaNaMpesaTransactionAsync(QueryLipaNaMpesaTransactionObject, accesstoken, equestEndPoint.QueryLipaNaMpesaOnlieTransaction);

B2C Payment Request

//B2C Object
var BusinessToCustomerObject = new BusinessToCustomerDto
(
	"test",//Remarks
	"1", //Amount
	"BusinessPayment", //CommandID
	"safaricom.15", //InitiatorName
	"test", //Occasion
	"603047", //PartyA
	"254708374149", //PartyB
	"https://blablabla/timeoutendpoint", //QueueTimeOutURL
	"https://blablabla/resultendpoint", //ResultURL
	"security credential" //SecurityCredential
);

var b2crequest = await _mpesaClient.MakeB2CPaymentAsync(BusinessToCustomerObject, accesstoken, RequestEndPoint.BusinessToCustomer);

B2B Payment Request

var BusinessToBusinessObject = new BusinessToBusinessDto
(
	"test", //AccountReference 
	"safaricom.13", //Initiator 
	"1500", //Amount 
	"603047", //PartyA 
	"600000", //PartyB
	"BusinessPayBill",// Please use the correct command -usage depends on what is enabled for your shortcode
	"https://blablabla/callback", //QueueTimeOutURL 
	"4", // RecieverIdentifierType  - Read on receiver identifier types from daraja
	"security credential", //SecurityCredential - Use MpesaLib.Helpers.Credentials class to generate security credential
	"4", //SenderIdentifierType
	"https://blablabla/callback", //ResultURL
	"payment" //Remarks
);

var b2brequest = await _mpesaClient.MakeB2BPaymentAsync(BusinessToBusinessObject, accesstoken, RequestEndPoint.BusinessToBusiness);

Transaction Status Request

var TransactionStatusObject = new MpesaTransactionStatusDto
(
	 "IdentifierType",//IdentifierType
	 "Initiator", //Initiator
	 "Occasion", //Occasion
	 "PartyA", //PartyA
	 "QueueTimeOutURL", //QueueTimeOutURL
	 "ResultURL", //ResultURL
	 "TransactionID", //TransactionID
	 "Remarks", //Remarks
	 "SecurityCredential" //SecurityCredential
);

var transactionrequest = await _mpesaClient.QueryMpesaTransactionStatusAsync(TransactionStatusObject, accesstoken, RequestEndPoint.QueryMpesaTransactionStatus);

Account Balance Query Request

var AccountBalanceObject = new AccountBalanceDto
(	
	"IdentifierType",// 4 for Paybill 2 for Till
	"Initiator", //Initiator password
	"PartyA", 
	"QueueTimeOutURL",
	"ResultURL",
	"remarks",
	"security credential", 
);

var accountbalancerequest = await _mpesaClient.QueryAccountBalanceAsync(AccountBalanceObject, accesstoken, RequestEndPoint.QueryAccountBalance); //async method

Transaction Reversal Request

var TransactionReversalObject = new ReversalDto
(
	"Initiator",	//Initiator
	"Occasion", //Occasion
	"ReceiverParty", //ReceiverParty
	"RecieverIdentifierType", //RecieverIdentifierType
	"QueueTimeOutURL", //QueueTimeOutURL
	"ResultURL", //ResultURL
	"TransactionID", //TransactionID
	"SecurityCredential",  //SecurityCredential
	"Remarks", //Remarks

);

var reversalrequest = await _mpesaClient.ReverseMpesaTransactionAsync(TransactionReversalObject, accesstoken, RequestEndPoint.ReverseMpesaTransaction);

Getting Security Credential for B2B, B2C, Reversal, Transaction Status and Account Balance APIs

The Security Credential helper class is in MpesaLib.Helpers namespace.

This class helps you generate the required credential to be used to authorize the above mentioned APIs.

using MpesaLib.Helpers; // add this to your class or namespace

//get path to Mpesa public certificate. There are different certs for development and for production, ensure to use the correct one)

string certificate = @"C:\Dev\MpesaLibSamples\WebApplication1\Certificate\prod.cer";
 
 //generate security credential as follows...

var SecutityCredential = Credentials.EncryptPassword(certificate, "Initiator Password");

Error handling

MpesaClient Throws MpesaApiException whenever A 200 status code is not returned. It is your role as the developer to catch the exception and continue processing in your aplication. Snippet below shows how you can catch the MpesaApiException.

using MpesaLib.Helpers.Exceptions; // add this to you class or namespace


try
{	
	return await _mpesaClient.MakeLipaNaMpesaOnlinePaymentAsync(MpesaPayment, accesstoken, RequestEndPoint.LipaNaMpesaOnline);
}
catch (MpesaApiException e)
{
	_logger.LogError($"An Error Occured, Status Code {e.StatusCode}: {e.Content}");

//check the status code and return what is appropriate for your case. e.Content has the error message from Mpesa inform of a json string (not object) incase you do things like tying to transact 0 shillings or more than the 70k limit per transaction, or your shorcode is wrong or your accesstoken is not valid etc.
    
	return BadRequest(); //I am just being lazy here.
}