Introduction

Africa's Talking is an African technology company specialising in building APIs to support African developers and businesses to build USSD applications, SMS applications, Voice applications and payments applications.

According to the company's website, the company supports over 25,000 developers in over 11 countries in Africa. These countries include Kenya, Tanzania, Uganda, Nigeria, South Africa, Rwanda, Zambia, Ethiopia, Gambia, Malawi, and Cote d'Ivoire.

One of their earliest and most successful products is the USSD API, which allows developers to build USSD applications. USSD applications are menu driven apps, which can be accessed using ANY mobile phone (both feature smart phones) that can connect to GSM network. When you dial *384# on your mobile phone, you are actually using a USSD application.

Sample USSD application menu (Africa's Talking, 2020)

From the diagram above, it can be observed that once you dial *384#, you are prompted to enter your password/PIN, say 1234, then in the next menu, you have 3 options to select from, say you select 2, then another menu appears and let's say this time you select 1. Next, you need to enter the amount..... and the process continues. Note that if you want to see the 'Amount' menu, you could dial *384*1234*3*1# at once and then Call.

What Africa's Talking has done is fantastic because when you use their USSD aggregator or API, you can connect to multiple Mobile Network Operators (MNOs), without having to negotiate connectivity contracts yourself. Their gateway also hides the complicated old school GMS's SS7 protocol to an easy to use REST API. What I will not forget to say is that their API's documentation is great and there is a USSD simulator to help in testing your application before you deploy it. Besides, you have access to a dashboard where the USSD sessions are logged to enable you find causes of an error when it occurs.

Prerequisites

This article is very easy to understand and it targets developers wishing to or have built USSD applications using Africa's Talking API. However, you should have:-

  • Some level of understanding of PHP or JavaScript  languages
  • Some familiarity of how USSD application work
  • Some familiarity of how the Africa's Talking USSD API work

If you have not checked out the API, please visit this website or create a developer account.

A fictitious USSD application and how Africa's Talking USSD gateway works

Suppose we have a fictitious mobile money USSD application, which allows a user to register, send money, withdraw money and check balance - an app just like M-PESA, but implemented as a USSD application (see diagram below).

Sample USSD menu

If a user were to send money, they would follow these steps:

  1. Dial *384# - this is the USSD service code

2. Select option 2 (Send money) by replying with a 2

3. Enter receivers mobile number (say 0726172578)

4. Enter the amount to send (say 400)

5. Enter PIN (say 1234)

6. Then confirm by replying with a 1 (At this point, the session is ends)

Alternatively, the user can dial *384*2*254726172578*400*1234*1#, then hit the Call button to achieve the same thing.

Notice also that at step 5, the user can reply with 98 to go back one step or 99 to go back to the main menu/home. The main menu is the menu you see when you dial *384# i.e. the USSD service code.

Therefore, if we have something such as this *384*2*254726172578*400*1234*98*4321*1#, it means that after step 5, the user entered 98 to go back one step and re-entered the PIN and then finally confirmed the transaction. On the other hand *384*2*254726172578*400*1234*99*4*....., means that after step 5, the user navigated to the main menu by replying with 99, and wants to check the balance instead.

The values, which the user is replying with are separated by an asterisk (*), it should be easy to extract them.

The Africa's Talking USSD gateway is designed to present to you (the developer) all the user replies, separated by an asterisk (*)  as above. However, it does not include the USSD service code and the last # (hash symbol). Thus instead of *384*2*254726172578*400*1234*98*4321*1#, it will return 2*254726172578*400*1234*98*4321*1. Remember, it is your responsibility as the developer to know what each of the replies mean because you designed the menu.

For new developers trying to understand Africa's Talking USSD API, it can be a challenge. This was the case when I started off. Some of the things you will have to do when building the menu include:

  • Extracting user replies from the asterisk separated string.
  • Knowing the number of times a user has replied so as to send to them the right menu.
  • Knowing when the user navigated back or to the main menu.
  • Knowing  when the user replied with an invalid option.

In this article, we are going to look at the inbuilt functions, that would help you to address most of the needs for PHP and JavaScript/Node developers.

Time to look at the functions

explode for PHP and split for JavaScript on string

If you're presented with 2*254726172578*400*1234*98*4321*1, you will need a PHP function called explode ().

This function takes the string and separator and returns an indexed array containing user replies as the array elements. The element index starts at 0.

$text = "2*254726172578*400*1234*98*4321*1";
$elementArray = explode("*",$text);

//Thus first reply is 2 => so you the user wants to send money and not to register 
//phone number is available at position 2 i.e $elementArray[1]
//Amount to transfer is obtained from $elementArray[2]

In JavaScript, you would use the split() function in a String object as follows

let text = '2*254726172578*400*1234*98*4321*1';
let elementArray = text.split('*');
//Thus the amount to send is available at elementArray[2]

If you are using a function in Node, which receives the string, then it would be advisable to  explicitly create a string object, before you call the split() method on it.

function convertToArray (text){
	let newText = new String(text);
    	return newText.split('*');
}

count for PHP and length for JavaScript on arrays  

For you to show the user the right menu at any given instance, then you will need to know the level at which the user is i.e. the number of replies the user has made. For instance, for you to send a menu to a user asking them to enter the 'Amount' to send, then they must have replied twice and the first reply must be 2. This can be done this way;-

$text = "2*254726172578*400*1234*98*4321*1";
$elementArray = explode("*",$text);
if(count($elementArray) == 2 && $elementArray[0] == 2){
	//Ask user to enter amount to send
}

An equivalent of this code in JavaScript is shown below. Notice that length is a property of the array and not a function/method.

let text = '2*254726172578*400*1234*98*4321*1';
let elementArray = text.split('*');

if(elementArray.length == 2 && elementArray[0] == 2){
    //Ask user to enter amount to send
}

substr for both PHP and JavaScript on strings

The substr() function for both PHP and JavaScript returns a part of a string. In our example above, the user enters a phone number without a country code (i.e. 0726172578). However, Africa's Talking USSD gateway appends the country code for you. If we were to do it ourselves, then the substr() method would be useful. It can be achieved as shown below.

$phone = "0726172578";
$phoneWithCode = "+254" . substr($phone, 1);
//$phoneWithCode has +254726172578
//Start at second character to the end

When using JavaScript, it can be done as shown below.

let phone = '0726172578';
let phoneWithCode = phone.substr(1);
//$phoneWithCode has +254726172578
//Start at second character to the end

array_shift for PHP and shift for JavaScript on array  

These methods in their respective languages, are used to remove the first element from an array, and returns the value of the removed element. In our example, when Africa's Talking returns the string to you, It will look like this:  2*254726172578*400*1234*98*4321*1 and not 384*2*254726172578*400*1234*98*4321*1. It means that Africa's Talking has already removed the USSD services code. If we were to do it ourselves, then the array_shift function would be useful. See code examples below.

$text = "384*2*254726172578*400*1234*98*4321*1";
$elementArray = explode("*",$text); //explode returns an array
array_shift($elementArray);
//if you check out the contents of $elementArray, 384 will be missing 

When using JavaScript, it would be done as shown below.

let text = '384*2*254726172578*400*1234*98*4321*1';
let elementArray = text.split('*');
elementArray.shift();

Next,

How do you handle a situation, when a user replied with a 98 to go back (one step) and 99 to go to home (i.e. to main menu)

For instance 2*254726172578*400*1234*98*4321*1 will need to be transformed to 2*254726172578*400*4321*1 Since 98 means go back, we remove 98 itself and the option before it. On the other code 2*254726172578*400*1234*99*2*254726172578 will need to be transformed to 2*254726172578 since 99 means go to the main menu, so we have to remove 99 and everything before it.  

Thus, the first step is to determine if the whole string contains a 98 or 99 somewhere. Note that either of the two can appear multiple times in the string and that both can appear in the same string.

array search() for PHP and indexOf() for JavaScript on array

Both array_search and indexOf searches an array for a value and returns the first key or index if the element is found. If the target element is not found, then array_search returns false whereas indexOf returns -1.

In our example this is how, we would determine if the user inputs contained a 98.

$text = "2*254726172578*400*1234*98*4321*1";
$elementArray = explode("*",$text); //explode returns an array
$target = "98";
$found = array_search($target,$elementArray);

if($found != false){
	//means the element was found and is in index $found
}

If the requirement is to use 0- for go back and 00-for go to the main menu, then the code above will not work. This is because, in terms of value, 0 and 00 are the same value but a string '0' and a string '00' are different, fortunately, array_search accepts a third optional argument, called strict, and is a boolean parameter. If this parameter is set to TRUE, then this function will search for identical elements in the array. Thus, the above PHP function can safely be re-written as shown below. With JavaScript, the best alternative is to use Typescript.

$text = "2*254726172578*400*1234*98*4321*1";
$elementArray = explode("*",$text); //explode returns an array
$target = "98";
$found = array_search($target,$elementArray, true);
if($found != false){
	//means the element was found and is in index $found
}

It is also worth noting that if you do not want to use the function/method, you would use a loop to find out if the target element does exist. See example below.

$text = "2*254726172578*400*1234*98*4321*1";
//explode returns an array
$elementArray = explode("*",$text); 
$target = "98";

//Function call
$found = findTarget($elementArray,$target);

if($found != false){
	echo $found;
}else {
	echo "not found";
}
//Function definition 
function findTarget($elementArray, $target){
	for($i=0; $i<count($elementArray); $i++){
        if ($elementArray[$i] === $target){
			return $i; 
        }
	}
    return false;
}

The JavaScript code would look like as shown below:-

let text = '2*254726172578*400*1234*98*4321*1';
let elementArray = text.split('*');
let found = elementArray.indexOf('98');
if(found != -1){
	//$target found and is contained in index $found of the array. 
  	console.log(found);
}

array_splice() and join() for PHP and splice () and join () for JavaScript on array

Now that we know the presence of 98 (for go back) and 99 (go to main menu) will result in removing some user inputs every time we receive the string. Both array_splice() for PHP and splice() for JavaScript function are used to remove elements from an array and replace[optional] it with new elements. On the other hand, join () creates and returns a new string by concatenating all of the elements in an array by a specified separator.

For instance:

const elements = ['1', '12345', '3'];
console.log (elements.join('*'));

//Will print 1*12345*3

Now how do we transform 2*254726172578*400*1234*99*2*25472617257 to 2*254726172578,  2*254726172578*400*1234*98*4321*1 to 2*254726172578*400*4321*1 and 2*254726172578*99*2*254726172578*400*1234*98*4321*1 to 2*254726172578*400*4321*1?

Let us write two functions goBack and goToMainMenu, which receives the string and returns what we want.

    $text = "2*254726172578*400*1234*99*2*25472617257";
    //$text = "2*254726172578*400*1234*98*4321*1";
    //$text = "2*254726172578*99*2*254726172578*400*1234*98*4321*1";
    
    //Each function receives a string and returns a string
    //So one can chain the functions as below
    $text = goBack(goToMainMenu($text));

    echo $text;


    function goBack($text){
        $elementArray = explode("*",$text);
        //The while loop is used to ensure that all occurences of "98" are captured
        while(array_search("98",$elementArray, true) !=false){
            $index = array_search("98",$elementArray, true);
            array_splice($elementArray, $index-1,2);
        }
        return join("*",$elementArray);
    }


    function goToMainMenu($text){
        $elementArray = explode("*",$text);
        while(array_search("99",$elementArray, true) !=false){
            $index = array_search("99",$elementArray, true);
            array_splice($elementArray,0,$index+1);
        }
        return join("*",$elementArray);
    }

In JavaScript, the above code can be written as follows:

    //let text = "2*254726172578*400*1234*99*2*25472617257";
    let text = "2*254726172578*400*1234*98*4321*1";
    //let text = "2*254726172578*99*2*254726172578*400*1234*98*4321*1";
    
    //Each function receives a string and returns a string
    //So one can chain the functions as below
    text = goBack(goToMainMenu(text));

   console.log (text);

    function goBack(text){
        let elementArray = new String(text).split('*');
        //The while loop is used to ensure that all occurences of "98" are captured. 
        while(elementArray.indexOf("98") != -1){
            let index = elementArray.indexOf("98");
            elementArray.splice(index-1,2);
        }
        return elementArray.join("*");
    }


    function goToMainMenu($text){
        let elementArray = new String(text).split('*');
        while(elementArray.indexOf("99") != -1){
            let index = elementArray.indexOf("99");
            elementArray.splice(0,index+1);
        }
        return elementArray.join("*");
    }

If you are a Node developer, there exists a utility package for easier routing i.e. going back and going to the main menu which is already published as a node package.

Links to official documentation for PHP and JavaScript's Array and String methods

Conclusion

In this article, we have discussed important PHP and JavaScript functions, which may improve your productivity when using Africa's Talking USSD API. There are many ways of addressing the challenges discussed but the ones we have discussed in this article are some of the ways.

Thank you stopping by.

See you in the next article.

Disclaimer  

I DO NOT work for Africa's Talking.

You've successfully subscribed to Decoded For Devs
Welcome back! You've successfully signed in.
Great! You've successfully signed up.
Your link has expired
Success! Your account is fully activated, you now have access to all content.