- Notifications
You must be signed in to change notification settings - Fork38
sparors/laravel-ussd
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
Build Ussd (Unstructured Supplementary Service Data) applications with laravel without breaking a sweat.
You can install the package via composer:
composer require sparors/laravel-ussd:^3.0-beta
For older version use
composer require sparors/laravel-ussd:^2.0
Laravel Ussd provides zero configuration out of the box. To publish the config, run the vendor publish command:
php artisan vendor:publish --provider="Sparors\Ussd\UssdServiceProvider" --tag=ussd-config
For older version look here:V2 README
<?phpnamespaceApp\Ussd\States;useApp\Ussd\Actions\TransferAccountAction;useSparors\Ussd\Attributes\Paginate;useSparors\Ussd\Attributes\Transition;useSparors\Ussd\Context;useSparors\Ussd\Contracts\State;useSparors\Ussd\Decisions\Equal;useSparors\Ussd\Decisions\Fallback;useSparors\Ussd\Decisions\In;useSparors\Ussd\Menu;useSparors\Ussd\Record;useSparors\Ussd\Traits\WithPagination;#[Transition(to: TransferAccountAction::class, match:newEqual(1))]#[Transition(to: TransferAmountState::class, match:newIn(2,3), callback: [self::class,'setTransferType'])]#[Transition(to: NewAccountNameState::class, match:newEqual(4))]#[Transition(to: HelplineState::class, match:newEqual(5))]#[Transition(to: InvalidInputState::class, match:newFallback())]#[Paginate(next:newEqual('#'), previous:newEqual('0'))]class CustomerMenuStateimplements State{use WithPagination;publicfunctionrender():Menu {return Menu::build() ->line('Banc') ->listing($this->getItems(), page:$this->currentPage(), perPage:$this->perPage()) ->when($this->hasPreviousPage(),fn (Menu$menu) =>$menu->line('0. Previous')) ->when($this->hasNextPage(),fn (Menu$menu) =>$menu->line('#. Next')) ->text('Powered by Sparors'); }publicfunctionsetTransferType(Context$context,Record$record) {$transferType ='2' ===$context->input() ?'deposit' :'withdraw';$record->set('transfer_type',$transferType); }publicfunctiongetItems():array {return ['Transfer','Deposit','Withdraw','New Account','Helpline', ]; }publicfunctionperPage():int {return3; }}
An example of a final state
<?phpnamespaceApp\Ussd\States;useSparors\Ussd\Attributes\Terminate;useSparors\Ussd\Contracts\State;useSparors\Ussd\Menu;useSparors\Ussd\Record;#[Terminate]class GoodByeStateimplements State{publicfunctionrender(Record$record):Menu {return Menu::build()->text('Bye bye' .$record->get('name')); }}
Due to some limitation with PHP 8.0, you can not pass class instance to attributes. So to overcome this limitation, you can pass an array with the full class path as the first element and the rest should be argument required. eg.
<?phpnamespaceApp\Ussd\States;useSparors\Ussd\Attributes\Transition;useSparors\Ussd\Contracts\State;useSparors\Ussd\Menu;#[Transition(MakePaymentAction::class, [Equal::class,1])]#[Transition(InvalidInputState::class, Fallback::class)]class WelcomeStateimplements State{publicfunctionrender():Menu {return Menu::build()->text('Welcome'); }}
<?phpnamespaceApp\Http\Controllers;useApp\Ussd\Actions\MenuAction;useApp\Ussd\Responses\AfricasTalkingResponse;useApp\Ussd\States\WouldYouLikeToContinueState;useIlluminate\Http\Request;useSparors\Ussd\Context;useSparors\Ussd\ContinuingMode;useSparors\Ussd\Ussd;class UssdControllerextends Controller{publicfunction__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,now()->addMinute(), WouldYouLikeToContinueState::class) ->useResponse(AfricasTalkingResponse::class) ->run(); }}
Use USSD action to conditional decide which state should be the next.
<?phpnamespaceApp\Http\Ussd\Actions;useSparors\Ussd\Contracts\Action;useApp\Http\Ussd\States\PaymentSuccessState;useApp\Http\Ussd\States\PaymentErrorState;class MakePaymentextends Action{publicfunctionexecute(Record$record):string {$response = Http::post('/payment', ['phone_number' =>$record->phoneNumber ]);if ($response->ok()) {return PaymentSuccessState::class; }return PaymentErrorState::class; }}
You can use configurator to simplify repetitive parts of your application so they can be shared easily.
<?phpnamespaceApp\Http\Ussd\Configurators;useSparors\Ussd\Contracts\Configurator;class Nsanoimplements Configurator{publicfunctionconfigure(Ussd$ussd):void {$ussd->setResponse(function (string$message,int$terminating) {return ['USSDResp' => ['action' =>$termination ?'prompt':'input','menus' =>'','title' =>$message ] ]; }); }}?>
You can easily test how your ussd application with our testing utilities
<?phpnamespaceApp\Tests\Feature;useSparors\Ussd\Ussd;finalclass UssdTestextends TestCase{publicfunctiontest_ussd_runs() { Ussd::test(WelcomeState::class) ->additional(['network' =>'MTN','phone_number' =>'123123123']) ->actingAs('isaac') ->start() ->assertSee('Welcome...') ->assertContextHas('network','MTN') ->assertContextHas('phone_number') ->assertContextMissing('name') ->input('1') ->assertSee('Now see the magic...') ->assertRecordHas('choice'); }}
You'll find the documentation onhttps://github.com/sparors/laravel-ussd/wiki for V3 andhttps://sparors.github.io/ussd-docs for V2.
Please see thechangelog for more information on what has changed recently.
Please seecontributing.md for details and a todolist.
If you discover any security related issues, please emailisaacsai030@gmail.com instead of using the issue tracker.
MIT. Please see thelicense file for more information.