Please Like our Facebook Page

How to add MPesa button into your website, Without API


For some reasons, the folks at Safaricom have never thought of sharing their MPESA API with web developers. A public MPESA API could open the door to all sorts of innovative home-made online payment solutions. Just as MPESA has made banks and ATMs irrelevant, Credit cards & Paypal would fade away if a ‘Pay By Mpesa’ option was available at an E-Commerce site. M Pesa has a fabulous automated Pay Bill system. Unfortunately, requirements for their option cannot be met by small fish like me and you. Available solution is available for Mega Co-operations only. That’s why many developers stick to ‘a headache’ PayPal solution while having the simplest solution in their hands. By the time you will be completing this article, you will be aware of how to implement mpesa option into your website Free of Charge, yeah, I said free of charge.

You may also like:

  1. Android press back again to exit application
  2. How to change language in android programatically
  3. Simple way to implement endless scrolling RecyclerView in android

1. Understanding MPesa

Before we jump into coding and testing my solution with you, let’s first understand MPESA from lay man’s language. MPesa is uniquely identified by two keys, Transaction Id and Sender’s Phone number. Having said that, we will only consider two things under this tutorial Transaction ID and Amount paid for that transaction id. I will consider everything else irrelevant. Remember transaction id is the same for both receiver and the sender.

2. How to detect the payment



I have done a lot of research before concluding this method as seamless and reliable. Let’s start by analysing a typical MPesa message.
LHF0VNC7O2 Confirmed.You
have received Kshs 110.0 from MARY WANJIKU 0712345678 on 15/8/17 at 9.04 PM
New M-Pesa balance is Kshs110.00. Pay Bills via MPESA

That’s exactly how MPesa message appears. MPesa has some permanent grammatical errors but worry not. That won’t hinder us from getting the concept. From the time sim card registration commenced for Safaricom, this message has never changed, It has been like this for almost 10 years down the line. We shall take advantage of this to create an online MPesa solution. Unless things changes, my solution remains 99.99% sure. Even though they changed, we are programmers and we will still study the pattern and do a hack! hahahahahaaahuuu.

3. Method

We are going to use Java, Android. After all, MPesa is a mobile solution and data mining it on the mobile phone is the most efficient way. Keep in mind we understand mobile devices are not the best hence, we have to consider everything that needs to be considered. First, if you are seriously going to employ this method into your online solution, Consider the following points:

  1. Mobile phone must be of strong types.
  2. Use the mobile phone for processing payments only. The mobile phone meant for this work must be bought intended for this work only and irrelevant applications must be uninstalled for the system to run seamlessly
  3. Handle Exceptions in case mobile goes off. Remember this phone will be used as a server, so in case it’s off, you can show your online users, that system is currently unavailable or something of a sort. In short, consider everything that needs to be considered

4. Programming Project



We need a way of detecting new messages. Fortunately android broad cast receiver will do that for us. Message broad cast will enable us to detect new messages. For this tutorial we will not be detecting all messages apart from MPESA MESSAGES ONLY, then we will extract mpesa transaction number and amount , then upload these data to a hosted SQL for verification and payment completion.

So go ahead and create new android project:

Add necessary permissions into your android manifest file. Permissions to be added outside application tag in the manifest tag. Remember for post Marshmallow devices, you will need to handle permissions programatically. For this tutorial, I will ignore that

<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.INTERNET" />

Also inside application tag in manifest file, register your sms Broad Cast Receiver

        <receiver android:name="MpesaBroadCastReceiver">
            <intent-filter>
                <action android:name="android.provider.Telephony.SMS_RECEIVED" />
            </intent-filter>
        </receiver>

MpesaBroadCastReceiver.java

package com.mpesa.com;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.telephony.SmsMessage;


public class MpesaBroadCastReceiver extends BroadcastReceiver {


    @Override
    public void onReceive(final Context context, final Intent intent) {
        // here we will receive an M_Pesa message


        final Bundle bundle = intent.getExtras();

        try {

            if (bundle != null) {

                final Object[] pdusObj = (Object[]) bundle.get("pdus");

                assert pdusObj != null;

                // check for the new message here


                for (int i = 0; i < pdusObj.length; i++) {

                    SmsMessage currentMessage = SmsMessage.createFromPdu((byte[]) pdusObj[i]);

                    String senderNum = currentMessage.getDisplayOriginatingAddress();
                    String message = currentMessage.getDisplayMessageBody();

                    if (senderNum.contentEquals("MPESA")) {

                        String messageArray[] = message.split(" ");

                        String received = messageArray[3]; // this will help us to get only the mpesa received message. This will ignore received mpesa messages for checking balances, buying credit e.t.c

                        if (received.contentEquals("received")) {

                            String transactionId = messageArray[0];
                            String amount = messageArray[4];
                            String senderFirstName = messageArray[6];
                            String senderSecondNmae = messageArray[7];
                            String phoneNumber = messageArray[8];
                            String date = messageArray[10];

                            //T.longToast(context, "mpesa message");
                            // we have extracted more data thatn enough, For this turoal am going to use 
                            // transactin number and amount only

                            String fullName = senderFirstName + " " + senderSecondNmae;

                            uplodaMpesaMetaData(context, transactionId, amount); 

                            

                        }
                    }

                } // end for loop
            } // bundle is null

        } catch (Exception e) {
            //Log.e("SmsReceiver", "Exception smsReceiver" +e);

        }


    }


    private void uplodaMpesaMetaData(Context context, final String transactionId, final String amount) {
    String url = "http://your_server_page_header.com/mpesa_folder/actions.php";

    StringRequest stringRequest = new StringRequest(Request.Method.POST, url, new Response.Listener<String>() {
        @Override
        public void onResponse(String response) {
            // remember broad cast works in the background, so implement
            // your own mechanisms to detect that sever has responded OK
        }
    }, new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError error) {
            // here network error has occurred
        }
    }) {
        @Override
        protected Map<String, String> getParams() {
            Map<String, String> params = new HashMap<>();
            params.put("action", "upload_mpesa_metada");
            params.put("amount", amount);
            params.put("transactionId", transactionId);
            return params;
        }
    };

    Volley.newRequestQueue(context).add(stringRequest);
}
}

PHP PAGE actions.php



<?php 

// this is my actions.php 

if(isset($_POST['action']) && $_POST['action'] == "upload_mpesa_metada"){
	// here upload yuour messages

	$transactionId = $_POST['transactionId']; 
	$amount = $_POST['amount'];

	saveMpesaMetaData($transactionId, $amount);

}

function connect(){
	$dbName = "mpesa"; // data base name 
	$dbUser = "root"; // database user name
	$dbPassword = ""; // database password
	
	try{
		$db = new PDO("mysql:host=localhost;dbname=$dbName",$dbUser,$dbPassword);
		$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
	} catch(Exception $e){
		die($e->getMessage());
	}

	return $db;
}

function saveMpesaMetaData($transactionId, $amount){
	$con = connect(); 
	try{
		$query = $con->prepare("SELECT * FROM mpesa_meta_data WHERE transactionId = ? "); 
		$query->bindParam(1, $transactionId); 
		$query->execute(); 

		if($query->rowCount()){
			// this just to confirm, if android sends multiple requests, there will be no duplicate of 
			// transaction ids
			return; 
		}

		$query = $con->prepare("INSERT INTO mpesa_meta_data(transactionId, amount) VALUES(?, ?) "); 
		$query->bindParam(1, $transactionId); 
		$query->bindParam(2, $amount); 
		$query->execute(); 

		// data has been saved

	} catch(Exception $e){
		die($e->getMessage());
	}
}

SQL DATABASE SCHEMA

How to add MPesa button into your website, Without API

5. Explaining the code

If you have studied this code clearly, it’s self explanatory and simple. Remember I have done it the simplest way.

You should never send android server request in the loop as I have done, in the broad cast receiver, reasons being volley networking library in android processes it’s requests in the background thread and loops do not understand background tasks, so if you get multiple mpesa messages some will be ignored. This is very dangerous. In my case I have just considered the case where system receives receives one message only. A simple hack for this is to create a data structure, then add your messages in the loop to data structure and outside the loop, handle the structure to the volley then deal with it in php code. But anyway that’s a simple hack on how to create a simple money processing system for your solution.



About SQL DATABASE, am just saving amount and transaction id. Status field is used to check if transaction is complete or not. When user enters transaction id on the website, I will handle money for that transaction id and update that field to ‘1’. Meaning another user trying to use the same transaction id will be invalid.

Let me hear your views in the comment. Thanks

6. VIDEO

VIDEO










Please Like us on Facebook