amos-o-7 / laravel-mpesa
A Laravel package for M-Pesa C2B (Customer to Business) integration
Requires
- php: ^8.1|^8.2
- guzzlehttp/guzzle: ^7.9
- illuminate/http: ^10.0|^11.0
- illuminate/support: ^10.0|^11.0
- psr/log: ^3.0
Requires (Dev)
- guzzlehttp/psr7: ^2.6
- mockery/mockery: ^1.6
- orchestra/testbench: ^8.0|^9.0
- phpunit/phpunit: ^10.5
This package is auto-updated.
Last update: 2025-05-14 18:40:45 UTC
README
A Laravel package for M-Pesa integration supporting both C2B (Customer to Business) and STK Push operations.
Installation
You can install the package via composer:
composer require amos-o-7/laravel-mpesa
Configuration
- Publish the configuration file:
php artisan vendor:publish --provider="Mpesa\Providers\MpesaServiceProvider" --tag="config"
- Add these variables to your
.env
file:
MPESA_BASE_URL=https://sandbox.safaricom.co.ke MPESA_CONSUMER_KEY=your_consumer_key MPESA_CONSUMER_SECRET=your_consumer_secret MPESA_SHORTCODE=your_shortcode MPESA_PASSKEY=your_passkey MPESA_CALLBACK_URL=https://your-domain.com/api/mpesa/callback MPESA_VALIDATION_URL=https://your-domain.com/api/mpesa/validate MPESA_CONFIRMATION_URL=https://your-domain.com/api/mpesa/confirm
Usage
Basic Usage
use Mpesa\Services\C2BService; class PaymentController extends Controller { protected $mpesa; public function __construct(C2BService $mpesa) { $this->mpesa = $mpesa; } // Register URLs (only needs to be done once) public function registerUrls() { try { $response = $this->mpesa->registerUrls(); return response()->json($response); } catch (MpesaException $e) { return response()->json(['error' => $e->getMessage()], 500); } } // Simulate a C2B payment (sandbox only) public function simulatePayment() { try { $response = $this->mpesa->simulateTransaction([ 'Amount' => 100, 'BillRefNumber' => 'INV001', 'PhoneNumber' => '254727343690' ]); return response()->json($response); } catch (MpesaException $e) { return response()->json(['error' => $e->getMessage()], 500); } } }
Handling Callbacks
// Validation callback public function validation(Request $request) { Log::info('M-Pesa Validation', $request->all()); return response()->json([ 'ResultCode' => 0, 'ResultDesc' => 'Accepted' ]); } // Confirmation callback public function confirmation(Request $request) { Log::info('M-Pesa Confirmation', $request->all()); return response()->json([ 'ResultCode' => 0, 'ResultDesc' => 'Success' ]); }
STK Push (M-Pesa Express)
The STK Push feature allows you to initiate M-Pesa payments by sending a payment prompt to the customer's phone.
1. Basic Usage
use Mpesa\Services\STKPushService; class PaymentController extends Controller { protected $stkPush; public function __construct(STKPushService $stkPush) { $this->stkPush = $stkPush; } public function initiatePayment() { try { $response = $this->stkPush->initiateSTKPush( amount: 100, // Amount in KES phoneNumber: '254712345678', accountReference: 'INV001', transactionDesc: 'Payment for Invoice 001' ); return response()->json($response); } catch (\Exception $e) { return response()->json(['error' => $e->getMessage()], 500); } } }
2. Using the Built-in Controller
The package comes with a pre-built controller. Just make a POST request to /api/mpesa/stk/push
with the following parameters:
{ "amount": 100, "phone": "254712345678", "account_reference": "INV001", "transaction_desc": "Payment for Invoice 001", "callback_url": "https://your-domain.com/custom-callback" // Optional }
3. Handling Callbacks
Create a callback handler to process M-Pesa payment notifications:
use Illuminate\Support\Facades\Log; public function handleCallback(Request $request) { $callbackData = $request->input('Body.stkCallback'); if ($callbackData['ResultCode'] == 0) { // Payment successful $amount = $callbackData['CallbackMetadata']['Item'][0]['Value']; $mpesaReceiptNumber = $callbackData['CallbackMetadata']['Item'][1]['Value']; $transactionDate = $callbackData['CallbackMetadata']['Item'][2]['Value']; $phoneNumber = $callbackData['CallbackMetadata']['Item'][3]['Value']; // Process the payment... } else { // Payment failed $resultDesc = $callbackData['ResultDesc']; // Handle the failure... } }
Response Format
Successful Initiation
{ "MerchantRequestID": "29115-34620561-1", "CheckoutRequestID": "ws_CO_191220191020363925", "ResponseCode": "0", "ResponseDescription": "Success. Request accepted for processing", "CustomerMessage": "Success. Request accepted for processing" }
Successful Payment Callback
{ "Body": { "stkCallback": { "MerchantRequestID": "29115-34620561-1", "CheckoutRequestID": "ws_CO_191220191020363925", "ResultCode": 0, "ResultDesc": "The service request is processed successfully.", "CallbackMetadata": { "Item": [ { "Name": "Amount", "Value": 100.00 }, { "Name": "MpesaReceiptNumber", "Value": "NLJ7RT61SV" }, { "Name": "TransactionDate", "Value": 20191219102115 }, { "Name": "PhoneNumber", "Value": 254712345678 } ] } } } }
Error Handling
The package throws MpesaException
for M-Pesa API-related errors. Common error scenarios:
- Invalid phone number format
- Insufficient balance
- Invalid credentials
- Network errors
Always wrap your API calls in try-catch blocks to handle these errors gracefully.
Testing
composer test
Security
If you discover any security-related issues, please email amosondari7@gmail.com instead of using the issue tracker.
Features
- Token Generation
- URL Registration
- C2B Payment Simulation (Sandbox)
- STK Push (M-Pesa Express)
- Validation & Confirmation Handling
- Error Handling
- Automatic Token Management
Credits
License
The MIT License (MIT). Please see License File for more information.