Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message
nyumbani-daraja-payments
nyumbani-daraja-payments
nyumbani/daraja
claude-code
laravel
mpesa
safaricom
daraja

Invoke when a Nyumbani app needs M-Pesa through Safaricom Daraja: STK push, C2B URL registration, Pull transaction registration or queries, building a ShortCode, switching sandbox and production, or handling a failed Daraja response. Skip for receiving callbacks (see nyumbani-daraja-webhooks).

Install
php artisan boost:add-skill nyumbani/daraja

Save this content to: .claude/skills/nyumbani-daraja-payments/SKILL.md

# Nyumbani Daraja Payments

Use `nyumbani/daraja` for every M-Pesa call. Never write another Daraja HTTP client, and never copy a gateway class from another app.

## Setup
- `DARAJA_ENVIRONMENT=sandbox|production` in `.env`. It defaults to `production`, so set sandbox explicitly while developing.
- For one client only, call `->sandbox()` or `->live()` on it.
- Credentials never go in code, config defaults or `.env.example`. Keep them in the gitignored `.env`, or in a database row for apps that serve several paybills, and never log them.

## Build a ShortCode
```php
use Nyumbani\Daraja\ShortCode;

$shortCode = new ShortCode(
    value: '174379',
    consumerKey: $key,
    consumerSecret: $secret,
    passKey: $passKey,
    tillNumber: null, // set for Buy Goods
);
```
Build it wherever the credentials live. The package does not read them itself.

## Calls
```php
use Nyumbani\Daraja\Daraja;

$daraja = Daraja::for($shortCode);

$daraja->stkPush($phone, $amount, 'INV-1', 'Order payment', $callbackUrl);
$daraja->registerC2BUrls($validationUrl, $confirmationUrl);
$daraja->registerPullUrl($nominatedNumber, $callbackUrl);
$daraja->pullTransactions($from, $to, $offset);
```
- `stkPush` needs the short code's pass key (otherwise a `LogicException`) and a public `$callbackUrl`. Phones are normalised with `daraja_phone()`; use it yourself for any stored number.
- `accessToken()` throws `DarajaException` when Daraja cannot be reached or refuses the credentials. Catch it where the user triggers the call and flash an error toast with `back()->alert('error', ...)`.
- Pull queries default to the last 48 hours; the times are converted to East Africa Time. `amount` is rounded to whole shillings.
- The access token is cached for 55 minutes per environment and short code in the default cache store, and a failed token request is never cached.
- A `ShortCode` with a `tillNumber` makes an STK push a Buy Goods payment to the till; without one it is a PayBill payment.

## Reading responses
Each call returns Laravel's HTTP `Response`. Daraja can answer HTTP 200 with a failure, so check both `successful()` and the code in the body: `ResponseCode` is `0` for an STK push and `1000` for the Pull calls.
```php
if ($response->failed() || ! in_array($response->json('ResponseCode'), ['0', '1000'], true)) { ... }
```

## Testing
Use `Http::fake()` for `sandbox.safaricom.co.ke` and `api.safaricom.co.ke`, faking the token request (`*/oauth/v1/generate*`) as well as the call. Never hit Daraja from the test suite.
```php
use Illuminate\Support\Facades\Http;

Http::fake([
    '*/oauth/v1/generate*' => Http::response(['access_token' => 'token']),
    '*/mpesa/stkpush/v1/processrequest' => Http::response(['ResponseCode' => '0', 'CheckoutRequestID' => 'ws_CO_1']),
]);
```
Save the `CheckoutRequestID` of an accepted push with a pending payment: the STK callback carries the same id.

## Rules
- Business logic (which order a payment belongs to) lives in the app's own service or action, not in the controller that calls Daraja.
- Validate input with a Form Request, and flash results as toasts.

Nyumbani Daraja Payments

Use nyumbani/daraja for every M-Pesa call. Never write another Daraja HTTP client, and never copy a gateway class from another app.

Setup

  • DARAJA_ENVIRONMENT=sandbox|production in .env. It defaults to production, so set sandbox explicitly while developing.
  • For one client only, call ->sandbox() or ->live() on it.
  • Credentials never go in code, config defaults or .env.example. Keep them in the gitignored .env, or in a database row for apps that serve several paybills, and never log them.

Build a ShortCode

use Nyumbani\Daraja\ShortCode;

$shortCode = new ShortCode(
    value: '174379',
    consumerKey: $key,
    consumerSecret: $secret,
    passKey: $passKey,
    tillNumber: null, // set for Buy Goods
);

Build it wherever the credentials live. The package does not read them itself.

Calls

use Nyumbani\Daraja\Daraja;

$daraja = Daraja::for($shortCode);

$daraja->stkPush($phone, $amount, 'INV-1', 'Order payment', $callbackUrl);
$daraja->registerC2BUrls($validationUrl, $confirmationUrl);
$daraja->registerPullUrl($nominatedNumber, $callbackUrl);
$daraja->pullTransactions($from, $to, $offset);
  • stkPush needs the short code's pass key (otherwise a LogicException) and a public $callbackUrl. Phones are normalised with daraja_phone(); use it yourself for any stored number.
  • accessToken() throws DarajaException when Daraja cannot be reached or refuses the credentials. Catch it where the user triggers the call and flash an error toast with back()->alert('error', ...).
  • Pull queries default to the last 48 hours; the times are converted to East Africa Time. amount is rounded to whole shillings.
  • The access token is cached for 55 minutes per environment and short code in the default cache store, and a failed token request is never cached.
  • A ShortCode with a tillNumber makes an STK push a Buy Goods payment to the till; without one it is a PayBill payment.

Reading responses

Each call returns Laravel's HTTP Response. Daraja can answer HTTP 200 with a failure, so check both successful() and the code in the body: ResponseCode is 0 for an STK push and 1000 for the Pull calls.

if ($response->failed() || ! in_array($response->json('ResponseCode'), ['0', '1000'], true)) { ... }

Testing

Use Http::fake() for sandbox.safaricom.co.ke and api.safaricom.co.ke, faking the token request (*/oauth/v1/generate*) as well as the call. Never hit Daraja from the test suite.

use Illuminate\Support\Facades\Http;

Http::fake([
    '*/oauth/v1/generate*' => Http::response(['access_token' => 'token']),
    '*/mpesa/stkpush/v1/processrequest' => Http::response(['ResponseCode' => '0', 'CheckoutRequestID' => 'ws_CO_1']),
]);

Save the CheckoutRequestID of an accepted push with a pending payment: the STK callback carries the same id.

Rules

  • Business logic (which order a payment belongs to) lives in the app's own service or action, not in the controller that calls Daraja.
  • Validate input with a Form Request, and flash results as toasts.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle