How to Integrate B2C M-Pesa API using Node.js

M-Pesa can be described as a phone-based mobile banking service. Since its inauguration in 2007 by Vodafone Group PLC and Safaricom in Kenya, it has expanded to eight more countries in Africa.

An API (Application Programming Interface) is an intermediary between two software applications that enables them to communicate.

B2C (Business to Consumer) M-Pesa API enables software developers or merchants to send payments to their customers. You can read more about the M-Pesa API from here.

1. Goals

In this article, we will integrate the B2C M-Pesa API in a Node.js RESTful API. We will consume the API using Swagger.

2. Prerequisites

To follow along in this article, it is helpful to have the following:

  • Node.js installed on your computer.
  • Some basic knowledge on JavaScript.
  • A text editor installed. Preferrably VScode

3. Overview

  • Setting up the development server
  • Getting an access token
  • B2C API

4. Setting up the development server

This article assumes that you have a Safaricom developer account.

If you don’t, go through these steps to create one.

Also, ensure that you have created at least one application from your developer portal. If you haven’t, follow these guidelines.

To get started, we will clone the starter project from here. With all the basic configurations done on the skeleton, our focus throughout the article will be on implementing the core functionalities.

We first need to install the following dependencies:

  • axios: For handling the requests to the M-Pesa API.
  • dotenv: For loading the environmental variables.
  • express: For providing a faster, and easier way to set up a RESTful API.
  • ngrok: For exposing our localhost server.
  • swagger-ui-express: For serving the API docs to the user interface.

To install these packages, open the starter project in your text editor. Next, launch the terminal in your text editor and run the following command:

npm install

Having installed the dependencies, we can move on to the next step.

Note that we will be working from the src/controllers/Mpesa.js file.

5. Getting an access token

All requests to the M-Pesa API must have an access token. It forms the basis for authentication.

To implement this functionality, we will edit the getAccessToken() method as follows:

//get access token.
async getAccessToken(req,res,next){
    // get data from headers by destructuring
    let {consumerkey,consumersecret} = req.headers;
    // request url
    let url = "https://sandbox.safaricom.co.ke/oauth/v1/generate?grant_type=client_credentials";

    // get a base64 encoded string from a buffer
    let buf = new Buffer.from(`${consumerkey}:${consumersecret}`).toString("base64");
    // authentication string
    let auth = `Basic ${buf}`;
    let response;

    try {

        // send a GET request to the URL
        response = await axios.default.get(url,{
            headers:{
                "Authorization":auth
            }
        });

    } catch (error) {

        // in case of an error, get the code and error message
        let err_code = error.response.status;
        let err_msg = error.response.statusText;

        // send response to client
        return res.status(err_code).send({
            message:err_msg
        });

    }

    // get the access token from server response
    let accessToken  = response.data.access_token;

    // set the status code.
    res.status(200);

    // send the access token to client
    return res.send({
        accessToken
    });
};

In the code snippet above, we are:

  • Destructuring the consumerkey and consumersecret from the headers.
  • Setting the URL to send the request.
  • Generating a base64 encoded string from a buffer.
  • Composing the authentication string by appending Basic before the encoded string.
  • Sending the request to M-Pesa API from a try/catch block. In case of an error, the error is sent to the client. Otherwise, if there is no error, the access token is sent to the client.

To test it:

  • Start the development server by running the following command from the terminal of your text editor:
npm run dev
  • In your browser, navigate to http://localhost:4000/api-docs.
  • Click the /access-token section under Mpesa B2C tag.
  • Click the Try it out button.
  • To get your consumer key and consumer secret, visit your applications page, select your application, from the keys section, then copy and paste them respectively into the section’s parameters.
  • Click the Execute button.
  • In case of an error, revisit the steps. Otherwise your server response should resemble the following:
access_token_response_screenshot

A screenshot of getting access token server response.

6. B2C API

We can use the access token to access the B2C API.

To do that, we need to modify the b2c() method as follows:

//b2c.
async b2c(req,res,next){
// destructure from headers
let {accesstoken,initiatorname,securitycredential,commandid,amount,partya,partyb,remarks}= req.headers;
// url to send request to.
let url = "https://sandbox.safaricom.co.ke/mpesa/b2c/v1/paymentrequest";
// url to expose our local server
let ngrok_url = process.env.NGROK_URL;
// authentication string
let auth = `Bearer ${accesstoken}`;
let response;

try{

    // send the request
    response = await axios.default.post(url,{
    "InitiatorName": initiatorname,
    "SecurityCredential":securitycredential,
    "CommandID": commandid,
    "Amount": amount,
    "PartyA": partya,
    "PartyB": partyb,
    "Remarks": remarks,
    "QueueTimeOutURL": `${ngrok_url}/timeout`,
    "ResultURL": `${ngrok_url}/cb`,
    "Occasion": remarks
    },{
        headers:{
            "Authorization":auth
        }
    })

}catch(error) {

    // in case of an error, get the code and the message.
    let err_code = error.response.status;
    let err_msg = error.response.data.errorMessage;

    // send to the client
    return res.status(err_code).send({
        message:err_msg
    });
}

// set the status code
res.status(200);

// send to the client
return res.send({
    result:response.data
});
};

In the above code snippet, we are:

  • Destructuring the data sent from the headers.
  • Setting the URL to send the request to.
  • Setting the ngrok URL. To get it, ensure that you have ngrok installed. Then open another tab in the terminal of your text editor and run the npm run ngrok command. Then, copy the HTTPS URL logged in your terminal and paste it appropriately in the .env file on the root of your project folder.
  • Setting the authentication token by appending Bearer before the access token.
  • Sending the request from a try/catch block. In case of an error, we are getting the status code and the error message and sending them to the client. If no error, we are setting the status code to 200 and sending the response from the request to the client.

To test it:

  • We first need to implement the timeout URL and the result URL. To do that we will edit the timeout() and cb() methods as follows:
//time-out.
async timeOut(req,res,next){
    console.log("--- request timeout ----");
    console.dir(req.body);
    console.log("--- end of request timeout ---");
};

//callback.
async cb(req,res,next){
    console.log("--- callback request ----");
    let response = req.body.Result;

    if(response.ResultParameters) {
        response.ResultParameters = response.ResultParameters.ResultParameter;
    }

    if(response.ReferenceData) {
        response.ReferenceData = response.ReferenceData.ReferenceItem;
    };

    console.log(response)
    console.log("--- end of callback request ---");
};
  • Ensure that your development server is running.
  • In your browser, navigate to http://localhost:4000/api-docs page, and then proceed to the /b2c section.
  • Click the Try it out button.
  • Fill in the parameters as follows:
    • For AccessToken, Repeat the previous process and copy and paste the access token generated.
    • For InitiatorName, copy and paste the Initiator Name from your test credentials page.
    • For SecurityCredential, copy the Security Credential from the test credentials page and paste it in the Initiator Security Password input below and click Generate Credentials. Copy and paste the long generated text.
    • For CommandID, select any from the dropdown.
    • For Amount, enter any amount.
    • For PartyA, copy and paste the Shortcode 1 from test credentials page.
    • For PartyB, copy and paste the Test MSISDN from test credentials page.
    • For Remarks, enter any text. Keep it short.
  • Click the Execute button.
  • In case of any error, revisit the steps above. Otherwise the following output should resemble your server response.
b2c_server_response_screenshot

A screenshot of b2c server response.

The information logged on your console should mimic the following:

b2c_console_response_screenshot

A screenshot of b2c console response

7. Conclusion

In today’s competitive business environment, business processes should be automated to lower costs. The M-Pesa B2C API offers an infrastructure to automate payments from merchants to customers.

To expand your knowledge on the covered topics, check out the following resources:

Happy coding!!

Related posts:

Node.js versus Next.js - A React Approach
Understanding Cookies and Implementing them in Node.js
Understanding Asynchronous Control Flows in Node.js Using Async.js
Better Error Handling In NodeJS With Error Classes
Why is Node.js wildly popular among developers?
How to build a real time chat application in Node.js
Introduction to hapi.js Framework
Email Authentication and Verification using Node.js and Firebase
Creating Secure Password Flows With NodeJS And MySQL
Building A Pub/Sub Service In-House Using Node.js And Redis
Getting Started with billboard.js charts
Creating Secure Password Resets With JSON Web Tokens
Getting Started with Node.js Event Emitter
How to use CORS in Node.js with Express
Debugging a Node.js app running in Docker using Nodemon and the Docker extension
Building A Real-Time Retrospective Board With Video Chat
Uploading Files using Formidable in a Node.js Application
Node.js vs Python for Backend Development
Speakeasy Two-factor Authentication in Node.js
Building A Node.js Express API To Convert Markdown To HTML
Building a RESTful API with Adonis.js
Choosing Between NPM and Yarn
How to Connect MongoDB to Node.js Using Mongoose
Sharing Code Between Projects: Lessons Learned In The Trenches
Understanding HTTP Requests in Node.js
Keeping Node.js Fast: Tools, Techniques, And Tips For Making High-Performance Node.js Servers
Getting Started with Json Web Auth using Angular 11 and Node.js
Getting Started with Strapi API CMS
Getting Started With Node.js Timers
Why Static Typing & Why is TypeScript so popular?
Debugging a Node.js Application running in a Docker Container
Writing A Multiplayer Text Adventure Engine In Node.js (Part 1)