Build XML based USSD menus.

Overview

License Unit Tests Code Quality Code Coverage Documentation

Table of Contents

Overview

Build USSD menus with ease.

Instead of having tonnes of nested, complex PHP files, this package give you the ability to construct your menus in XML and execute them as though they were plain PHP files.

This approach greatly shrinks the code footprint as well as increase readability.

Let's see an example for a simple would be SACCO USSD application.

">
xml version="1.0" encoding="UTF-8"?>
<menu name="sacco">
    <action name="check-user"/>
    <options header="SACCO Services" noback="no">
        <option text="Savings">
            <list header="Saving Accounts" provider="saving-accounts" prefix="account"/>
            <options header="Savings">
                <option text="Deposit">
                    <options header="Deposit From:">
                        <option text="My Number">
                            <variable name="sender" value="{{phone_number}}"/>
                        option>
                        <option text="Another Number">
                            <question name="sender" text="Enter Phone Number: "/>
                        option>
                    options>
                    <question name="amount" text="Enter Amount: "/>
                    <action name="deposit"/>
                option>
                <option text="Withdraw">
                    <options header="Withdraw To:">
                        <option text="My Number">
                            <variable name="receiver" value="{{phone_number}}"/>
                        option>
                        <option text="Another Number">
                            <question name="receiver" text="Enter Phone Number: "/>
                        option>
                    options>
                    <question name="amount" text="Enter Amount: "/>
                    <action name="withdraw"/>
                option>
                <option text="Check Balance">
                    <action name="check-balance" text="To see your balance, enter PIN: "/>
                option>
                <option text="Check Transaction">
                    <question name="transaction_id" text="Enter Transaction ID: "/>
                    <action name="check-transaction"/>
                option>
            options>
        option>
        <option text="Loans">
            <response text="Coming soon."/>
        option>
    options>
menu>

Installation

Install the package via the Composer.

composer require bmatovu/laravel-ussd

Configurations

php artisan vendor:publish --provider="Bmatovu\Ussd\UssdServiceProvider" --tag="config"

Usage

Example

menus/menu.xml

">
xml version="1.0" encoding="UTF-8" ?>
<menu name="demo">
    <question name="guest" text="Enter Name: "/>
    <response text="Hello {{guest}}."/>
menu>
use Bmatovu\Ussd\Ussd;
use Illuminate\Http\Request;
use Illuminate\Http\Response;

/**
 * @see https://developers.africastalking.com/docs/ussd/overview
 */
class UssdController extends Controller
{
    public function __invoke(Request $request): Response
    {
        try {
            $ussd = new Ussd('menu.xml', $request->session_id);

            $output = $ussd->handle($request->text);
        } catch(\Exception $ex) {
            return response('END ' . $ex->getMessage());
        }

        return response('CON ' . $output);
    }
}

Validation

Publish the menu schema (optional). Defaults to using the schema bundled within the package if none is present in your menus path, usually menus/menu.xsd.

php artisan vendor:publish --provider="Bmatovu\Ussd\UssdServiceProvider" --tag="schema"

Validate your menu files against the schema

php artisan ussd:validate

Simulator

The package comes with a CLI USSD simulator supporting a handful of populator aggregators.

Publish the simulator config file to get started. Update the aggregator and the USSD service endpoint in the config file.

php artisan vendor:publish --provider="Bmatovu\Ussd\UssdServiceProvider" --tag="simulator"

Usage:

./vendor/bin/ussd --help
./vendor/bin/ussd 256772100103

If you're an aggregator missing from the current list reachout to have you added. Or simply send a pull request

Constructs

Variable

$color = 'blue';
">
<variable name="color" value="blue"/>

Note: This tag has no output

Question

$username = readline('Enter username: ');
">
<question name="username" text="Enter username: "/>

Response

exit('Thank you for banking with us.');
">
<response text="Thank you for banking with us."/>

Note: this tag throws an exception to mark a break in the normal flow.

Options

Options are like named grouped if, else-if statements that allow a user to navigate to a predefined path.

$choice = readline('Choose gender [1. Male, 2. Female]: ');

if($choice === 1) {
    // do male stuff
} elseif($choice === 2) {
    // Do female stuff
}
">
<options header="Choose gender">
    <option text="Male">
        
    option>
    <option text="Female">
        
    option>
options>

Disable backward navigation

By default 0) Back option will be added to the options rendered. Use the attribute noback to this able this behavior.

This behavior may only be used for nested tags.

">
<options header="Choose gender" noback="no">
    
options>

If

Can container any other tags inclusive of the IF tag itself.

if($gender == 'male') {
    // ...
}
">
<if key="gender" value="male">
    
if>

Choose

This construct should cover for if-else, if-elseif-else, and the native switch.

Example #1

if($gender == 'male') {
    // ...
} else {
    // ...
}
">
<choose>
    <when key="gender" value="male">
        
    when>
    <otherwise>
        
    otherwise>
choose>

Example #2

if($gender == 'male') {
    // ...
} elseif($gender == 'female') {
    // ...
} else {

}
">
<choose>
    <when key="gender" value="male">
        
    when>
    <when key="gender" value="female">
        
    when>
    <otherwise>
        
    otherwise>
choose>

Example #3

switch ($gender) {
    case "male":
        // ...
        break;
    case "female":
        // ...
        break;
    default:
        // ...
}
">
<choose>
    <when key="gender" value="male">
        
    when>
    <when key="gender" value="female">
        
    when>
    <otherwise>
        
    otherwise>
choose>

Action

The action tag gives you the ability to perform more customized operations.

$userInfo = \App\Ussd\Actions\GetUserInfoAction('256732000000');
">

<action name="get-user-info"/>

<action name="get-user-info" msisdn="256732000000"/>

<action name="get-user-info" msisdn="{{msisdn}}"/>

Note: Actions behave just like the normal tag i.e they can take input from a user or cache, and may or may not return output.

List

List are showing dynamic items. E.g: user accounts fetched on demand.

Provider is the class providing the list of items. Each item must container an id and a label.

$listItems = (new \App\Ussd\Providers\SavingAccountsProvider)->load();

[
    [
        'id' => 4364852, // account_id 
        'label' => '01085475262', // account_number
    ],
];
">
<list header="Saving Accounts" provider="saving-accounts" prefix="account"/>

Advanced

Cache

This package persists USSD session data in cache. Each key is prefixed with the session_id and it automatically expires after the configured ttl.

Accessing variables

$this->store->get('color'); // blue Cache::store($driver)->get("{$sessionId}color"); // blue">
color" value="blue"/>

$this->store->get('color'); // blue

Cache::store($driver)->get("{$sessionId}color"); // blue

Reusing existing variables

">
<variable name="msg" value="Bye bye."/>

<response text="{{msg}}"/> 

Manual injection

$this->store->put('color', 'pink');

Parser

Save default variables

Example for saving any variable from the incoming USSD request.

(new Ussd($menu, $request->session_id))
    // ->save($request->all())
    ->save([
        'phone_number' => $request->phone_number,
        'network_code' => $request->network_code,
    ]);

Use custom menu entry point

By default the parsing starts at the 1st element in you menu file, i.e /menu/*[1].

If you wish to start from a different point or using a custom menu file structure. Here's how to go about it...

(new Ussd($menu, $request->session_id))
    ->entry("/menus/menu[@name='sacco']/*[1]");

See: xpath playground

Simulator

You can extend the USSD simulator with your aggregator of choice by simply registering it in the simulator config file.

The provider class should implement Bmatovu\Ussd\Contracts\Aggregator.

simulator.json

  {
+     "aggregator": "hubtel",
      "aggregators": {
+         "hubtel": {
+             "provider": "App\\Ussd\\Simulator\\Hubtel",
+             "uri": "http://localhost:8000/api/ussd/hubtel",
+             "service_code": "*123#"
+         }
      }
  }

JSON

Why use XML 🥴 and not JSON ☺️ ?

Compare the snippets below...

">
<menu name="demo">
    <question name="guest" text="Enter Name: "/>
    <response text="Hello {{guest}}."/>
menu>
{
    "@name": "demo",
    "question": {
        "@name": "guest",
        "@text": "Enter Name:"
    },
    "response": {
        "@text": "Hello {{guest}}."
    }
}

XML is more suited for writing programming language like constructs. It's very easy to validate XML schemas. XML is also more compact and readable 🥰 .

Testing

To run the package's unit tests, run the following command:

composer test

Security

If you find any security related issues, please contact me directly at [email protected] to report it.

Contribution

If you wish to make any changes or improvements to the package, feel free to make a pull request.

Note: A contribution guide will be added soon.

Alternatives

License

The MIT License (MIT). Please see License file for more information.

You might also like...
Laravel Homestead Build Scripts

Laravel Settler The scripts that build the Laravel Homestead development environment. End result can be found at https://app.vagrantup.com/laravel/box

👻 It's never been easier to build and customize admin panels. Yah! yaldash is a beautifully designed administration panel for Laravel.
👻 It's never been easier to build and customize admin panels. Yah! yaldash is a beautifully designed administration panel for Laravel.

👻 It's never been easier to build and customize admin panels. Yah! yaldash is a beautifully designed administration panel for Laravel.

Viewi for Laravel: Build full-stack and completely reactive user interfaces with PHP.

[WIP] Laravel Viewi This is just a proof-of-concept. Don't use it in production! Viewi for Laravel: Build full-stack and completely reactive user inte

A demo of how to use filament/forms to build a user-facing Form Builder which stores fields in JSON.

About Laravel Laravel is a web application framework with expressive, elegant syntax. We believe development must be an enjoyable and creative experie

Electrik is a full-featured, open-source, starter-kit to help you build you your SaaS application.
Electrik is a full-featured, open-source, starter-kit to help you build you your SaaS application.

Electrik Electrik is a full-featured and open-source stater-kit for for your next SaaS application. It's built on top of Laravel, Livewire, neerajsoha

CV-Resumes-App is helped us to build resume .. you can help me to improve this app...

About Laravel Laravel is a web application framework with expressive, elegant syntax. We believe development must be an enjoyable and creative experie

Awes.io // boilerplate based on Vue, Nuxt, TailwindCSS plus Laravel as a backend. 🤟
Awes.io // boilerplate based on Vue, Nuxt, TailwindCSS plus Laravel as a backend. 🤟

Platform for Interactive Business Applications 10x faster to create than the traditional way • 3x increase application experiences • 60% decrease in d

Determine the geographical location of website visitors based on their IP addresses.

GeoIP for Laravel Determine the geographical location and currency of website visitors based on their IP addresses. GeoIP for Laravel on Packagist Geo

Ubilling is opensource ISP billing system based on stargazer

Ubilling Ubilling is opensource ISP billing system based on stargazer. Please visit our official resources: Project homepage Documentation Community f

Releases(v1.0.1)
Build structured navigation menus in Filament.

Build structured navigation menus in Filament. This plugin for Filament provides a Navigation resource that allows to build structural navigation menu

HappyToDev 0 Jun 29, 2022
Navigator is a package to create headless navigation menus for use in Laravel applications

Navigator Navigator is a package to create headless navigation menus for use in Laravel applications: // In a Service Provider Nav::define(fn ($user)

Sam Rowden 36 Oct 30, 2022
Fullstack komponents to write Forms, Queries and Menus in Laravel

kompo.io • Documentation • Demos • Twitter kompo/kompo kompo/kompo is a library of Fullstack Komponents to help you write forms, queries and menus in

Bass El Hachem 107 Dec 5, 2022
PHP Simple Response, XML, JSON,... auto response with accept in request's header

simple-response Simple package to handle response properly in your API. This package does not include any dependency. Install Via Composer $ composer

Phuong Danh 3 Dec 8, 2021
⚡ Laravel Charts — Build charts using laravel. The laravel adapter for Chartisan.

What is laravel charts? Charts is a Laravel library used to create Charts using Chartisan. Chartisan does already have a PHP adapter. However, this li

Erik C. Forés 31 Dec 18, 2022
A Laravel package making a diagram of your models, relations and the ability to build them with it

Laravel Schematics This package allows you to make multiple diagrams of your Eloquent models and their relations. It will help building them providing

Maarten Tolhuijs 1.4k Dec 31, 2022
The guide to build a Laravel 5.2 app from a to z.

Laravel Apz The guide to build a Laravel 5.2 app from a to z. Step-by-Step Tutorial (Start Here!) https://github.com/jp7internet/laravel-apz/wiki Scre

JP7 327 Dec 20, 2022
Online Shop build in Laravel

About Laravel Laravel is a web application framework with expressive, elegant syntax. We believe development must be an enjoyable and creative experie

Steve McDougall 32 Dec 7, 2022
Laravel Kickstart is a Laravel starter configuration that helps you build Laravel websites faster.

Laravel Kickstart What is Laravel Kickstart? Laravel Kickstart is a Laravel starter configuration that helps you build Laravel websites faster. It com

Sam Rapaport 46 Oct 1, 2022
A suit of basic files samples to build a light-weight , short-handed & a strong Laravel REST API Applications.

Concerning Laravel. I found myself repeating a very basic form of code each time i begin a new REST API. in which the whole Interface's pieces are dev

Adnane Kadri 1 Nov 22, 2021