Skip to content

Docs ‐ USSD

Isaac Sai edited this page Jan 20, 2024 · 5 revisions

Introduction to USSD

Creating complicated USSD can be challenging. But with Laravel USSD, it becomes enjoyable. Laravel USSD provides a Ussd class that help build USSD applications. This should be used in a controller or a route closure.

Creating a USSD App

<?php

namespace App\Http\Controllers;

use App\Ussd\Actions\MenuAction;
use App\Ussd\Responses\AfricasTalkingResponse;
use Illuminate\Http\Request;
use Sparors\Ussd\Context;
use Sparors\Ussd\Ussd;

class UssdController extends Controller
{
    public function __invoke(Request $request)
    {
        // Most USSD provider provides the last user input.
        // Africa's Talking API returns all inputs entered by the user separated by *
        $lastText = $request->input('text') ?? '';

        if (strlen($lastText) > 0) {
            $lastText = explode('*', $lastText);
            $lastText = end($lastText);
        }

        return Ussd::build(
            Context::create(
                $request->input('sessionId'),
                $request->input('phoneNumber'),
                $lastText
            )
            ->with(['phone_number' => $request->input('phoneNumber')])
        )
        ->useInitialState(MenuAction::class)
        ->useResponse(AfricasTalkingResponse::class)
        ->run();
    }
}

Resuming USSD sessions

USSD app can easily timeout. This can frustrate your users if you have a very long process and they will have to start all over again. This issue can be fixed by defining how USSD should resume uncompleted sessions. Let configure our USSD to automatically continue from last state when a user dial again within a minute of timeout.

<?php

namespace App\Http\Controllers;

use App\Ussd\Actions\MenuAction;
use App\Ussd\Responses\AfricasTalkingResponse;
use Illuminate\Http\Request;
use Sparors\Ussd\Context;
use Sparors\Ussd\ContinuingMode;
use Sparors\Ussd\Ussd;

class UssdController extends Controller
{
    public function __invoke(Request $request)
    {
        $lastText = $request->input('text') ?? '';

        if (strlen($lastText) > 0) {
            $lastText = explode('*', $lastText);
            $lastText = end($lastText);
        }

        return Ussd::build(
            Context::create(
                $request->input('sessionId'),
                $request->input('phoneNumber'),
                $lastText
            )
            ->with(['phone_number' => $request->input('phoneNumber')])
        )
        ->useInitialState(MenuAction::class)
        ->useContinuingState(ContinuingMode::CONTINUE, now()->addMinute())
        ->useResponse(AfricasTalkingResponse::class)
        ->run();
    }
}

Resuming by asking the user

To ask the user before resuming, use continuing mode confirm and create a new state to ask the user.

<?php

namespace App\Http\Controllers;

use App\Ussd\Actions\MenuAction;
use App\Ussd\Responses\AfricasTalkingResponse;
use App\Ussd\States\WouldYouLikeToContinueState;
use Illuminate\Http\Request;
use Sparors\Ussd\Context;
use Sparors\Ussd\ContinuingMode;
use Sparors\Ussd\Ussd;

class UssdController extends Controller
{
    public function __invoke(Request $request)
    {
        $lastText = $request->input('text') ?? '';

        if (strlen($lastText) > 0) {
            $lastText = explode('*', $lastText);
            $lastText = end($lastText);
        }

        return Ussd::build(
            Context::create(
                $request->input('sessionId'),
                $request->input('phoneNumber'),
                $lastText
            )
            ->with(['phone_number' => $request->input('phoneNumber')])
        )
        ->useInitialState(MenuAction::class)
        ->useContinuingState(ContinuingMode::CONFIRM, null, WouldYouLikeToContinueState::class)
        ->useResponse(AfricasTalkingResponse::class)
        ->run();
    }
}