Introduction
To be honest I have always had issues with USSD applications. I wanted a way to make creating USSD applications manageable.
Usually, USSD applications move from one state to another. Several cases must be managed.
- what input and what type do we expect?
- how do we handle empty cases?
- can we go back?
- do we want to log the current state?
- do we want to version our ussd state machine?
Problem statement
this is borrowed from the Africastalking June Technical Challenge, just the first part.
User journey: person dials the USSD Code and gets prompted for a username and email address.
What is this state machine?
I wont try to make this complex but I will choose to use a normal map in a ussd.edn
file.
there are two fixed states :start
and :finish
. These tell us where we are. We also have all the valid choices in their own set which are the expected user inputs, plus we have versioning.
What is appealing about this is that this map can be changed by someone who doesn't know anything about programming.
the layout is pretty simple
current state | via | next state |
---|---|---|
:start | :init | :text |
:ready | "1" | :query-email |
:query-email | :empty | :query-email |
:query-email | :not-empty | :query-username |
:query-username | :empty | :query-username |
:query-username | :not-empty | :finish |
{:fsm
{:start {:init {:text "Welcome to the USSD application.\nWe are registering users.\nPress 1 to continue or just cancel.",
:next-state :ready}}
:ready {"1" {:next-state :query-email
:text "Please enter your email address."}}
:query-email {:empty {:next-state :query-email
:text "Sorry, the text is empty.\nPlease enter an email"}
:not-empty {:next-state :query-username
:text "Please enter a username."}}
:query-username {:empty {:next-state :query-username
:text "Sorry, the text is empty.\nPlease enter a username"}
:not-empty {:next-state :finish
:text "Thank you for participating in the registration."}}
:finish :finish}
:choices #{"1"}
:version "0.0.1"}
the callback
when our ussd application receives a callback from the Africastalking Service we get:
- session-id
- phone-number
- network-code
- service-code
- text
how the database looks
{"ATUid_7c6bad2c84927fcd17cf8331b5c3e497"
{:phone-number +254XXXXXXX
:network-code XXXXXX
:service-code *384*XXXX#
:text ""
:current-state :start
:current-state-response "Welcome to the USSD Application\n"
:past-state [{:from :start :via :init :ready}]}
By storing all the past states like this we are able to find out where our users are having a problem or even create a situation that allows our users to go back if they had an error of some kind.
overview
does the session exist? we check the current-state then we use the ussd finite state machine to to get the next state and then respond with the text response.
example:
{:next-state :query-email
:text "Please enter your email address."}
if the session does not exist? we just associate
the new session-id on to the database.
the code is below
https://gist.github.com/kevinmungai/4a8fcf9a56a055dc1ac6eb9884db987f
Top comments (1)
This is interesting.
There is this course, which was published recently - a very comprehensive one.
skillsday.co/courses/building-and-...