elbrahms / ipaymoney
Un package Laravel complet pour intégrer la passerelle de paiement iPay Money (Mobile Money & Carte) en Afrique de l'Ouest.
Requires
- php: ^8.1
- guzzlehttp/guzzle: ^7.5
- illuminate/console: ^10.0 || ^11.0 || ^12.0
- illuminate/contracts: ^10.0 || ^11.0 || ^12.0
- illuminate/database: ^10.0 || ^11.0 || ^12.0
- illuminate/http: ^10.0 || ^11.0 || ^12.0
- illuminate/support: ^10.0 || ^11.0 || ^12.0
Requires (Dev)
- mockery/mockery: ^1.5
- orchestra/testbench: ^8.0 || ^9.0 || ^10.0
- phpunit/phpunit: ^10.0 || ^11.0
This package is auto-updated.
Last update: 2026-07-31 20:10:08 UTC
README
Un package Laravel complet pour intégrer la passerelle de paiement iPay Money (Mobile Money & Carte bancaire) en Afrique de l'Ouest - Niger, Bénin, et autres pays de la zone XOF.
- ✅ Création de paiements (Mobile Money & Carte)
- ✅ Consultation du statut d'une transaction
- ✅ Réception & vérification des webhooks (signature
secret-hash) - ✅ Événements Laravel (
PaymentSucceeded,PaymentFailed,WebhookReceived) - ✅ Persistance des transactions (modèle + migration, mise à jour auto par webhook)
- ✅ Commande Artisan de test d'intégration (
php artisan ipaymoney:test) - ✅ Bouton de checkout front-end (SDK JavaScript)
- ✅ Environnements sandbox et live
- ✅ Façade, auto-discovery, config publiable, tests inclus
Installation
composer require elbrahms/ipaymoney
Le package utilise l'auto-discovery Laravel. Publiez ensuite la configuration :
php artisan vendor:publish --tag=ipaymoney-config
Pour activer la persistance des transactions (optionnelle), publiez et exécutez la migration :
php artisan vendor:publish --tag=ipaymoney-migrations php artisan migrate
Variables d'environnement
Ajoutez à votre fichier .env :
IPAYMONEY_ENVIRONMENT=sandbox # sandbox | live IPAYMONEY_SECRET_KEY=sk_xxxxxxxxxxxxx # clé secrète (côté serveur) IPAYMONEY_PUBLIC_KEY=pk_xxxxxxxxxxxxx # clé publique (front / checkout) IPAYMONEY_COUNTRY=NE # NE (Niger), BJ (Bénin), ... IPAYMONEY_CURRENCY=XOF IPAYMONEY_PAYMENT_TYPE=mobile # mobile | card # Webhook IPAYMONEY_WEBHOOK_ENABLED=true IPAYMONEY_WEBHOOK_PATH=ipaymoney/webhook IPAYMONEY_WEBHOOK_SECRET=sk_xxxxxxxxxxxxx # le "Secret Hash" du dashboard # Persistance des transactions (optionnelle) IPAYMONEY_RECORD_TRANSACTIONS=true IPAYMONEY_TABLE=ipaymoney_transactions
⚠️ Ne partagez jamais votre clé secrète et ne la committez pas.
Vos clés sont disponibles dans votre dashboard iPay Money : Développeurs → Clés API.
Utilisation
1. Créer un paiement Mobile Money, MyNIta ou Amanata
use IPayMoney\Laravel\Facades\IPayMoney; use IPayMoney\Laravel\Data\PaymentRequest; $payment = IPayMoney::requestPayment( PaymentRequest::make() ->amount(1000) // montant > 100 ->msisdn('40410000000') // numéro du client ->transactionId('CMD-'.$order->id) // référence unique de VOTRE côté ->customerName('Amadou Diallo') ->country('NE') // optionnel (défaut: config) ->mobile() // ->card() pour une carte //->MyNIta() //->Amanata() ); if ($payment->isSuccessful()) { // Conservez la référence iPay Money pour le suivi $order->update(['ipay_reference' => $payment->reference]); }
Vous pouvez aussi passer un simple tableau :
$payment = IPayMoney::requestPayment([ 'amount' => 1000, 'msisdn' => '40410000000', 'transaction_id' => 'CMD-42', 'customer_name' => 'Amadou Diallo', 'payment_type' => 'mobile', ]);
Réponse (PaymentResponse) :
| Propriété | Description |
|---|---|
status |
Enum PaymentStatus (succeeded/failed/pending) |
reference |
La référence générée par iPay Money |
externalReference |
Votre transaction_id |
msisdn |
Le numéro du client |
isSuccessful() |
true si succeeded |
isFailed() |
true si failed |
isPending() |
true si pending |
2. Consulter le statut d'un paiement
$status = IPayMoney::getPaymentStatus('vslfxgawkpkm'); if ($status->isSuccessful()) { // ... }
3. Forcer un environnement à la volée
IPayMoney::usingEnvironment('live')->requestPayment(...);
Webhooks
iPay Money notifie votre serveur du résultat final d'une transaction. Le package enregistre automatiquement une route protégée par la vérification de signature.
- URL par défaut :
POST /ipaymoney/webhook(nomméeipaymoney.webhook) - Vérification : l'en-tête
secret-hashest comparé, en temps constant, àconfig('ipaymoney.webhook.secret_hash').
Configurez cette URL dans votre dashboard iPay Money (Développeurs → Webhooks) et renseignez votre Secret Hash.
Excluez ce chemin de la protection CSRF (
VerifyCsrfToken) - c'est déjà le cas si vous conservez le middlewareapipar défaut.
Écouter les événements
Dans un EventServiceProvider :
use IPayMoney\Laravel\Events\PaymentSucceeded; use IPayMoney\Laravel\Events\PaymentFailed; protected $listen = [ PaymentSucceeded::class => [ \App\Listeners\MarkOrderAsPaid::class, ], PaymentFailed::class => [ \App\Listeners\NotifyPaymentFailure::class, ], ];
Exemple de listener :
use IPayMoney\Laravel\Events\PaymentSucceeded; class MarkOrderAsPaid { public function handle(PaymentSucceeded $event): void { $payment = $event->payment; // PaymentResponse Order::where('reference', $payment->externalReference) ->update([ 'status' => 'paid', 'ipay_reference' => $payment->reference, ]); } }
L'événement WebhookReceived est émis pour toute notification vérifiée
(idéal pour la journalisation).
Checkout front-end (SDK JavaScript)
Pour un paiement redirigé (bouton de paiement iPay Money) dans une vue Blade :
{!! IPayMoney::checkout() ->amount(1000) ->transactionId('CMD-42') ->redirectUrl(route('checkout.done')) ->callbackUrl(route('ipaymoney.webhook')) ->label('Payer 1 000 XOF') ->button() !!} {{-- Avant </body> --}} {!! IPayMoney::checkout()->script() !!}
Rendu généré :
<button type="button" class="ipaymoney-button" data-amount="1000" data-environement="sandbox" data-key="pk_xxxxxxxxxxxxx" data-transaction-id="CMD-42" data-redirect-url="https://votre-app.test/checkout/done" data-callback-url="https://votre-app.test/ipaymoney/webhook"> Payer 1 000 XOF </button> <script src="https://i-pay.money/checkout.js"></script>
Sandbox : numéros de test
En environnement sandbox, utilisez ces numéros pour simuler les scénarios :
| MSISDN | Scénario |
|---|---|
40410000000 |
Succès |
40410000001 |
Succès |
40410000002 |
Erreur |
40410000003 |
Erreur |
40410000004 |
Fonds insuffisants |
40410000005 |
Fonds insuffisants |
40410000006 |
Refusé |
40410000007 |
Refusé |
40410000008 |
En attente (180 s) |
40410000009 |
En attente (180 s) |
Persistance des transactions
Le package peut enregistrer automatiquement chaque paiement en base de
données via le modèle IPayMoneyTransaction.
Activez-la avec IPAYMONEY_RECORD_TRANSACTIONS=true (après avoir publié et
exécuté la migration). Dès lors :
IPayMoney::requestPayment(...)crée une ligne (statutpending) puis la met à jour avec la réponse de l'API.- Les webhooks retrouvent la transaction (par
referencepuistransaction_id) et synchronisent son statut ainsi quepaid_at.
use IPayMoney\Laravel\Models\IPayMoneyTransaction; // Retrouver une transaction $tx = IPayMoneyTransaction::where('transaction_id', 'CMD-42')->first(); $tx->isSuccessful(); // bool $tx->status; // Enum PaymentStatus $tx->reference; // référence iPay Money $tx->amount; // decimal $tx->paid_at; // Carbon|null $tx->meta; // dernier payload brut (array)
Table ipaymoney_transactions (colonnes principales) :
| Colonne | Description |
|---|---|
transaction_id |
Votre référence (unique) |
reference |
Référence générée par iPay Money |
status |
pending / succeeded / failed |
payment_type |
mobile / myNita / amanata / card |
environment |
sandbox / live |
amount, currency, country |
Montant et localisation |
customer_name, msisdn |
Infos client |
meta |
Dernier payload brut (JSON) |
paid_at |
Horodatage du succès |
La persistance est tolérante aux pannes : toute erreur de base de données est journalisée sans jamais faire échouer un paiement ni un webhook.
Le modèle est aussi utilisable manuellement, même sans activer l'option
record, si vous préférez gérer l'enregistrement vous-même.
Commande Artisan de test d'intégration
Validez votre configuration de bout en bout (config → paiement sandbox → statut) sans écrire une ligne de code :
php artisan ipaymoney:test
Options :
php artisan ipaymoney:test \
--msisdn=40410000004 \ # scénario "fonds insuffisants"
--amount=250 \
--type=mobile \ # mobile | myNita | amanata | card
--no-status # ne pas consulter le statut après création
La commande :
- vérifie la présence des clés (les affiche masquées) et l'environnement ;
- crée un paiement de test avec une référence unique auto-générée ;
- consulte le statut renvoyé et affiche un résumé coloré.
En mode
live, la commande demande une confirmation avant de lancer un vrai paiement.
Gestion des erreurs
use IPayMoney\Laravel\Exceptions\PaymentException; use IPayMoney\Laravel\Exceptions\ConfigurationException; try { IPayMoney::requestPayment(...); } catch (PaymentException $e) { $e->getMessage(); // message renvoyé par l'API $e->statusCode; // code HTTP $e->response(); // corps brut décodé } catch (ConfigurationException $e) { // clé secrète manquante, etc. }
Injection de dépendance
La façade est pratique, mais vous pouvez aussi résoudre le client :
use IPayMoney\Laravel\IPayMoney; public function pay(IPayMoney $ipay) { return $ipay->requestPayment(...); }
Tests
composer install
composer test
Référence API
| Opération | Méthode HTTP | Endpoint |
|---|---|---|
| Créer un paiement | POST |
/api/v1/payments |
| Statut d'un paiement | GET |
/api/v1/payments/{reference} |
En-têtes envoyés : Authorization: Bearer {clé secrète},
Ipay-Payment-Type, Ipay-Target-Environment, Content-Type: application/json.
Licence
MIT. Voir LICENSE.md.