{
utUssd: {
ussd: {
exposeState: 'true|false', // this will expose runtime
// state if set to true, defaults: false
// refresh: gets refreshed on every cycle;
// static(default): sets only once and will expire
// in predefined period of time (timeOut);
expireRule: 'refresh|static',
timeOut: 1000, // expiration period definition
shortCodes: { // short codes
"*877#": "menu/entrance"
},
maintenanceModeState: "menu/maintenance", // maintenance mode state
wrongInputState: "error/wrongInput", // wrong input state
resumeState: "menu/resume", // resume state
strings: [ // USSD strings
"*877*1*1#",
"*877*1*2#",
"*877*2*1#",
"*877*2*2#",
"*877*2*3#",
"*877*3*1#",
"*877*3*2#",
"*877*4#"
],
defaultPhone: "1234", // default phone number for the simulator
defaultShortCode: "*131#", // default short code for the simulator
charsCount: true, // if characters count should be visible in the simulator
// To display a slogan with the respective text above the phone number input
// (no slogan will be displayed by default)
slogan: 'Test'
}
}
}
USSD menu is defined in template files named view.xml
, each one being in a separate
folder. Folders are usually structured to mirror the USSD menu structure.
For example:
ussd
├── components
| ├── back.xml
| ├── backToHome.xml
| └── footer.xml
└── menu
├── home
| └── view.xml
├── login
| └── view.xml
└── error
| ├── runtimeError
| | └── view.xml
| └── wrongInput
| └── view.xml
└── account
├── balanceEnquiry
| └── view.xml
└── miniStatement
└── view.xml
The template files are JavaScript template literals, passed to ut-function.template engine. Each view file can contain some specific markup as in the below examples:
-
Links
- links are defined with the tag<a id="" href="">
, where the attributeid
represents the USSD input, andhref
represents the next menu to show when this input is received.Menu <a id="1" href="menu/account">1. Account information</a>
-
Expressions
- the standard syntax${}
applicable to JS template literals can be used to define expressions, either simple ones like:${params.system.prevState}
or more complex like iterating over array:
${ params.miniStatement.map( rec => `${rec.amount} on ${rec.postDate}` ).join(`<br/>`) }
or for conditional rendering:
${ params.view === 'pin' ? 'Please enter your PIN' : params.view === 'wrongPin' ? `Wrong PIN.<br/>Please try again' : 'Unexpected Error' }
-
Translations
- the USSD template engine includes the functionT
, which can be used to translate text:${T`Please enter your PIN`}
The syntax is based on JS tagged templates.
-
Includes
- repeated fragments can be included in multiple views using the syntax:Some menu ${include('../../components/back.xml')}
The essential API objects available in the views
${}
expressions are:
- All
node.js
global objects -
T
- the function used for translation -
include
- the function used to include fragments -
params
- object, containing the template parameters
The essential tags available in the views are:
-
<a id="" href="">link</a>
- for defining links to other menus -
<br/>
- for line breaks
Each menu can have an optional controller.js
file,
which handles actions related to the menu.
This file resides in the same folder as the menu's
respective view.js
.
There are two optional actions, that can be defined:
-
send
: This is executed before rendering the current menu. It can call other services to fetch data to be displayed in the menu. -
receive
: This is executed after receiving the response for a particular menu.
Controllers can be defined as object:
module.exports = {
async send(params) {
// some processing
return params;
},
async receive(params) {
// some processing
return params;
}
};
Controllers can be also be defined as a function, returning an object.
This is useful when external API must be called using
the familiar destructuring syntax: import:{}
.
Note that
import
is the only available property at the moment.
module.exports = ({
import: {
subjectObjectPredicate
}
}) => ({
async send(params) {
try {
const result = await subjectObjectPredicate({});
// some processing
return params;
} catch (error) {
params.error = error;
this.redirect('menu/error/runtimeError');
return params;
}
}
});
The official API objects available in the controllers are:
-
import: {subjectObjectPredicate}
- proxy for obtaining external API -
this.redirect(view)
- for selecting the next view