Download the PHP package maestrodimateo/simple-mobile-money without Composer

On this page you can find all versions of the php package maestrodimateo/simple-mobile-money. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.

FAQ

After the download, you have to make one include require_once('vendor/autoload.php');. After that you have to import the classes with use statements.

Example:
If you use only one package a project is not needed. But if you use more then one package, without a project it is not possible to import the classes with use statements.

In general, it is recommended to use always a project to download your libraries. In an application normally there is more than one library needed.
Some PHP packages are not free to download and because of that hosted in private repositories. In this case some credentials are needed to access such packages. Please use the auth.json textarea to insert credentials, if a package is coming from a private repository. You can look here for more information.

  • Some hosting areas are not accessible by a terminal or SSH. Then it is not possible to use Composer.
  • To use Composer is sometimes complicated. Especially for beginners.
  • Composer needs much resources. Sometimes they are not available on a simple webspace.
  • If you are using private repositories you don't need to share your credentials. You can set up everything on our site and then you provide a simple download link to your team member.
  • Simplify your Composer build process. Use our own command line tool to download the vendor folder as binary. This makes your build process faster and you don't need to expose your credentials for private repositories.
Please rate this library. Is it a good library?

Informations about the package simple-mobile-money

Simple Mobile Money

Tests Quality Latest Version on Packagist

One simple, unified Laravel API to collect and disburse mobile money payments in Gabon — through E-Billing, SingPay and PViT (Airtel Money & Moov Money).

You write the same code for every provider. The package hides each API's base URL, auth scheme, payload format and webhook shape behind neutral DTOs, a single facade, and Laravel events.

Nouveau sur le mobile money ? Lis le Guide du débutant — une explication pas à pas (en français) du fonctionnement du package et de chaque agrégateur.


Table of contents

Section Description
How it works Lifecycle of a payment — read this first
Requirements PHP & Laravel versions
Installation Composer, config, migration
Provider setup Credentials for E-Billing, SingPay, PViT
Quickstart End-to-end payment in 3 steps
Payout (cash-out) Send money to a beneficiary
API reference Facade, DTOs, enums, events, exceptions
Webhooks Route, security, local testing
Security model How webhooks are verified
Configuration Full config reference
Testing Package tests & MobileMoney::fake()
Recipes & FAQ Common patterns
Roadmap What's next




How it works

A mobile money collection is asynchronous: pay() only starts it. The real outcome (success / failure) arrives later through a webhook, which the package turns into a Laravel event.


Two flows

Flow Providers What pay() returns What you do
USSD push SingPay (default), PViT, E-Billing (ussd_push) PaymentResponse with needsRedirect() === false Tell the user to confirm the push (PIN) on their phone, then wait for the event
Hosted redirect E-Billing (default), SingPay (ext) PaymentResponse with a redirectUrl Redirect the user to that URL; they pay on the provider's page and come back


Full lifecycle

Key idea: never mark an order as paid from the pay() response. Fulfil it only when you receive the PaymentSucceeded event.




Requirements




Installation

Publish the config and run the migration:

The transactions table is registered automatically.




Provider setup

Pick your default provider, then fill in credentials for the ones you use.


E-Billing (Digitech)

Credentials come from your merchant profile (LAB or PROD).

E-Billing requires payer_email and payer_name — set payerEmail and payerName on the PaymentRequest.

E-Billing is callback-only: no status endpoint, so status() throws (supportsStatusQuery() === false).


Payout credentials (SHAP API)

Payout uses separate OAuth2 credentials:


PAYIN OAuth2 (AWS Cognito)

E-Billing is migrating PAYIN from HTTP Basic to AWS Cognito OAuth2 (production cutover 2026-08-31). The driver supports both — it stays on Basic until you flip the toggle.

OAuth2 details - Uses **client-credentials** flow (HTTP Basic `client_id:secret` + form `grant_type=client_credentials&scope=…`). - Token is cached automatically. - **Scopes:** `ebilling-api/invoice:create` (create a bill), `ebilling-api/payment:create` (USSD push). The portal shows names without the `ebilling-api/` prefix — always use the prefix in config. - **Secret rotation:** Digitech auto-rotates `client_secret` (lab every 30 days, prod every 90). Update during the grace period. - This covers **PAYIN only** — the SHAP payout API keeps its own `EBILLING_PAYOUT_API_*` credentials.


SingPay

Credentials come from SingPay Workspace (client.singpay.ga).

For the ext (hosted page) flow:


PViT (mypvit / BakoAI, API v2)

Credentials come from your PViT merchant space. Auth is the X-Secret header.


Note: Some provider details are not publicly documented (PViT's Airtel v2 operator code, E-Billing operator machine codes). They are configurable in config/mobile-money.php (providers.*.operators) — confirm them with each provider.




Quickstart

Three steps: initiate → webhook → fulfil.


Step 1 — Start the payment

$response->status is PENDING — do not treat it as paid yet.


Step 2 — Register the webhook URL

The package exposes POST /mobile-money/webhook/{provider} automatically. Register the matching public URL in each provider's dashboard:


Step 3 — Fulfil the order on success

Register it in your EventServiceProvider (or with an attribute listener). A PaymentFailed event is dispatched for failed / cancelled / expired payments.




Payout (cash-out)

Send money out to a beneficiary (refund, cashback, withdrawal).


Provider support

Provider Payout Notes
E-Billing Yes Any beneficiary via SHAP. Synchronous for Gabon operators.
PViT Yes "Rendu monnaie" via GIVE_CHANGE.
SingPay No SingPay's only cash-out is a transfer tied to a prior collection — not an arbitrary payout.


Usage


Balance & status


Payout events

PayoutInitiated → PayoutSucceeded / PayoutFailed (fired immediately since the payout is synchronous). Payouts are stored in the same table with type = payout.




API reference


Facade — MobileMoney


Gateway methods

Method Returns Description
pay(PaymentRequest) PaymentResponse Start a collection
status(string $providerRef) PaymentStatus Poll current status
supportsStatusQuery() bool Whether the provider supports status polling
verify(string $merchantRef, ?string $providerRef) PaymentStatus Re-verify bound to merchant reference
parseWebhook(Request) CallbackResult Normalise a raw webhook
name() string The provider key

status() throws if supportsStatusQuery() is false (E-Billing).


PaymentRequest

What you build and pass to pay().

Field Type Required Notes
amount int yes XAF, integer
reference string yes Your unique reference (PViT: max 15 chars)
msisdn string yes Customer number, e.g. 074000000
operator Operator yes AIRTEL or MOOV
description ?string Shown to the customer
payerName ?string Required for E-Billing
payerEmail ?string Required for E-Billing
callbackUrl ?string Per-request return URL (hosted flow)
disbursement ?string SingPay only: ID of the pre-registered disbursement recipient (falls back to config)
metadata array Echoed back; never sent to provider


PaymentResponse

Returned by pay().

Property Type Notes
status PaymentStatus Usually PENDING
reference string Your reference
providerReference ?string Provider transaction / bill id
redirectUrl ?string Set for hosted flows
raw array Raw provider response
needsRedirect() bool true when a redirect is required


PaymentStatus (enum)

PENDING · SUCCESS · FAILED · CANCELLED · EXPIRED · AMBIGUOUS · UNKNOWN


Operator (enum)

Operator::AIRTEL · Operator::MOOV


CallbackResult

Carried by webhook events.

Property Type
reference string
status PaymentStatus
providerReference ?string
amount ?int
operator ?string
raw array


Events

Event When Properties
PaymentInitiated After pay() provider, request, response, transaction
PaymentSucceeded Webhook re-verified as success provider, result, transaction
PaymentFailed Webhook re-verified as failed provider, result, transaction
PayoutInitiated After payout() provider, request, response, transaction
PayoutSucceeded Payout confirmed success provider, result, transaction
PayoutFailed Payout confirmed failure provider, result, transaction

transaction is the stored Transaction model (or null if persistence is off).


Transaction model

Stored in mobile_money_transactions.

provider · type · reference · provider_reference · status · amount · currency · msisdn · operator · description · metadata · raw


Exceptions

Exception When
InvalidConfigurationException Missing credential or unmapped operator
ProviderRequestException Provider returned an HTTP error (->provider, ->statusCode, ->context)

Both extend MobileMoneyException.




Webhooks


Endpoint POST {webhooks.path}/{provider} (default mobile-money/webhook/{provider})
Route name mobile-money.webhook
CSRF Excluded — the route is registered outside the web group
Response { "responseCode": 200, "transactionId": "..." } (shape required by PViT; others just need HTTP 200)
Disable MOBILE_MONEY_WEBHOOKS=false


Testing locally: expose your app with a tunnel (e.g. php artisan expose or ngrok) and register the public tunnel URL in the provider dashboards.




Security model

None of the three aggregators sign their webhooks. The callback body is treated as an untrusted hint. On every webhook the package:

  1. IP allowlist — optionally restricts callbacks to known IPs (webhooks.allowed_ips). Configure TrustedProxies so request()->ip() is the real client IP behind a load balancer.

  2. Reference matching — matches the callback to a stored transaction and rejects any webhook pointing to a different provider transaction than the one on record.

  3. Status re-verification — re-verifies the status against the provider API using the stored provider reference, never the one in the webhook body (webhooks.verify_status, on by default). For SingPay's ext flow, the re-verified provider transaction must also match the merchant reference.

  4. Fail-closed — returns HTTP 4xx when it cannot re-verify or the status is uncertain (UNKNOWN / AMBIGUOUS). Never moves a transaction out of a terminal state. For E-Billing (callback-only), a matching amount is mandatory.

  5. Replay-safe — dispatches terminal events only on the transition into the final state. A replayed webhook cannot re-trigger fulfilment.

  6. Rate-limited — by default (webhooks.middleware), since each call triggers a synchronous outbound verification.

Keep persistence enabled (store.enabled) in production. With storage off, the package can only do a best-effort check — your app must validate the reference ↔ provider-reference mapping itself.




Configuration

config/mobile-money.php

Key Default Description
default ebilling Provider used by MobileMoney::driver()
Storage
store.enabled true Persist transactions (also gates the auto-migration)
store.store_raw true Persist raw payloads (contain PII) — false to omit
store.table mobile_money_transactions Table name
store.model Transaction::class Custom model must extend Transaction
Webhooks
webhooks.enabled true Register the webhook route
webhooks.path mobile-money/webhook Base path (provider is appended)
webhooks.middleware ['throttle:60,1'] Middleware for the webhook route
webhooks.verify_status true Re-verify before trusting a success
webhooks.allowed_ips [] Per-provider IP allowlist ([] = no check)
Providers
providers.* — Credentials, base URLs, operator maps




Testing

Package tests


Faking in your app

MobileMoney::fake() swaps the manager for a test double — no HTTP, no raw payloads to stub.


Stub responses

Method Effect
respondToPayments(PaymentStatus) Status returned by pay() (default PENDING)
respondToPayouts(PaymentStatus) Status returned by payout() (default SUCCESS)
respondToStatus(PaymentStatus) Status returned by status() / verify()
respondToBalance(array) Value returned by balance()


Assertions

Method Asserts
assertPaid($callback \| int \| null) A payment was made
assertPayout($callback \| int \| null) A payout was made
assertNothingSent() No payment or payout was made


Testing a declined payment

The fake covers pay() / payout() only. It does not persist transactions or dispatch events (those are webhook-driven). To test that path, Http::fake() the provider and POST the webhook route.




Recipes & FAQ


Custom Transaction model Point store.model at your own model (extend the package's Transaction).


Go stateless Set store.enabled=false. Persist what you need from the events yourself. Read the security note first.


Idempotent fulfilment The same webhook can arrive more than once. Guard your listener: if ($order->isPaid()) return;


Poll status Call MobileMoney::driver('pvit')->status($providerReference) where $providerReference is from PaymentResponse->providerReference or the stored transaction. Not available for E-Billing (supportsStatusQuery() === false).


Test with HTTP fakes




Roadmap




License

MIT.


All versions of simple-mobile-money with dependencies

PHP Build Version
Package Version
Requires php Version ^8.3 || ^8.4
illuminate/support Version ^12.0|^13.0
illuminate/database Version ^12.0|^13.0
illuminate/http Version ^12.0|^13.0
Composer command for our command line client (download client) This client runs in each environment. You don't need a specific PHP version etc. The first 20 API calls are free. Standard composer command

The package maestrodimateo/simple-mobile-money contains the following files

Loading the files please wait ...