Android Mpesa Integration using Daraja Library (Part 2)

Ronnie Otieno
6 min readJun 28, 2020

--

This is a continuation from the last part. Today we are going to download and install Node, Firebase CLI and implement Mpesa Callback.

First things first head to Node Website and download the latest version.

After install to make sure that it was installed perfectly open terminal or command prompt and run this

npm 

if you get a message that npm isn't recognized(for windows) then you didn't install properly, try again.

If everything is okay run this command to install firebase CLI

npm install -g firebase tools

It will take some time, after installation we can now login to our firebase by running, it doesn't matter any directory for now.

firebase login

After that now let's connect our project to firebase. I hope you all know how to connect to Firebase if you don't pause right there and have a look, continue after connecting your app to firebase because next part depends on it.

After successfully connecting the app to the Firebase, go back to Android studio add paste the following in your buid.gradle

implementation 'com.google.firebase:firebase-functions:19.0.2'
implementation 'com.google.firebase:firebase-messaging:20.2.0'
implementation 'com.google.firebase:firebase-database:19.3.0'
implementation 'com.google.firebase:firebase-core:17.4.3'
implementation 'com.google.code.gson:gson:2.8.6'

Sync the Gradle then navigate at the bottom and open the terminal and run

firebase init functions

Type ‘Y’ if you are asked if you are ready to proceed, then click on ‘Choose an existing project’ and choose the project you just connected your app with.

Use arrows to move up and down and ENTER to select

Next, select Javascript if you are prompted to choose language, then if you see this, “Do you want to use ESLint to catch probable bugs and enforce style?” type a big N. It will complicate things. The last one type ‘Y’ if asked about dependencies. Wait for it to initialize. If everything went well you should see “Initialization Complete”.

Now lets open project View in our project

Click on android and select Project

Expand then navigate to functions then package.json file. Read through it and check where its written “Engine” change it from 8 to 10

if it's already 10 leave it.

Go back to Functions folder, right-click and select open in the terminal and run

npm install express body-parser -S

Now we are set just two more steps. Go back to functions folder and open index.js, delete everything and paste the following.

let functions = require('firebase-functions');

let admin = require('firebase-admin');

admin.initializeApp(functions.config().firebase);
const express = require('express');
const bodyParser = require('body-parser');

//Initialize our web App
const app = express();
app.use(bodyParser.json());
app.disable('x-powered-by');


//This is our actual callback url `Format will be www.example.com/api/myCallbackUrl`
app.post('/myCallbackUrl', (req, res) => {
let response = {
"ResultCode": 0,
"ResultDesc": "Success"
}
//Send response back to safaricom that payload has been received successfully
res.status(200).json(response);

//Then handle data through above received payload as per your app logic.
let body = req.body;
let payload = JSON.stringify(body)

console.log(payload)

let id = body.Body.stkCallback.CheckoutRequestID

const payloadSend = {
data: {
payload,
},
topic: id
};

return admin.messaging().send(payloadSend).catch(error=>{
console.error(error)
})


})

exports.api = functions.https.onRequest(app);

Clear everything on Terminal and open terminal again, this time we are going to deploy our function by running

firebase deploy --only functions

If everything goes as planned you should see “Deploy Complete”

Now let's go to firebase and open Functions. Copy the function URL. That will our callback URL

copy the URL on the Request

Go back to Android studio, paste the URL in the callback URL place and append “/myCallbackUrl” like this

Now that we have added the Callback URL we need to add Firebase Cloud messaging. This will receive the data sent from the function. In MainActivity scroll down to

And add this

FirebaseMessaging.getInstance()
.subscribeToTopic(lnmResult.CheckoutRequestID.toString())

This will allow the firebase to subscribe to the topic which the function will send data to.

Now I want you to add the following class like this

Body

data class Body(
val stkCallback: StkCallback
)

Item

data class Item(
val Name: String,
val Value: String
)

CallBackMetaData

data class CallbackMetadata(
val Item: List<Item>
)

MpesaResponse

data class MpesaResponse(
val Body: Body
)

StkCallBack

data class StkCallback(
val CallbackMetadata: CallbackMetadata,
val CheckoutRequestID: String,
val MerchantRequestID: String,
val ResultCode: Int,
val ResultDesc: String
)

MpesaListener

interface MpesaListener {

fun sendSuccesfull(amount: String, phone: String, date: String, receipt: String)
fun sendFailed(reason: String)
}

Now, let MainActivity Implements Mpesalistener

Add-in MainActivity

companion object {
lateinit var mpesaListener: MpesaListener
}

and its On create method have this,

mpesaListener = this

Inside sendSuccesfull override function have this,

runOnUiThread {
Toast.makeText(
this, "Payment Succesfull\n" +
"Receipt: $receipt\n" +
"Date: $date\n" +
"Phone: $phone\n" +
"Amount: $amount", Toast.LENGTH_LONG
).show()

}

Inside sendFail override function have have this

runOnUiThread {
Toast.makeText(
this, "Payment Failed\n" +
"Reason: $reason"
, Toast.LENGTH_LONG
).show()
}

Now lets Implement FirebaseMessaging by having this class

import android.util.Log
import com.google.firebase.messaging.FirebaseMessaging
import com.google.firebase.messaging.FirebaseMessagingService
import com.google.firebase.messaging.RemoteMessage
import com.google.gson.Gson


class FirebaseMessagingService :
FirebaseMessagingService() {

override fun onMessageReceived(remoteMessage: RemoteMessage) {
super.onMessageReceived(remoteMessage)

Log.d("MessagingService", remoteMessage.data.toString())

val payload = remoteMessage.data["payload"]

val gson = Gson()

val mpesaResponse = gson.fromJson(payload, MpesaResponse::class.java)

Log.d("MessagingServiceSecond", mpesaResponse.toString())

var id = mpesaResponse.Body.stkCallback.CheckoutRequestID

if (mpesaResponse.Body.stkCallback.ResultCode != 0) {

var reason = mpesaResponse.Body.stkCallback.ResultDesc

MainActivity.mpesaListener.sendFailed(reason)
Log.d("MessagingServiceThird", "Operation Failed")
} else {
Log.d("MessagingServiceThird", "Operation Success")

val list = mpesaResponse.Body.stkCallback.CallbackMetadata.Item

var receipt = ""
var date = ""
var phone = ""
var amount = ""


for (item in list) {

if (item.Name == "MpesaReceiptNumber") {
receipt = item.Value
}
if (item.Name == "TransactionDate") {
date = item.Value
}
if (item.Name == "PhoneNumber") {
phone = item.Value

}
if (item.Name == "Amount") {
amount = item.Value
}

}
MainActivity.mpesaListener.sendSuccesfull(amount, phone, date, receipt)
Log.d("MetaData", "\nReceipt: $receipt\nDate: $date\nPhone: $phone\nAmount: $amount")
//Log.d("NewDate", getDate(date.toLong()))
}

FirebaseMessaging.getInstance()
.unsubscribeFromTopic(id)

}


override fun onNewToken(token: String) {
super.onNewToken(token)

}

}

Before running your app go to Manifest inside application and register service

<service
android:name=".FirebaseMessagingService"
android:stopWithTask="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>

Run your app and try sending, you should be able to see the following.

Thanks all, if you have any question you can get me on Twitter @Ronnieonly. Stay tuned for next Part on how to apply for production credentials. Thanks!

Entire Repo https://github.com/ronnieotieno/Lipa-na-Mpesa-Express-using-Daraja-Library-for-Android

--

--

Ronnie Otieno
Ronnie Otieno

Written by Ronnie Otieno

A software developer with years of experience designing and developing Android applications.

Responses (1)