mmchrist89/laravel-mobile-money

Package Laravel pour l'intégration de MTN Mobile Money et Airtel Money

Maintainers

Package info

github.com/mmchrist89/laravel-mobile-money

pkg:composer/mmchrist89/laravel-mobile-money

Statistics

Installs: 0

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

dev-main 2026-02-12 03:13 UTC

This package is auto-updated.

Last update: 2026-03-12 03:35:19 UTC


README

Package Laravel complet pour l'intégration de MTN Mobile Money et Airtel Money. Solution flexible et prête pour la production.

🚀 Fonctionnalités

  • ✅ Support de MTN Mobile Money et Airtel Money
  • ✅ Demandes de paiement (Collection)
  • ✅ Transferts d'argent (Disbursement)
  • ✅ Vérification du statut des transactions
  • ✅ Consultation du solde
  • ✅ Détection automatique du provider
  • ✅ Gestion des webhooks/callbacks
  • ✅ Enregistrement des transactions en base de données
  • ✅ Logging complet
  • ✅ Configuration flexible
  • ✅ Gestion des erreurs robuste

📦 Installation

Étape 1 : Installation via Composer

composer require mmchrist89/laravel-mobile-money

Étape 2 : Publier la configuration

php artisan vendor:publish --tag=mobile-money-config

Étape 3 : Publier les migrations

php artisan vendor:publish --tag=mobile-money-migrations

Étape 4 : Exécuter les migrations

php artisan migrate

⚙️ Configuration

Ajoutez vos identifiants dans le fichier .env :

MTN Mobile Money

MTN_ENABLED=true
MTN_ENVIRONMENT=sandbox
MTN_CURRENCY=XAF
MTN_COUNTRY=CM
MTN_API_USER=your-api-user
MTN_API_KEY=your-api-key
MTN_SUBSCRIPTION_KEY=your-subscription-key
MTN_COLLECTION_SUBSCRIPTION_KEY=your-collection-key
MTN_DISBURSEMENT_SUBSCRIPTION_KEY=your-disbursement-key
MTN_BASE_URL=https://sandbox.momodeveloper.mtn.com
MTN_CALLBACK_URL=https://votre-domaine.com/mobile-money/webhooks/mtn

Airtel Money

AIRTEL_ENABLED=true
AIRTEL_ENVIRONMENT=staging
AIRTEL_CURRENCY=XAF
AIRTEL_COUNTRY=CM
AIRTEL_CLIENT_ID=your-client-id
AIRTEL_CLIENT_SECRET=your-client-secret
AIRTEL_PIN=your-pin
AIRTEL_BASE_URL=https://openapiuat.airtel.africa
AIRTEL_CALLBACK_URL=https://votre-domaine.com/mobile-money/webhooks/airtel

Configuration générale

MOBILE_MONEY_DEFAULT_PROVIDER=mtn
MOBILE_MONEY_LOGGING=true
MOBILE_MONEY_LOG_CHANNEL=stack

📖 Utilisation

Utilisation de base

use MobileMoney\Facades\MobileMoney;

// Demander un paiement
$transaction = MobileMoney::requestPayment(
    phone: '237650123456',
    amount: 5000,
    options: [
        'provider' => 'mtn', // optionnel
        'reference' => 'CMD-12345', // optionnel, généré automatiquement
        'metadata' => [
            'customer_name' => 'John Doe',
            'order_id' => 12345,
        ]
    ]
);

// Vérifier le statut
$transaction = MobileMoney::checkStatus($transaction->transaction_id);

// Effectuer un transfert
$transaction = MobileMoney::transfer(
    phone: '237690123456',
    amount: 2000,
    options: ['provider' => 'airtel']
);

// Obtenir le solde
$balance = MobileMoney::getBalance('mtn');

Détection automatique du provider

// Le package détecte automatiquement MTN ou Airtel
$transaction = MobileMoney::smartPayment(
    phone: '237650123456', // MTN sera détecté
    amount: 5000
);

Utilisation avec provider spécifique

// Utiliser directement un provider
$result = MobileMoney::provider('mtn')->requestPayment(
    phone: '237650123456',
    amount: 5000,
    reference: 'CMD-12345'
);

// Vérifier les providers disponibles
$providers = MobileMoney::availableProviders();
// ['mtn', 'airtel']

Gestion des transactions en base de données

use MobileMoney\Models\Transaction;

// Récupérer toutes les transactions
$transactions = Transaction::all();

// Filtrer par provider
$mtnTransactions = Transaction::provider('mtn')->get();

// Filtrer par statut
$successfulTransactions = Transaction::successful()->get();
$pendingTransactions = Transaction::pending()->get();
$failedTransactions = Transaction::failed()->get();

// Vérifier le statut
if ($transaction->isSuccessful()) {
    // Transaction réussie
}

if ($transaction->isPending()) {
    // Transaction en attente
}

if ($transaction->isFailed()) {
    // Transaction échouée
}

// Marquer manuellement une transaction
$transaction->markAsSuccessful();
$transaction->markAsFailed('Solde insuffisant');

Gestion des erreurs

use MobileMoney\Exceptions\MobileMoneyException;

try {
    $transaction = MobileMoney::requestPayment('237650123456', 5000);
} catch (MobileMoneyException $e) {
    // Gérer l'erreur
    Log::error('Erreur Mobile Money: ' . $e->getMessage());

    // Obtenir le contexte
    $context = $e->getContext();
}

🔔 Webhooks/Callbacks

Le package enregistre automatiquement les routes de webhook :

  • MTN : POST /mobile-money/webhooks/mtn
  • Airtel : POST /mobile-money/webhooks/airtel

Les transactions sont automatiquement mises à jour lors de la réception des callbacks.

Personnaliser le traitement des callbacks

Vous pouvez écouter les événements de transaction (à implémenter selon vos besoins) :

// Dans EventServiceProvider
protected $listen = [
    'MobileMoney\Events\TransactionUpdated' => [
        'App\Listeners\SendTransactionNotification',
    ],
];

🧪 Tests

composer test

📝 Exemples d'utilisation

Cas d'usage 1 : Système de paiement e-commerce

class PaymentController extends Controller
{
    public function processPayment(Request $request)
    {
        $validated = $request->validate([
            'phone' => 'required|string',
            'amount' => 'required|numeric|min:100',
            'order_id' => 'required|integer',
        ]);

        try {
            $transaction = MobileMoney::smartPayment(
                phone: $validated['phone'],
                amount: $validated['amount'],
                options: [
                    'reference' => 'ORDER-' . $validated['order_id'],
                    'metadata' => [
                        'order_id' => $validated['order_id'],
                        'customer_id' => auth()->id(),
                    ],
                ]
            );

            return response()->json([
                'success' => true,
                'transaction_id' => $transaction->transaction_id,
                'message' => 'Veuillez confirmer le paiement sur votre téléphone',
            ]);
        } catch (MobileMoneyException $e) {
            return response()->json([
                'success' => false,
                'message' => $e->getMessage(),
            ], 400);
        }
    }

    public function checkPaymentStatus($transactionId)
    {
        $transaction = MobileMoney::checkStatus($transactionId);

        return response()->json([
            'status' => $transaction->status,
            'amount' => $transaction->amount,
        ]);
    }
}

Cas d'usage 2 : Système de retrait

class WithdrawalController extends Controller
{
    public function withdraw(Request $request)
    {
        $validated = $request->validate([
            'phone' => 'required|string',
            'amount' => 'required|numeric|min:500',
        ]);

        // Vérifier le solde utilisateur
        if (auth()->user()->balance < $validated['amount']) {
            return response()->json([
                'success' => false,
                'message' => 'Solde insuffisant',
            ], 400);
        }

        try {
            $transaction = MobileMoney::transfer(
                phone: $validated['phone'],
                amount: $validated['amount'],
                options: [
                    'provider' => MobileMoney::detectProvider($validated['phone']),
                    'metadata' => [
                        'user_id' => auth()->id(),
                        'type' => 'withdrawal',
                    ],
                ]
            );

            // Déduire du solde utilisateur
            auth()->user()->decrement('balance', $validated['amount']);

            return response()->json([
                'success' => true,
                'transaction_id' => $transaction->transaction_id,
                'message' => 'Retrait initié avec succès',
            ]);
        } catch (MobileMoneyException $e) {
            return response()->json([
                'success' => false,
                'message' => $e->getMessage(),
            ], 400);
        }
    }
}

Cas d'usage 3 : Commande artisan pour vérifier les transactions en attente

namespace App\Console\Commands;

use Illuminate\Console\Command;
use MobileMoney\Facades\MobileMoney;
use MobileMoney\Models\Transaction;

class CheckPendingTransactions extends Command
{
    protected $signature = 'mobile-money:check-pending';
    protected $description = 'Vérifier le statut des transactions en attente';

    public function handle()
    {
        $pendingTransactions = Transaction::pending()
            ->where('created_at', '>', now()->subHours(24))
            ->get();

        $this->info("Vérification de {$pendingTransactions->count()} transactions...");

        foreach ($pendingTransactions as $transaction) {
            try {
                $updated = MobileMoney::checkStatus(
                    $transaction->transaction_id,
                    $transaction->provider
                );

                $this->info("Transaction {$transaction->transaction_id}: {$updated->status}");
            } catch (\Exception $e) {
                $this->error("Erreur pour {$transaction->transaction_id}: {$e->getMessage()}");
            }
        }

        $this->info('Terminé !');
    }
}

🛠️ Configuration avancée

Personnaliser la table des transactions

Dans config/mobile-money.php :

'database' => [
    'transactions_table' => 'custom_transactions_table',
    'connection' => 'custom_connection',
],

Désactiver un provider

MTN_ENABLED=false

Configuration multi-pays

Le package supporte plusieurs pays. Modifiez simplement :

MTN_COUNTRY=UG  # Ouganda
AIRTEL_COUNTRY=GH  # Ghana

📚 API Reference

MobileMoneyManager

requestPayment(string $phone, float $amount, array $options = []): Transaction

Demander un paiement au client.

transfer(string $phone, float $amount, array $options = []): Transaction

Effectuer un transfert vers un numéro.

checkStatus(string $transactionId, ?string $provider = null): Transaction

Vérifier le statut d'une transaction.

getBalance(?string $provider = null): array

Obtenir le solde du compte.

detectProvider(string $phone): ?string

Détecter le provider à partir du numéro.

smartPayment(string $phone, float $amount, array $options = []): Transaction

Paiement avec détection automatique du provider.

availableProviders(): array

Obtenir la liste des providers disponibles.

🔒 Sécurité

  • Les données sensibles sont automatiquement masquées dans les logs
  • Support HTTPS pour la production
  • Validation des numéros de téléphone
  • Gestion sécurisée des tokens d'accès

🤝 Contribution

Les contributions sont les bienvenues ! N'hésitez pas à ouvrir une issue ou une pull request.

📄 Licence

Ce package est open-source sous licence MIT.

👨‍💻 Auteur

Créé avec ❤️ pour la communauté Laravel

🔗 Liens utiles