M-Pesa webhook handler for Laravel
# laravel-mpesa-webhooks
Advanced M-Pesa webhook handling for Laravel. Signature verification, IP allowlisting, idempotency, automatic retry, structured logging, and a built-in dashboard — all in one package.
Requires `felixmuhoro/laravel-mpesa` for the underlying Daraja API client.
## Requirements
| Requirement | Version |
|---|---|
| PHP | 8.1+ |
| Laravel | 10 / 11 / 12 / 13 |
| felixmuhoro/laravel-mpesa | ^1.2 |
## Installation
```bash
composer require felixmuhoro/laravel-mpesa-webhooks
```
Publish the config and run the migration:
```bash
php artisan vendor:publish --tag=mpesa-webhooks-config
php artisan vendor:publish --tag=mpesa-webhooks-migrations
php artisan migrate
```
## Configuration
```dotenv
# Disable during sandbox development, enable in production
MPESA_WEBHOOK_VERIFY_IP=true
# Comma-separated list overrides the default Safaricom production IPs
MPESA_WEBHOOK_IP_ALLOWLIST=196.201.214.200,196.201.214.206
# Only needed if you are proxying and signing callbacks yourself
MPESA_WEBHOOK_VERIFY_SIGNATURE=false
MPESA_WEBHOOK_SECRET=your-shared-secret
# Retry configuration
MPESA_WEBHOOK_MAX_ATTEMPTS=3
MPESA_WEBHOOK_BACKOFF_BASE=60
# Auto-prune processed logs older than N days (null = never)
MPESA_WEBHOOK_PRUNE_DAYS=90
```
## Callback URLs
Register these URLs in your Daraja portal:
| Type | URL |
|---|---|
| STK Push Result URL | `
your-domain.com` |
| C2B Confirmation URL | `
your-domain.com` |
| B2C Result URL | `
your-domain.com` |
## Listening to Events
### STK Push
```php
use FelixMuhoro\MpesaWebhooks\Events\StkCallbackReceived;
class HandleStkCallback
{
public function handle(StkCallbackReceived $event): void
{
if (! $event->wasSuccessful()) {
$resultCode = $event->stkCallback['ResultCode'];
$resultDesc = $event->stkCallback['ResultDesc'];
return;
}
$amount = $event->amount();
$receipt = $event->receiptNumber();
$phone = $event->phoneNumber();
$ch …