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

Mpesa Laravel Package

safaricom/mpesa

Laravel package for Safaricom M-Pesa integration, simplifying STK Push, C2B, B2C, transaction status, and callback handling. Configure credentials, initiate payments, and reconcile responses with clean, expressive PHP APIs built for Laravel applications.

View on GitHub
Deep Wiki
Context7

Getting Started

  • Install with Composer and confirm the package’s PHP constraints before committing:
    composer require safaricom/mpesa
    
  • The new 1.0.8 release allows parsing of .env parameters. Check the README and src/ to see exactly how that works: whether the SDK loads .env itself, reads existing environment variables, accepts a path, and how it handles precedence. Prefer Laravel config in application code, but use the new feature only if it fits your setup.
  • Look first at the README, the main SDK class under src/, any examples, and composer.json. The package history is old—previous release was 2019—so verify abandoned/old dependencies and test against your PHP version before rollout.
  • Put M-Pesa settings in Laravel config/env rather than inline in controllers:
    MPESA_ENV=sandbox
    MPESA_CONSUMER_KEY=
    MPESA_CONSUMER_SECRET=
    MPESA_SHORTCODE=
    MPESA_PASSKEY=
    MPESA_CALLBACK_URL=https://example.test/api/mpesa/callback
    
  • First use case: STK Push for an order payment. Create a payment attempt record, initiate the push, store the MerchantRequestID and CheckoutRequestID, then expose a public callback route that logs and updates the attempt.
  • Minimal flow:
    use Safaricom\Mpesa\Mpesa;
    
    $mpesa = new Mpesa();
    $timestamp = date('YmdHis');
    $password = base64_encode($shortcode . $passkey . $timestamp);
    
    // Follow the SDK README for exact argument order.
    $response = $mpesa->STKPush(
        $shortcode,
        $password,
        $timestamp,
        'CustomerPayBillOnline',
        $amount,
        $phone,
        $shortcode,
        $phone,
        $callbackUrl,
        $accountReference,
        $description
    );
    

Implementation Patterns

  • Wrap the SDK in an application service such as MpesaService or MpesaGateway. Controllers and jobs should not call the SDK directly. This gives you one place to normalize arguments, log requests, handle environment switching, and later replace the SDK.
  • Treat the new .env parsing in 1.0.8 as a convenience for bootstrapping or local setup, not as your application configuration strategy. Resolve MPESA_* values through Laravel config(), pass explicit values into your gateway, and keep the SDK isolated from config-cache behavior.
  • Persist every payment attempt. Store order ID, phone, amount, MerchantRequestID, CheckoutRequestID, raw request, raw response, status, and callback payload. Day-to-day reconciliation depends on these IDs.
  • Use a dedicated callback controller. Parse the raw JSON, log it before processing, make processing idempotent by CheckoutRequestID/MerchantRequestID, queue heavier work, and return HTTP 200 quickly.
  • Build a reconciliation command/job for pending payments. Query STK Push status or transaction status for attempts that have no callback after a timeout, then update the order and notify the customer.
  • Cache the OAuth token if the SDK exposes token generation, or wrap authentication yourself if it requests a token on every call. M-Pesa tokens are short-lived; avoid unnecessary auth calls.
  • Use Laravel queues for callbacks and reconciliation, but initiate STK Push synchronously enough to return the checkout prompt to the user. Retry only transient network failures; do not blindly retry payment initiation.
  • Separate sandbox and production credentials completely. Use named config keys, not positional arrays spread through controllers.
  • In tests, fake the SDK service or HTTP client and use callback fixtures. Add coverage for .env parsing if you rely on it: missing keys, empty values, quoted values, and changes after config:cache. Use the real sandbox for a smoke test, but do not make CI depend on M-Pesa availability.
  • Integrate events such as PaymentInitiated, PaymentSucceeded, and PaymentFailed so order, invoice, and notification logic stays decoupled from M-Pesa response codes.

Gotchas and Tips

  • The package is still risky to depend on directly. 1.0.8 adds .env parsing, but the release history is sparse and the package was previously dormant. Test on PHP 8.x, check Composer conflicts, pin the version, and isolate it behind your own adapter so you can fork or replace it.
  • .env parsing is a likely source of surprises. Confirm whether the SDK reads .env directly, uses getenv(), or relies on Laravel already having loaded env values. In production, config:cache means env() outside config files can return null; do not let SDK-side env parsing bypass Laravel’s config cache.
  • If the SDK parses .env itself, verify path resolution and precedence. It should not override real production environment variables, read from an unexpected working directory, or break when .env is absent in deployments that inject env vars another way.
  • This SDK is thin and often requires positional arguments. That is easy to misuse. Create a DTO or named-argument wrapper in your service and validate amount, phone, shortcode, and callback URL before calling.
  • STK password must be base64(shortcode + passkey + timestamp), with timestamp in YmdHis format and matching the request. Do not reuse a stale timestamp/password.
  • Normalize phone numbers to the expected format, usually 2547XXXXXXXX without +, spaces, or a leading zero.
  • Amounts are generally whole integers. Avoid decimals and floating-point money types when building the request.
  • Callback URLs must be publicly reachable over HTTPS. Use ngrok or a tunnel in development, and exclude the callback route from CSRF protection in Laravel.
  • Do not trust callback data alone. Treat it as a trigger, log the raw payload, verify the CheckoutRequestID against your database, and confirm final state with a status query when needed.
  • Make callbacks idempotent. M-Pesa may retry or duplicate callbacks; a second callback must not double-credit an order.
  • Log response codes and raw bodies, but redact consumer secrets and passkeys. Useful codes include 0 success, 1032 cancelled by user, and 1037 timeout/no response; map these into your own statuses.
  • Expect timeouts and slow responses. Set sensible HTTP timeouts, avoid holding database transactions open during API calls, and reconcile pending payments instead of assuming failure.
  • If the SDK does not expose configuration for base URLs, HTTP client, token storage, or .env parsing behavior, do not edit vendor/. Wrap it, subclass it if safe, or fork it with a small patch and document the fork.
  • Keep credentials server-side only. Do not expose shortcode passkeys or consumer secrets to frontend code, and restrict who can trigger payment attempts.
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.
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums
rlacerda83/query-parser
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings