Wednesday 22 July 2015

Developing USSD apps: Test App

Developing ussd apps: test app

In this tutorial, we shall develop a basic USSD test app and dial it from mchoice-simulator.

My assumptions

  • you have read the last 2 posts and have a firm background about how USSD apps work.
  • you have downloaded mchoice-simulator,  run it and been able to access it's web GUI from the browser.
  • you are using java programming language.  



Photo credit http://www.memegenerator.net

After this tutorial, we will become familiar with most of the required libraries that will help you develop and simulate any USSD app you desire from this point henceforth. 

I even think some guys have already run a simple test app after reading the previous tutorials, that would be cool.


Photo credit: http://www.theonlinestate.com

Open your IDE (I use MyEclipse 2014) and create a new web application project like so:

Click File, select web project, and fill in the project name and configure project




click next, next again




 ensure the 2 checkboxes are selected, click next, uncheck jstl libraries, 


click finish.

By now our project hierarchy looks something like this


Ensure these jars are in your web-inf/lib and on your project build path, you can just google their exact names and download them, pretty light.

The log4j and slf jars are not necessary but I use them for smart logging, on the server console.


Create a package com.egima.ussd and create a new class called UssdReceiver.java
which extends MchoiceUssdReceiver.
This is my code for UssdReceiver.java:


package com.egima.ussd;

import javax.servlet.ServletException;
import hms.sdp.ussd.MchoiceUssdException;
import hms.sdp.ussd.MchoiceUssdMessage;
import hms.sdp.ussd.MchoiceUssdTerminateMessage;
import hms.sdp.ussd.client.MchoiceUssdReceiver;
import hms.sdp.ussd.client.MchoiceUssdSender;

public class UssdReceiver extends MchoiceUssdReceiver {

       /**
        *
        */
       private static final long serialVersionUID = 1L;
       private MchoiceUssdSender ussdSender;

       /**
        * we need to override the generic servlet init() method to create some
        * important objects
        *
        */
       @Override
       public void init() throws ServletException {

             super.init();
             try {
                    String clientUrl = "http://127.0.0.1:8000/ussd/";
                    String appId = "appid";
                    String pass = "password";
                    ussdSender = new MchoiceUssdSender(clientUrl, appId, pass);
             } catch (MchoiceUssdException e) {
                    e.printStackTrace();
             }
       }

       /**
        * override onMessage of the parent class, we are passed MchoiceUssdMessage
        * which contains some useful data about the session and client
        */
       @Override
       public void onMessage(MchoiceUssdMessage arg0) {
             // address of requesting client(the gsm handset)
             String address = arg0.getAddress();
             // a unique identifier for the current USSD session
             String convId = arg0.getConversationId();
             // a unique identifier for the incoming message
             String corrId = arg0.getCorrelationId();
             // the incoming USSD message string
             String message = arg0.getMessage();
             // now send a message back to the phone client to show we have received
             // a request
             try {
                    ussdSender.sendMessage("Message received: " + message, address,
                                 convId, false);
             } catch (MchoiceUssdException e) {
                    e.printStackTrace();
             }
       }

       /**
        * call back method called when the session is terminated
        */
       @Override
       public void onSessionTerminate(MchoiceUssdTerminateMessage arg0) {

       }

}


Change your web.xml file to look like so


xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns="http://xmlns.jcp.org/xml/ns/javaee"
       xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
       id="WebApp_ID" version="3.1">
       <display-name>UssdTestApp</display-name>
       <servlet>
             <servlet-name>UssdTestApp</servlet-name>
             <servlet-class>com.egima.ussd.UssdReceiver</servlet-class>
       </servlet>

       <servlet-mapping>
             <servlet-name>UssdTestApp</servlet-name>
             <url-pattern>/*</url-pattern>
       </servlet-mapping>
       <welcome-file-list>
             <welcome-file>index.html</welcome-file>
             <welcome-file>index.htm</welcome-file>
             <welcome-file>index.jsp</welcome-file>
             <welcome-file>default.html</welcome-file>
             <welcome-file>default.htm</welcome-file>
             <welcome-file>default.jsp</welcome-file>
       </welcome-file-list>
</web-app>

Now deploy your app to whatever web or app server you are using (I am using JBoss-as-7.1.0).

Power up mchoice-simulator and launch it from the browser

Select the USSD tab and fill in the app URL (my server runs on http port:8084 so my URL is http:127.0.0.1:8084/UssdTestApp), type any message and click send

If all has gone well, you should be able to see message sent to and received from our server successfully. 


I expect the virtual phone to display the response message we had set in the servlet.



If this does not go well for you, then just recheck the steps and try again, otherwise all should be okay.


All the fundamentals are now complete, 
  • we have a simple app 
  • already deployed to the server, 
  • we have accessed it successfully from our USSD simulator, and 
  • have received a response to our request from the server.

Damnnnn, is that really all?????  What Next??????
To have a meaningful USSD app like you have been seing on your handsets however, we need to add a few more capabilities to ours. i.e

data validation

  • when should the app expect short code and when should it expect an integer corresponding to a menu item selection
  • when should it expect other data input i.e. when you prompt for a pin or a phone number to complete some arbitrary process.
  • When validation varies from data to data. Validating a pin may involve a call to a db to check the client's account, validating a phone number may require some regex etc.
Session handling and data persistence


  • we need to add session handling and put an exit menu option for every menu generated, in case a user would like to terminate the session at any point.
  • due to the limit on the number of alpha numeric characters in a USSD message, we may have to split our menu items to cover multiple screens, navigable with a 'more' option on menus that exceed this limit.
  • for many meaningful apps, you may have to store the selections made by a client during the session to be used in subsequent transactions or at the end of the session.

Good luck coding these operations manually. I ended up with a lot of repetitive boilerplate code for each of my apps. Trust me building an app became so boring, It wasn't acceptable to me, don't know about you 

This is where we shall need another library ussdmenuserver-2.0.jar. I have found myself able to develop an app of most any complexity within just a few minutes to a few hours, depending on the complexity of course.

In the next post, I will take you through this library and show all its unique features through building a more complex app (Mobile money app of one of the popular MSP's in my country, others will find it very useful as well)

If you have ideas on other apps you've been wanting to build, don't hesitate to mail me and we see how to go about it.

Cheers!!!

No comments:

Post a Comment