nyumbani / daraja
A small Laravel client for Safaricom's Daraja API: STK push, C2B and Pull transactions, with the payloads, events and middleware to receive them.
Requires
- php: ^8.3
- illuminate/http: ^12.0||^13.0
- illuminate/support: ^12.0||^13.0
Requires (Dev)
- nyumbani/docs: ^1.1
Suggests
- nyumbani/docs: The local-only guides of Nyumbani packages, chosen in php artisan nyumbani:install and installed with composer require --dev nyumbani/docs
Provides
None
Conflicts
None
Replaces
None
README
A small Laravel client for Safaricom's Daraja API: STK push, C2B URL registration and Pull transactions, plus the payload parsers, middleware, and response helpers to receive them. It requires only Laravel.
Requirements
- PHP 8.3 or newer and Laravel 12 or 13
- A Safaricom Daraja app with a short code, consumer key and secret, and a pass key for STK push
Install
- Require it:
composer require nyumbani/daraja
- Set the environment in
.env. Credentials normally live wherever your app keeps them (see Short code below); these keys feed the local docs only:
DARAJA_ENVIRONMENT=sandbox
DARAJA_SHORT_CODE=
DARAJA_CONSUMER_KEY=
DARAJA_CONSUMER_SECRET=
DARAJA_PASS_KEY=
DARAJA_TILL_NUMBER=
- Optionally publish the configuration (the Safaricom IP allow-list and the environment switch):
php artisan vendor:publish --tag=daraja-config
- Call it, and guard the routes Safaricom posts to (see below). In an app with
nyumbani/essentials,php artisan nyumbani:install --with=darajadoes steps 1 to 3 for you.
Short code
Set the environment, sandbox or production, in your .env (it defaults to production):
DARAJA_ENVIRONMENT=sandbox
To use another environment for one client, call live() or sandbox(): Daraja::for($shortCode)->sandbox().
Build a ShortCode wherever your credentials live (env, config or a database row):
use Nyumbani\Daraja\ShortCode; $shortCode = new ShortCode( value: '174379', consumerKey: '...', consumerSecret: '...', passKey: '...', tillNumber: null, // set for Buy Goods );
Calls
use Nyumbani\Daraja\Daraja; $daraja = Daraja::for($shortCode); $daraja->stkPush('0712345678', 100, 'INV-1', 'Order payment', $callbackUrl); $daraja->registerC2BUrls($validationUrl, $confirmationUrl); $daraja->registerPullUrl('0712345678', $callbackUrl); $daraja->pullTransactions(); // last 48 hours, or pass from and to
Each call returns Laravel's HTTP client response, so use successful(), failed() and json(). Daraja can answer 200 with a failure code, so also check ResponseCode (0 for an STK push, 1000 for the Pull calls).
Receiving payments
Validation, confirmation, Pull and STK push callbacks are your app's routes, so it decides which paybill a request belongs to, how to read the payload and what to do with it. The package only guards them:
use App\Http\Controllers\ConfirmationController; use Illuminate\Support\Facades\Route; use Nyumbani\Daraja\Http\Middleware\EnsureRequestIsFromSafaricom; Route::post('hooks/{paybill}/confirm', [ConfirmationController::class, 'store']) ->middleware(EnsureRequestIsFromSafaricom::class);
EnsureRequestIsFromSafaricom checks daraja.allowed_ips (skipped in daraja.skip_ip_check_in environments) and answers other addresses with C2B00016.
stkPush() needs the callbackUrl Safaricom posts the result to. daraja_phone() normalises a Kenyan number to the 254XXXXXXXXX format Daraja expects.
Docs
The package suggests nyumbani/docs (composer require --dev nyumbani/docs), which then serves the docs locally at /nyumbani-daraja/docs, in any Laravel app. The package works without it.