Implementing a mobile money USSD menu with branded SMS using Africa’s Talking API


The idea is to build a USSD menu for a mobile money application (such as MPESA). The objective is to enable the developer to think out how to code the menu when a menu is somehow complex and learn how to build the navigation e.g. go back, go to the main menu etc. In mobile money apps, one may receive an SMS, so we will add branded/alphanumeric SMS functionality.

In this tutorial, we will build a simple USSD based mobile money application on the Africa’s Taking (AT) platform. Apart from USSD and SMS, AT has other products such as Airtime, Payments, Mobile data, Voice and IoT.

The diagram below summarizes the application menu.

Mobile money application USSD sample menu

The mobile money application also sends a branded SMS. This application is written in PHP.

Note the following:

  • The yellow boxes show the point at which an SMS is sent.
  • The 98. Back box allows a user to navigate back one step
  • The 99. Main Menu box allows a user to navigate back to the main menu, i.e. to see a similar menu as to when you dial the USSD code.

Tutorial outline

  1. Setting up USSD code and alphanumeric in Africas Talking.
  2. Write the USSD menu logic.
  3. Add the ‘Go back’ navigation feature.
  4. Add the ‘Go To Main Menu ‘ navigation feature.
  5. Add SMS functionality.
  6. Conclusion, Troubleshooting ideas, and complete source code


  • Some knowledge of PHP programming language.
  • Some knowledge on AT USSD and SMS API
  • Knowledge on how to set up a PHP server such as Apache (you could use XAMPP software)
  • Composer is set up in your machine for dependency management (we will use AT SMS PHP SDK)
  • An IDE of your choice (I love Visual Studio code)
  • A sender ID
  • A USSD code (You will learn how to generate this in the next lesson)
  • A callback URL.

Setting up USSD code and alphanumeric in Africa’s Talking

In this section, you will create your USSD service code, SMS sender ID and generate your API key on the AT platform.

Creating a developer account in AT
  1. Follow this link to create your AT developer account: Click here.
  2. Login to AT developer account
  3. Click on Go TO Sandbox App. AT sandbox account helps you to test your app before you go live.
Creating USSD service code
  • Click here to create a USSD service code channel.
  • The following information is needed to create the channel:-
    1. A service code, which is shared. It will be selected by default, e.g. *384#
    2. A channel, which is a unique number put after the service code to differentiate your app from other apps, which are using the same service code. If the system rejects a number, which you enter, it means another developer has taken it. Try different numbers until you are successful.
    3. A callback URL, which is a http link pointing to a server, where your app logic is stored. You can create a link pointing to your local machine using ngrok if you do not have an online server. If you do not know how to set up a http link using ngrok, please see this tutorial, How to access your Windows computer or local server from anywhere using Ngrok. Also, to learn more about callback URL, click here.

Your USSD service code would be something like this *384*231# 

Creating an SMS sender ID
  1. Click this link: Click here
  2. Enter your alphanumeric (sender ID). Your sender ID is a name such your as company name. Sender ID is used to brand your messages as you send them to your customers.
  3. Click submit
Generating an API Key

For you to use AT products/services, such as sending SMS, you need to generate an API key for your account. 

Use the following steps to generate an API Key:-

  1. Click here to access the AT dashboard
  2. Read the instructions on that page.
  3. Enter your account password
  4. Click on Generate to generate your API key.

Writing the USSD menu logic.

When a user dials a USSD code, AT gateway will reach your server (where your code lives) using the callback URL. This means you need to have an entry point to your server, i.e. some script file in our case, index.php

Project file structure

We have 4 PHP files as shown:

  • index.php – Application entry point
  • menu.php – Contains a class called Menu, which has methods used to show user menus.
  • util.php – Contains some settings variables, which may be unique to each user/developer, e.g. API key.
  • sms.php – Contains logic for sending an SMS.

Building the USSD menu

Use the following steps.

Step 1:

Read data sent by AT API in the index.php file as shown below. See more details in the API docs.

    include_once 'menu.php';
    //set isUserRegistered flag to true
    $isUserRegistered = true;
    //Read the data sent via POST from our AT API
    $sessionId   = $_POST["sessionId"];
    $serviceCode = $_POST["serviceCode"];
    $phoneNumber = $_POST["phoneNumber"];
    $text        = $_POST["text"];

Notice the inclusion of the menu.php file and the $isUserRegistered flag. You want the users to register if they haven’t registered yet, or perform the rest of the operations if they have registered. Thus, you can change the flag $isUserRegistered to false to test the other scenario. 

Step 2: 

Add the following code to index.php

Any HTTP response body, sent to AT gateway must be pre-appended with either CON and END. See more details in the API docs

CON tells AT that the USSD session is on, and hence we expect a user input whereas END tells AT to end the sessions, and hence no user input is expected. 

Also, notice the role of the explode function. It converts the $text variable into an array using the * as the delimiter. Read the tutorial here to learn about the functions you should know when using AT gateway. 

The default part of the switch…case represents an invalid entry. In a future tutorial, we will discuss how to replay the USSD menus instead of ending the session. 

Step 3

Add the following code in the menu.php file. 

Notice the following:-

  • We have included the util.php file in menu.php.
  • The addCountryCodeToPhoneNumber functions pre-appends a country code to a recipient phone number.
  • We have implemented registerMenu and sendMoneyMenu functions. checkBalanceMenu and withdrawMoneyMenu functions have been left out for you to try out as part of your assignment.
  • The  registerMenu and sendMoneyMenu functions process user’s inputs to show menus to a user based on user replies and the number of replies.

Step 4:

Add the following code into the util.php file.

    class Util{
        static $GO_BACK = "98";        
        static $GO_TO_MAIN_MENU = "99";
        static $COUNTRY_CODE = "+254";        

Notice that you can change the country code depending on your country. You can also change the ‘Go Back’ or ‘Go To Main Menu’ options to suit your requirements. 

Testing the USSD menu with AT simulator

  1. While in AT sandbox dashboard, launch the simulator (see the left menu, lower side). You can also download the AT simulator from Google Play store and test the menu from your phone.
  2. Setup a phone number of your choice. The mobile number, in this case, is equivalent to the one held in a SIM card of an actual mobile phone. If the phone number you use refuses, chances are another developer somewhere is using a similar number in the emulator, so you have to try another one.
  3. Dial your USSD code on the simulator (the one you set in AT sandbox dashboard), e.g. *384*234#. Replace 234 with your channel.
  4. Hit the call button and follow the prompts.

Do not forget to flip $isUserRegistered flag to true or false to test both scenarios. Every time you make a change in your code, you must restart the IDE.

Your task 

Write the logic for checkBalanceMenu and withdrawMoneyMenu functions to output the menu as presented in lesson 1.

Adding the ‘Go back’ navigation feature

In the previous lesson, the ‘send money option‘ needed to allow us to move back one step, perhaps if a user realises they have entered a wrong PIN or for some other reason. Our logic currently shows a message You have requested to back to one step - re-enter PIN and does not take us back. 

To send money, a user will select option 2, then enter the recipient mobile phone, then the amount, then the PIN. At this point the $text variable has something like this;  2*0726123562*400*1234

If a user selects 98, i.e. going back, they are asked to enter a PIN again. Now the $text variable will have a value like this; 2*0726123562*400*1234*98*1243. Notice 1234 and 1243 are pins, the difference being that 1243 is the correct one. So we have to eliminate 1234. Equally, we need to eliminate 98 because it is just an option for going back. Thus, every time our server receives $text from AT, we need to remove 98 and the item just before it. I highly recommend this article, 10 Most Useful PHP and JavaScript/Node Inbuilt Functions for Africa’s Talking (AT) USSD Developers.  

The ‘Go Back’ algorithm

Input: 2*0726123562*400*1234*98*1243

Output: 2*0726123562*400*1243

Simply put, any time you see a 98, remove it and any item before it. 98 may occur multiple times; hence you must repeat until all of them disappear. There may be many ways of looking at this problem – this is just one of them. 

Use the following steps;

Step 1

Add the following code (function) in the menu class.

Step 2

Use the goBack function as a middleware in the index.php by putting the following line of code just after creating the $menu object.


$text = $menu->goBack($text);

Just after:

$menu = new Menu();

in index.php file

Step 3:

Test your USSD menu again.

Adding the ‘Go To Main Menu ‘ navigation feature

The ‘Send money’ option also allows a user to go back to the main menu. A reason, which may necessitate this action is if a user wants to check the account balance before sending. In our case, replying with 99 takes the user back to the main menu.  

To send money, a user will select option 2, then enter the recipient mobile phone number, then the amount, then the PIN. At this point the $text variable has something like this;  2*0726123562*400*1234

If a user selects 99, i.e. going to the main menu, they’ll be asked to start all over again. So we have to $text variable with value 2*0726123562*400*1234*99. Therefore, we must remove 99 and everything before it. 

The ‘Go Back’ algorithm

Input: 2*0726123562*400*1234*99*3

Output: 3

Simply put, if you see a 99 in the $text variable, remove it and everything before it. 99 may occur multiple times, hence you must repeat until all 99’s disappear. This algorithm will be efficient if you search for the last occurrence of 99. 

Use the following steps;

Step 1:

Add the following function in the Menu class.

$text string is first converted into an array. array_search function checks the existence of the ‘Go Back’ option, which is then removed, together with everything before it using array_slice function. 

Notice that the goToMainMenu function works as a middleware, just like goBack in the previous lesson.

Step 2

Add the following function in the Menu class.

public function middleware($text){
    //remove entries for going back and going to the main menu
    return $this->goBack($this->goToMainMenu($text));

The middleware function combines the ‘go back’ and ‘go to main menu’ into one function. 

Step 3:

Replace $text = $menu->goBack($text);with $text = $menu->middleware($text);in the inde.php file. 

Step 4:

Test your USSD menu again.

Adding SMS functionality

After a user registers to the mobile money app, you may need to notify them that the registration was successful. One of the ways to do this is using an SMS, more specifically, a branded SMS. AT makes it easier by providing an SDK. See AT API docs for more info. You can use the REST API options if you wish. In this tutorial, we chose to use AT’s PHP SDK.

To send a branded SMS, you need to have the following:

  • An API key (we already set it in the previous section)
  • A sender ID (we already set it in the previous section)
  • A username, which is always set to sandbox for sandbox environment.
  • A recipient phone number and
  • The message to be sent.

Use the following steps:

Step 1:

Run composer require africastalking/africastalking from your project directory to install AT’s PHP SDK.

Step 2:

Add the following lines of code into your util.php (Util class) file

static  $API_KEY = "YOUR SANDBOX API KEY HERE"; //sandbox

static $API_USERNAME = "sandbox"; //it is always sandbox


Step 3:

Add the following code in your sms.php file.

The constructor of the Sms class initializes the $AT variable. $AT is an object, which allows us to access any AT services (See AT API docs). The sendSms function sends the SMS. The AT service we are using is SMS as shown by $sms = $this->AT->sms();

Step 4:

Add the following code in any place where the SMS needs to be sent.

$sms = new Sms();
$message = "You have been registered";

In this case, we want to send an SMS when a user registers successfully. Thus, change the $isUserRegistered variable value to false and change the registerMenu function as shown below. 

Notice that we have just added the SMS sending logic. Everything else remains unchanged. 

Step 5:

Test your USSD app as explained earlier. If you added the SMS sending logic when a user registers, you should receive an SMS in the simulator’s SMS inbox.

Conclusion, Troubleshooting Ideas

If you are here, you are a champ! You made it. Do not forget to attempt your assignment. 

However, if things seem not to be working, please check on the following:

  • Ensure that you have used the right username for the sandbox environment. The Username for the sandbox environment is always sandbox. Do not confuse it with your live environment username.
  • Ensure you have used the API keys for sandbox. Please copy and paste it to avoid errors.
  • For PHP programming language, you may need to change your ‘Go back’ and ‘Got to main menu’ logic if you want to use 0 and 00 as your user options for ‘Go back’ or ‘Got to main menu’ respectively.
  • Ensure a sender ID has been created in the AT sandbox dashboard.
  • Ensure a USSD service code channel has been created in the AT sandbox dashboard
  • HTTP responses sent to AT gateway (when handling USSD sessions) must  end with either CON or END.
  • Use your own variables where you were asked to, e.g. API key, sender ID etc…
  • AT simulator uses port 1517 (see this for access. Thus if you are using an internet connection, with a restriction such as access port, it may not work. In that case, you may try to use your mobile data.
  • Be very keen to toggle the $isUserRegistered variable from true to false when testing different scenarios.

To access the complete code for this tutorial in GitHub, click here.

Thank you for following this tutorial. I hope it was helpful. Feel free to add your comment.

You May Also Like