Skip to content

Upgrading from 4.x to 5.0

v5 is a rewrite. The facade, the class names and the configuration keys have all changed.

4.x 5.0
PHP 7.3+ 8.3+
Laravel 8 12 or 13
use Starnerz\LaravelDaraja\Facades\MpesaApi;
use Starnerz\LaravelDaraja\Facades\Daraja;

The MpesaApi alias is gone. Requests\* classes are replaced by Apis\*, resolved through the facade rather than instantiated.

4.x 5.0
MpesaApi::STK()->push($phone, $amount, $desc, $ref) Daraja::stk()->push($phone, $amount, $ref, $desc)
MpesaApi::STK()->transactionStatus($id) Daraja::stk()->query($id)
MpesaApi::c2b()->registerUrls($conf, $valid) Daraja::c2b()->registerUrls($conf, $valid)
MpesaApi::c2b()->simulatePaymentToPaybill(…) Daraja::c2b()->simulatePayBill(…)
MpesaApi::c2b()->simulatePaymentToTill(…) Daraja::c2b()->simulateBuyGoods(…)
MpesaApi::b2c()->… Daraja::b2c()->business(), ->salary(), ->promotion()
MpesaApi::balance()->… Daraja::balance()->query()
MpesaApi::transaction()->… Daraja::transaction()->query()
MpesaApi::reversal()->… Daraja::reversal()->reverse()
new STK() etc. Resolve from the container, or use the facade

Note the argument order changed on push(): the account reference now comes before the description, since the description is optional and defaults to it.

Keys were reorganised. The file is still config/laravel-daraja.php.

4.x 5.0
stk_push.short_code stk.short_code
stk_push.pass_key stk.pass_key
stk_push.callback_url stk.callback_url
c2b_url.confirmation urls.c2b.confirmation
c2b_url.validation urls.c2b.validation
result_url.b2c urls.result.b2c
queue_timeout_url.b2c urls.timeout.b2c
logs.enabled logging.enabled
logs.level logging.channel
mode (hardcoded) mode via DARAJA_MODE

Republish the config, or copy the new file and re-enter your values:

Terminal window
php artisan vendor:publish --tag=laravel-daraja-config --force

4.x returned stdClass from json_decode(). v5 returns readonly objects:

$response = MpesaApi::STK()->push(…);
$id = $response->CheckoutRequestID;
$response = Daraja::stk()->push(…);
$id = $response->checkoutRequestId;
$response->accepted();

The decoded array is still available on $response->raw if you need a field the DTO does not expose.

use Starnerz\LaravelDaraja\Exceptions\MpesaApiRequestException;
use Starnerz\LaravelDaraja\Exceptions\ApiRequestException;

ApiRequestException now carries errorCode, requestId, status and payload. Configuration problems raise ConfigurationException and token failures AuthenticationException, both extending DarajaException.

Several endpoints moved, which changes payloads Safaricom sends you:

API 4.x 5.0
C2B mpesa/c2b/v1/* mpesa/c2b/v2/*
B2C mpesa/b2c/v1/paymentrequest mpesa/b2c/v3/paymentrequest

C2B v2 masks the MSISDN (2547 ***** 126) where the older endpoint sent a SHA-256 hash. Any code matching customers on that value needs revisiting.

B2C v3 requires OriginatorConversationID. The package generates one; pass your own to make retries idempotent.

4.x bundled only the production certificate and used it for sandbox too. v5 ships both and picks the right one from mode, so no action is needed. To use your own copy, set DARAJA_CERTIFICATE_PATH.

  • Cached OAuth tokens instead of a request per instantiation
  • Dynamic QR, M-Pesa Ratiba, Bill Manager, Pull Transactions, Lipa na Bonga, B2B Express Checkout, B2C Account Top Up, Business to Pochi
  • Opt-in callback routes with typed events
  • Http::fake()-driven testing
  • TLS verification in sandbox, which 4.x disabled