Handling USSD Applications With PHP / Java / JavaScript

Subscribe to my newsletter and never miss my upcoming articles

What is USSD ?

When you dial a number that starts with * and ends with #, you are using USSD and USSD is currently the best available communications technology to deliver mobile financial services to low-income customers.

You are going to need a tool like Postman to be able to test your application.

How it works

Now, the challenge lies in, how do you keep up to where the user is, in the USSD?, what step are they on?, what answer corresponds to which question they were asked?, how is going back to the previous selection choice is implemented ? and also how to automatically clean up old sessions so that they don't fill up your database and make your USSD slow. Bear with me, that's what we are going to figure out, me and you on this journey 😉.

Let’s take for example, your shortcode is *123#. While registering it with a telecommunications company, you provide a URL which is called everytime the USSD is dialed and each time a user respond with your questions with an answer.

When a phone user dials the USSD shortcode, the network operator, in this case MTN, calls your USSD application on the provided URL. The request comes with four GET parameters :

  • msisdn : phone number of the user who dialled the USSD short code
  • input : input from the user
  • newRequest : boolean value indicating if the user is just entering the USSD, in other words, where you display the welcome screen
  • sessionId : unique ID number of each USSD session, which is always the same through out the whole time the user is interacting with your USSD

Keep in mind that each time the user types an answer, your USSD application is called with the input parameter including the typed answer number and newRequest containing 0 if they are in the middle of the USSD, and with other parameters too as they are defined above.

What makes it a little bit hard is that, sometimes the next display message is based on the input from the user, and also a sometimes the message is generated dynamically as in after doing some business logic or fetching some information from the database. That makes it a little bit harder in how we are going to handle our USSD flow.

A use case

Let's use an example to make this process easire to understand, let's say we want to make a banking USSD application, where a bank customer who already have an account can check balance, make transaction to another account, view the last 5 transactions on their account. The means we are going to have thise 3 options on the menu. let's try to see how it'll work.

Welcome to M-Banking

Enter your Bank PIN
Welcome Steve

1) View Balance
2) Make Transaction
3) View History

When the use chose to view their balance

Your balance is 100,000

When the user chose to make a transaction

Enter account number
Enter ammount
Confirm you want to send {amount} to this account {account} by entering your PIN.
Transaction successfully done!

When the use chose to view history

1. Credited 50,000
2. Debited 3,500
3. Debited 2,000
4. Credited 10,000
5. Debited 5,600

Here we go ...

The first HTTP request that you received will have newRequest with value 1, meaning a user just started a new USSD session by dialing *123 on their phone.

    "msisdn": "25078XXXXX",
    "input" : "123", <---------- notice it is not *123#
    "newRequest": 1,
    "sessionId": 15346474

As usual, the good thing to do it to display a welcome screen as we saw above with a list of options for the user to choose from, depending on what they want to do.

When the user types an option and confirm, you receive a HTTP request again with input containing what the user just typed and newRequest containing 0.

    "msisdn": "25078XXXXX",
    "input" : "3",
    "newRequest": 0,
    "sessionId": 15346474

It is more complex for example on option two, when the user chose option 2 to make a transaction and then you prompt them for an account number, when they enter the account number and confirms, you receive a HTTP request again with input containing the account number which was just entered :

    "msisdn": "25078XXXXX",
    "input" : "4563453453432",
    "newRequest": 0,
    "sessionId": 15346474

The hard part is when you received a request like this, you don't know which question was asked in order to process the request, so the obvious thing to do is to track which step the user is on. But the question is, how are we going to do that? Well, by using the unique sessionId which comes on each session.

Everytime the user responds to your USSD, you receive a request to your app containing the sessionId we talked about before, the technique I like to use is to store the sessionIds in table with the step from which the user is at. for example in this case we have about 7 steps, so on the first request, which comes with newRequest having 1 i would create a new USSD session record with step 0. And on the next request I will fetch the session from the table and do a switch case on the step which the user was on before and prepare the display screen of the next step. First of I like to define which step corresponds to which integer number from 0 being the welcome screen. like this for example :

Step 0 : Welcome Screen
Step 1 : Menu Options
Step 2 : Option 1 : View Balance
Step 3 : Option 2 : Make Transactions
Step 4 : Option 2 : Enter account number
Step 5 : Option 2 : Enter amount
Step 6 : Option 2 : Confirm transaction with PIN
Step 7 : Option 3 : View PIN

After defining this, everytime there is a request I check which step the user was on and save/update with the next step they're going to be in just before I return with the display message again.

In this case, previousStep is equal to the current step value on the current session record. It is called previous because the user is no longer going to be on this step.

On the switch case, when the previousStep is 0:

This means that the user just came from the welcome screen and as our case defines, we expect the input to be the Bank PIN, so we validate the Bank PIN against our database, after this we save that the user is now on step 1 and then we return the display message.

so when the previousStep is 1:

This means that the user just came from step 1, which is in our case the menu options, so we expect the input to be one of the menu options we can figure out which menu option the user chose by also applying another switch case here. After that, depending on the menu option chosen and how we defined the step number would be, we save the appropriate step, and return the next display message.

This is exactly what happens on each step, you take the previousStep and do a switch case on it to figure out what the user wants and save the current step and return the display message.

The icing on the cake

To make the code more readable and easy to debug, I prefer to use Enums to define the steps and use them on the switch cases instead of numbers, that way it's easy to read and navigate in code.

Another thing I like to do is to schedule an automated clean up of sessions so that they don't pile up in the database and make the ussd slower. You can use cron jobs for that or any other tool that is appropriate in your stack. For any guidance, shoot the question in the comments section.


I tried as I can to be language neutral on this, because I think this approach can be used regardless of any language or framework you are using. I hope to hear what you think about this in the comments so that we can improve the conversation around this.

linh bạch's photo

Nice idea

Edidiong Asikpo's photo


I really love this. Thanks for sharing Serge Byishimo.

Peter Thaleikis's photo

Interesting idea!