Process USSD Lua Service

Introduction

The ProcessUssdLuaService is a service for initiating Lua scripts running within the LogicApp.

The ProcessUssdLuaService receives a ProcessUnstructuredSSRequest operation contained in a TCAP-RECV message from an instance of the SigtranApp which is configured to receive TCAP messages from an external client.

During the transaction, the ProcessUssdLuaService communicates with the SigtranApp using the TCAP-SEND and TCAP-RECV messages. See the definition of the TCAP-… messages.

Configuring ProcessUssdLuaService

The ProcessUssdLuaService is configured within a LogicApp.

    <?xml version="1.0" encoding="utf-8"?>
    <n2svcd>
      ...
      <applications>
        ...
        <application name="Logic" module="LogicApp">
          <include>
            <lib>../apps/logic/lib</lib>
          </include>
          <parameters>
            ...
          </parameters>
          <config>
            <services>
              <service module="SigtranApp::ProcessUssdLuaService" libs="/usr/share/n2ttg/apps/sigtran/lib/" script_dir="/var/lib/n2svcd/logic/ussd_gw">
                <menu_timeout>10</menu_timeout>
                <error_message>Custom Error String</error_message>
                <triggers>
                  <trigger dest_ssn="120" ussd_string_prefix="*123#" script_key="123"/>
                  <trigger dest_ssn="120" destination="333" script_key="333"/>
                  <trigger dest_ssn="120" ussd_string_prefix="*444#" script_key="444"/>
                  <trigger dest_ssn="120" ussd_string_prefix="*666#" script_key="666"/>
                  <trigger dest_ssn="120" destination="777" script_key="777"/>
                </triggers>
              </service>
            </services>
            <agents>
              ...
            </agents>
          </config>
        </application>
        ...
      </application>
      ...
    </n2svcd>

In addition to the Common LogicApp Service Configuration, note the following specific attribute notes, and service-specific attributes.

Under normal installation, the following service attributes apply:

Parameter Name Type XML Type Description
module String Attribute [Required] The module name containing the Lua Service code: SigtranApp::ProcessUssdLuaService
libs String Element Location of the module for ProcessUssdLuaService.
(Default: ../apps/sigtran/lib)
script_dir String Attribute [Required] The directory containing scripts used by this service.
dcs_language Integer Element The default ussdDataCodingScheme_language.
If not present, a codec-specified default is applied.
menu_timeout Integer Element The default duration (in seconds) after which the script will resume if no result/error is received.
notify_timeout Integer Element The default duration (in seconds) after which the script will assume a notify has failed if no result/error is received.
error_message String Element The message which will be returned to the subscriber if an unhandled error occurs in then Lua script.
The internal script error will be written to the application log, but will not be sent to the subscriber.
.triggers Array Element Array of trigger elements specifying Lua scripts to run for USSD Inbound Transactions.
.trigger Object Element Provisions a Lua script to run for a USSD Inbound Transaction for received ProcessUssdRequest operations.

Script Trigger Rules

Each USSD Incall trigger rule defines the name of a script which is ready to handle an inbound USSD Transaction.

Note that destination and origination addresses may contain hex digits A-F, and the matching is for destination_prefix and origination_prefix is case-insensitive. However, the string matching for ussd_string_prefix is case-sensitive.

Each trigger Object in the config.triggers Array is configured as follows.

Parameter Name Type XML Type Description
ssn 1-255 Attribute This trigger applies for only USSD Transactions to this exact SCCP subsystem number.
(Default = Trigger applies to all SCCP subsystem numbers).
ussd_string_prefix String Attribute This trigger applies for only USSD ProcessUnstructuredSSRequest with content beginning with this sub-string.
(Default = Trigger applies to all ProcessUnstructuredSSRequest).
destination Hex Digits Attribute This trigger applies for only USSD ProcessUnstructuredSSRequest to this exact destination reference digits (in MAP Open).
(Default = Trigger applies to all ProcessUnstructuredSSRequest).
destination_prefix Hex Digits Attribute This trigger applies for only USSD ProcessUnstructuredSSRequest to destination reference digits (in MAP Open) with this prefix.
(Default = Trigger applies to all ProcessUnstructuredSSRequest).
origination Hex Digits Attribute This trigger applies for only USSD ProcessUnstructuredSSRequest from this exact origination reference digits (in MAP Open).
(Default = Trigger applies to all ProcessUnstructuredSSRequest).
origination_prefix Integer Attribute This trigger applies for only USSD ProcessUnstructuredSSRequest from origination reference digits (in MAP Open) with this prefix.
(Default = Trigger applies to all ProcessUnstructuredSSRequest).
script_key String Attribute The key for the Lua script to load. This is the file name excluding the ".lua" suffix.
The script should reside in the directory configured for the LogicApp's lua_script_dir, or in the specified subdirectory if script_subdir is configured for this service library.

Script Selection (USSD Transaction Request)

The Lua script selection to execute for a USSD ProcessUnstructuredSSRequest takes into consideration the received content of the inbound TCAP_BEGIN transaction and/or the MAP content and/or the SCCP addressing information.

The destination address for matching is:

The origination address for matching is:

The Process USSD Lua Service will iterate the configured trigger entries in the sequence in which they are configured and find the first trigger which matches the parameters of the received message.

Refer to the LogicApp configuration for more information on directories, library paths, and script caching parameters.

Script Global Variables

Scripts run with this service have access to the Common LUA Service Global Variables.

There are no service-specific global variables.

Script Entry Parameters (USSD Request)

The Lua script must be a Lua chunk which returns an n2svcd.handler, such as the following:

    local n2svcd = require "n2.n2svcd"
    local pussds_api = require "n2.n2svcd.pussds_api"

    -- The args contain the content of the ProcessUnstructuredSSRequest sent by the HLR.
    local handler = function (args)

        -- This sends UnstructuredSSRequest and expects a UnstructuredSSRequest / ReturnResult.
        local input = pussds_api.menu ("1. Add-ons\n2. Packages\n3. Account Services\n4. Other Services", 2)
        if (type (input) == "nil") then
            return "No input provided.  Session over."
        end

        -- This sends UnstructuredSSNotify within the session.  No response is required, do not wait for possible error.
        pussds_api.notify ("You chose option " .. input .. " thanks.")

        -- This closes the session by sending ProcessUnstructuredSSRequest / ReturnResult.
        return "We'll send an SMS with your usage details."
    end

    return n2svcd.handler (handler)

The handler will be executed with a single ussd entry parameter which is an object with the following attributes:

Attribute Type Description
.remote_sccp SCCP Address Object The far-end SCCP address, as per the TCAP-RECV Message.
.local_sccp SCCP Address Object The near-end SCCP address, as per the TCAP-RECV Message.
.text String The ussdString_text decoded message text copied from .process_ussd.ussdString_text.
.process_ussd Object The decoded attributes of the ProcessUnstructuredSSRequest operation. Some of these attributes may be optional. Site-specific protocol variants may add additional parameters not documented here.
.ussdString Binary The raw encoded bytes of the USSD message content.
.ussdString_text String The decoded text of the ussdString in ASCII or Unicode.
.msisdn Binary The MSISDN (raw bytes) encoded as MAP Address String.
.msisdn_digits HEX String The decoded digits of the MSISDN address.
.msisdn_noa Integer The decoded Nature Of Address of the MSISDN address.
.msisdn_npi Integer The decoded Numbering Plan Indicator of the MSISDN address.
.ussdDataCodingScheme Binary The USSD Data Coding Scheme (raw bytes) encoded as USSD Call Broadcast Data Scheme.
.ussdDataCodingScheme_encoding Integer The decoded encoding of the ussdDataCodingScheme compound field.
.ussdDataCodingScheme_group Integer The decoded group of the ussdDataCodingScheme compound field.
.ussdDataCodingScheme_is_compressed 0/1 The decoded is_compressed of the ussdDataCodingScheme compound field.
.ussdDataCodingScheme_language Integer The decoded language of the ussdDataCodingScheme compound field.
.map_open Table The decoded attributes of the MAP-Open element within the TCAP's MAP Dialogue PDU. Some of these attributes may be optional. Site-specific protocol variants may add additional parameters not documented here.
.destination_reference Binary The Destination Reference (raw bytes) encoded as MAP Address String.
.destination_reference_digits HEX String The decoded digits of the Destination Reference address.
.destination_reference_noa Integer The decoded Nature Of Address of the Destination Reference address.
.destination_reference_npi Integer The decoded Numbering Plan Indicator of the Origination Reference address.
.origination_reference Binary The Origination Reference (raw bytes) encoded as MAP Address String.
.origination_reference_digits HEX String The decoded digits of the Origination Reference address.
.origination_reference_noa Integer The decoded Nature Of Address of the Origination Reference address.
.origination_reference_npi Integer The decoded Numbering Plan Indicator of the Origination Reference address.

Script Return Parameters (USSD Response)

The Lua script is responsible for determing the contents of the ReturnResult for the ProcessUnstructuredSSRequest operation, which will be sent back to the subscriber and conclude the session.

The simplest way to do this is by the return value given back to the service at the end of script execution.

For full control over the USSD response, the script return value may be a response object with the following attributes:

Field Type Description
response Table Container for the USSD response parameters we are to send.
.ussdString Binary The encoded bytes for the USSD String content.
You will generally not specify this value, the service will encode it for you.
.ussdString_text String The user string in ASCII for Unicode that you wish to be encoded.
(Default = None)
.ussdDataCodingScheme_group Integer The encoding group associated with the string encoding.
(Default = 0)
.ussdDataCodingScheme_language Integer The encoding language associated with the string encoding.
(Default = service dcs_language or codec-determined default)
.ussdDataCodingScheme_is_compressed Integer The compression flag associated with the string encoding.
(Default = 0)
.ussdDataCodingScheme_message_class Integer The encoding message class associated with the string encoding.
(Default = 0)
.ussdDataCodingScheme_encoding Integer The encoding type associated with the string encoding.
(Default = 0)

Alternatively, the script may return a string. This is the same as specifying .ussdString_text = (the given simple string) with all other attributes not specified.

Alternatively, the script may return nil in which case the USSD transaction will be closed by sending Empty TCAP END. The subscriber behaviour here may vary according to handset.

Example (returning a Table USSD Response):

    local n2svcd = require "n2.n2svcd"

    local handler = function (ussd)
        return ({ ussdString_text = "Bienvenue a la service", ussdDataCodingScheme_language = 3 })
    end

    return n2svcd.handler (handler)

Alternatively, a script may return a simple string instead of a Table.

Example (returning a String USSD Response):

    local n2svcd = require "n2.n2svcd"

    local handler = function (ussd)
        return "Welcome to the service"
    end

    return n2svcd.handler (handler)

This is a shorthand for ussdString_text = (Text Message) with all other values set to defaults.

Alternatively, a script may return nil.

Example (returning the default success message):

    local n2svcd = require "n2.n2svcd"

    local handler = function (ussd)
        return nil
    end

    return n2svcd.handler (handler)

In this case, the session will be closed with an Empty TCAP END to the subscriber handset.

The ProcessUssdLuaService API

The Process USSD Service API can be loaded as follows.

    local pussds_api = require "n2.n2svcd.pussds_api"

It is not necessary to load the Process USSD Service API if you are only using the simple response mechanism described above. It is only required if you wish to use any of the extended features described below.

.response [Synchronous]

When a Lua script needs to perform extended processing, it may wish to send an early USSD response before the script completes. This can be done with the response method on the USSD Service API.

This method will send a ReturnResult for the ProcessUnstructuredSSRequest operation, within a TCAP_END. The USSD transaction is over. Subsequent calls to response, decline, notify, or menu are not permitted, and will generate a runtime script error.

The response method takes a single response parameter.

Parameter Type Description
response Table or String A simple "text/plain" string, or an Table with the same structure as the returned object described under "Script Return Parameters".

After the response method, the USSD transaction is no longer in progress.

The response method returns the following object structure:

Parameter Type Description
controlled false This field is always false to indicate that the session is no longer under control.
reason Response / Abandon Response - The ReturnResult was successfully sent.
Abandon - The user abandoned with TCAP ABORT or TCAP Empty END prior to the response attempt.

[Fragment] Example Early Response specifying Language:

    ...
    pussds_api.response ({ ussdString_text = "Bienvenue a la service", ussdDataCodingScheme_language = 3 })

    [post-processing logic after USSD transaction is ended]
    ...

[Fragment] Example Early Response with default Language:

    ...
    pussds_api.response ("Welcome to the service")

    [post-processing logic after USSD transaction is ended]
    ...

.decline [Synchronous]

If the Lua service logic script does not wish to process the call, it can indicate error processing by sending a ReturnResult for the ProcessUnstructuredSSRequest operation, within a TCAP_END.

The USSD transaction is over. Subsequent calls to response, decline, notify, or menu are not permitted, and will generate a runtime script error.

The decline method takes a single error_code parameter.

Parameter Type Description
error_code Integer An optional custom error code.
(Default = Call Barred - Error Code 25, or other configured default)

After the decline method, the USSD transaction is no longer in progress.

The decline method returns the following object structure:

Parameter Type Description
controlled false This field is always false to indicate that the session is no longer under control.
reason Decline / Abandon Response - The ReturnResult was successfully sent.
Abandon - The user abandoned with TCAP ABORT or TCAP Empty END prior to the decline attempt.

[Fragment] Decline request using custom error code:

    ...
    pussds_api.decline (pussds_api.ERROR_ILLEGAL_EQUIPMENT)

    return nil

.notify [Asychronous]

As part of the interaction, the Lua script may wish to send intermediate UnstructuredSSNotify messages to the subscriber. There is no response or confirmation for these messages.

The notify method on the USSD API will perform this function.

The script may only use notify while the USSD subscriber session is controlled. i.e. At the start of the script, or after a previous call to notify or menu has returned controlled = true. Invoking notify after a previous call to notify or menu has returned controlled = false is not permitted and will raise a Lua error.

The notify method has two different forms. The “full form” supports the following single parameter:

Parameter Type Description
ussd Table Container for the USSD request parameters we are to send.
.ussdString Binary The encoded bytes for the USSD String content.
You will generally not specify this value, the service will encode it for you.
.ussdString_text String The user string in ASCII for Unicode that you wish to be encoded.
(Default = None)
.msisdn Binary The MSISDN (raw bytes) encoded as MAP Address String.
This is not typically required when a Notify occurs with the context of an established dialog.
.msisdn_digits HEX String The digits of the MSISDN address.
This is not typically required when a Notify occurs with the context of an established dialog.
.msisdn_noa Integer The Nature Of Address of the MSISDN address.
This is not typically required when a Notify occurs with the context of an established dialog.
.msisdn_npi Integer The Numbering Plan Indicator of the MSISDN address.
This is not typically required when a Notify occurs with the context of an established dialog.
.ussdDataCodingScheme_group Integer The encoding group associated with the string encoding.
(Default = 0)
.ussdDataCodingScheme_language Integer The encoding language associated with the string encoding.
(Default = service dcs_language or codec-determined default)
.ussdDataCodingScheme_is_compressed Integer The compression flag associated with the string encoding.
(Default = 0)
.ussdDataCodingScheme_message_class Integer The encoding message class associated with the string encoding.
(Default = 0)
.ussdDataCodingScheme_encoding Integer The encoding type associated with the string encoding.
(Default = 0)
seconds Number The timeout in seconds for the script to wait for an ReturnResult/ReturnError response from the network.
(Default = Service configured notify_timeout value).

The “simplified form” accepts a simple text argument, which is sufficient for most purposes:

Parameter Type Description
text String A simple "text/plain" string which will be the ussdString_text in the request.
seconds Number The timeout in seconds for the script to wait for an ReturnResult/ReturnError response from the network.
(Default = Service configured notify_timeout value).

After the notify method, the USSD transaction may or may not be in progress.
The result.controlled field will indicate if the USSD interaction is still under our control.

The notify method returns the following object structure:

Parameter Type Description
controlled Boolean This attribute is true if the USSD session is still proceeding.
It will be always true in the case of reason Notify.
It will be always false in the case of reason Abandon.
reason Notify / Error / Abandon / Timeout Notify - Acknowledgement was received. controlled may be true or false.
Error - A user/network error code was received within the timeout window. controlled may be true or false.
Abandon - The user/network abandoned with TCAP ABORT or TCAP Empty END. controlled = false.
Timeout - The handset did not acknowledge the notify within the timer. controlled = true.
error_code Integer Present if and only if reason = Error.
The user/network-provided error code number.

[Fragment] Example Notification specifying Language:

    ...
    pussds_api.notify ({ ussdString_text = "En cours.  Patientez SVP.", ussdDataCodingScheme_language = 3 })
    ...
    [additional logic including further USSD interactions]
    ...

[Fragment] Example Notification with default Language, wait for possible error:

    ...
    -- Wait up to 1.5 seconds to see if an error is returned from the handset.
    pussds_api.notify ("Working... please wait.", 1.5)
    ...
    [additional logic including further USSD interactions]
    ...

As part of the interaction, the Lua script may wish to send intermediate UnstructuredSSRequest messages to the subscriber. This is effectively a “menu prompt”. The subscriber will be shown a text, and prompted to enter additional input which is returned to the service in a ReturnResult component for the UnstructuredSSRequest operation.

The script may only use menu while the USSD subscriber session is controlled. i.e. At the start of the script, or after a previous call to notify or menu has returned controlled = true. Invoking menu after a previous call to notify or menu has returned controlled = false is not permitted and will raise a Lua error.

The script will suspend until the subscriber input is received, or until the configurable time value expires.

The request method has two different forms. The “full form” supports the following two parameters:

Parameter Type Description
ussd Table Container for the USSD request parameters we are to send.
This is the same as for the notify method.
seconds Number The timeout in seconds before the script resumes processing without input.
(Default = Service configured menu_timeout value).

The “simplified form” accepts a simple text argument, which is sufficient for most purposes:

Parameter Type Description
text String A simple "text/plain" string which will be the ussdString_text in the request.
seconds Integer The timeout in seconds before the script resumes processing without input.
(Default = Service configured menu_timeout value).

In either case, the menu method returns the following object structure:

Parameter Type Description
controlled Boolean This attribute is true if the USSD session is still proceeding.
It will be always false in the case of reason Abandon.
reason Input / Error / Abandon / Timeout Input - A user input string was received. controlled may be true or false.
Error - A user/network error code was received. controlled may be true or false.
Abandon - The user/network abandoned with TCAP ABORT or TCAP Empty END. controlled = false.
Timeout - The handset did not respond within the timer. controlled = true.
error_code Integer Present if and only if reason = Error.
The user/network-provided error code number.
text String A simple "text/plain" string which will be the ussdString_text from the response.
This is present only when supplied by the subscriber, i.e. only when result.reason = pussds_api.REASON_INPUT.
ussd Table Container for the USSD request result parameters we received.
In the case of timeout or user abandon, this field will be `nil`.
.ussdString Binary The encoded bytes for the USSD String content.
You will generally not specify this value, the service will encode it for you.
.ussdString_text String The user string in ASCII for Unicode that you wish to be encoded.
(Default = None)
.ussdDataCodingScheme_group Integer The encoding group associated with the string encoding.
(Default = 0)
.ussdDataCodingScheme_language Integer The encoding language associated with the string encoding.
(Default = service dcs_language or codec-determined default)
.ussdDataCodingScheme_is_compressed Integer The compression flag associated with the string encoding.
(Default = 0)
.ussdDataCodingScheme_message_class Integer The encoding message class associated with the string encoding.
(Default = 0)
.ussdDataCodingScheme_encoding Integer The encoding type associated with the string encoding.
(Default = 0)

After the menu method, the USSD transaction may or may not be in progress.
The result.controlled field will indicate if the USSD interaction is still under our control.

[Fragment] Full form with custom Timeout:

    ...
    local result = pussds_api.request ({ ussdString_text = "1. Account Balance\n2. My Usage\n3. Recharge History\n4. Recharge\n0. Back" }, 20)

    -- Check for anything other than successful result.
    if (result.reason ~= ussd.REASON_INPUT) then
        return "Session terminated because of " .. result.reason
    end

    -- Now we can access the response text.
    if (result.ussd.ussdString_text == "1") then
        ...
    end
    ...

[Fragment] Simplified form Menu with custom Timeout:

    ...
    local result = pussds_api.menu ("1. Account Balance\n2. My Usage\n3. Recharge History\n4. Recharge\n0. Back", 20)
    if (not result.controlled) then return nil end   
    if (not result.text) then return "No input received to menu.  Session terminated." end

    if (result.text == "1") then
        ...
    end
    ...

.close [Synchronous]

The service logic may use this method to conclude the subscriber interaction without sending back a final response message. This has the same effect as returning nil from the handler method.

However, calling close causes the USSD session (and associated TCAP transaction) to be closed immediately. In general, service logic should call close as soon as possible.
This will free the transaction resources, and (for some handsets) may be necessary before the handset can perform another function.

The close method takes no parameters.

The close method returns nil.

[Fragment] Example close session without sending response:

    ...
    -- Session is no longer required and we have no response.
    pussds_api.close ()
    ...

Constants

The following USSD constants are defined on the returned pussds_api object.

USSD Reason Constants

The following constants are used to indicate the reason that a USSD interaction succeed or failed.

-- USSD Reason Constants.
pussds_api.REASON_RESPONSE = 'Response'
pussds_api.REASON_DECLINE = 'Decline'
pussds_api.REASON_NOTIFY = 'Notify'
pussds_api.REASON_INPUT = 'Input'
pussds_api.REASON_ABANDON = 'Abandon'
pussds_api.REASON_TIMEOUT = 'Timeout'

USSD Error Constants

The following constants are error code values for ReturnError, for example as passed into the decline method.

-- USSD Error Constants.
pussds_api.ERROR_SYSTEM_FAILURE = 34
pussds_api.ERROR_DATA_MISSING = 35
pussds_api.ERROR_UNEXPECTED_DATA_VALUE = 36
pussds_api.ERROR_UNKNOWN_ALPHABET = 71
pussds_api.ERROR_CALL_BARRED = 13
pussds_api.ERROR_ABSENT_SUBSCRIBER = 27
pussds_api.ERROR_ROAMING_NOT_ALLOWED = 8
pussds_api.ERROR_ILLEGAL_SUBSCRIBER = 9
pussds_api.ERROR_ILLEGAL_EQUIPMENT = 12
pussds_api.ERROR_BUSY_SUBSCRIBER = 45
pussds_api.ERROR_UNKNOWN_SUBSCRIBER = 1
pussds_api.ERROR_USSD_BUSY = 72