YateUSGW setup

In order to set up YateUSGW equipment, you need first to set the CAMEL USSD subscription information in the CS Profile of the subscribers.

We will assume that set up URL for USGW is

Initial set up

Log in to YateMMI, go to Profile Management context → CS Profile → Edit profile → USSD

Prefix = NNN or *
GW = 8822007141

You may set any number of NNN prefixes – those digits you “dial” like *100# or *100*12345#

Each USSD code (almost always 3 digits) can be routed to its own USSD GW.

If a prefix is set to * (one asterisk) it will match anything after trying the other codes.

Note: While roaming (so this applies to MVNOs) the usual convention is that only codes 100 to 149 are always routed to the home network.

A visited network may intercept any other codes for its own use.

If you receive USSD in YateHLR/HSS, but it looks like below (with no details about IMSI or content of message), you need to set up a correct template for the URL.

GET /receive.php HTTP/1.1
User-Agent: YATE/6.1.1 (yate-usgw)
Accept: text/plain;charset=UTF-8
Connection: Keep-Alive



${id} – Session identifier you need to send back in every request
${operation} – Type of USSD operation
${msisdn} – Phone number
${code} – Only for MO USSD, text of initiating message
${text} – Last text entered, equals ${code} in first message, usually a menu selection digit in subsequent ones


To respond make GET or POST requests to http://ip-of-yate-usgw/usgw/ussd.php and provide:

id – Session identifier you respond to
operation – Type of USSD operation or “stop” to terminate the TCAP dialog
text – Text to be displayed on screen, required for all operations except “stop”


Valid operation sequences


USSD v2 (pretty much the only used today)

   pssr =>
        <= pssr

pssr =>
      <= ussr

 ussr =>
      <= ussr

 ussr =>
        <= pssr

      <= ussr

 ussr =>
       <= ussr

 ussr =>
       <= ussn 

<= ussn


USSD v1 (unlikely to see one of these)

pssd =>
      <= pssd 

At any time any side can issue a “stop” to abort the dialog. Network conditions can also cause an abnormal termination.


An example PHP for handling USSDs.



$ussd_url = “;;


function getparam($param, $def = null)
    if (isset($_GET[$param]))
        return $_GET[$param];
    if (isset($_POST[$param]))
        return $_POST[$param];
     return $def;

function menu($num,$text,&$oper,$user,$code)
    if (“stop” == $oper)
        return “”;
    if (“pssd” == $oper)
        return “You entered: $text\n\nGoodbye!”;
    switch ($text) {
        case “w”:
        case “who”:
        case “*100#”:
            $oper = “ussr”;
            return “Your number is: $num\n\nNext?”;
         case “q”:
         case “quit”:
            if (“true” != $user)
               return “”;
            $oper = “pssr”;
            return “Goodbye!”;
         case “”:
              return “”;
         case “*101#”:
              if (“pssr” == $oper)
                 return “See you on another USSD code!”;
              // fall through
             $oper = “ussr”;
             return “You said: $text\n\nSomething else?”;

header(“Content-Type: text/plain;charset=UTF-8”);

$sync = getparam(“sync”);
$oper = getparam(“operation”);
$final = (“stop” == $oper) || (“” == $sync);

$text = menu(getparam(“msisdn”),getparam(“text”),$oper,getparam(“user”),getparam(“code”));
if ($final)

if (“true” == $sync)
     print $text;
else {
    $id = getparam(“id”);
    $text = urlencode($text);
    $curl = curl_init(“$ussd_url?id=$id&operation=$oper&text=$text”);
    if (false !== $curl) {
        $ret = curl_exec($curl);
        if (false === $ret)
            $ret = “CURL Error: ” + curl_error($curl);
            $ret = “OK, remote returned: $ret”;
        print $ret;
         print “CURL Init Error”;

/* vi: set ts=8 sw=4 sts=4 noet: */

Our solutions