Passerelle de paiement MTN MoMo
Acceptez les paiements par mobile money des utilisateurs MTN Mobile Money (MoMo) à travers l’Afrique. S’intègre à l’API MTN MoMo Collections pour créer des transactions « Request to Pay », permettant aux clients d’approuver les paiements directement depuis leur téléphone.
Request to Pay
Initiez des demandes de paiement que les clients approuvent via une invite USSD sur leur téléphone MTN.
Provisionnement Sandbox
Génération en un clic des identifiants API sandbox directement depuis le panneau d’administration.
Vérification en temps réel
Vérification automatique du statut de paiement avec barre de progression. Support des webhooks pour les environnements de production.
Identifiants chiffrés
Tous les identifiants API sont chiffrés au repos en utilisant la façade Crypt de Laravel avant le stockage en base de données.
Cas d’utilisation
E-commerce en Afrique
Vous gérez une boutique en ligne sur Larapen ciblant les clients dans les pays desservis par MTN (Ouganda, Ghana, Cameroun, Côte d’Ivoire, Bénin, Congo, Libéria). Les clients paient leurs commandes en utilisant leur portefeuille MTN MoMo : aucune carte de crédit requise.
- Installez les add-ons Shop et MoMo.
- Configurez les identifiants MTN MoMo dans le panneau d’administration.
- Les clients sélectionnent « MTN Mobile Money » au moment du paiement, entrent leur numéro de téléphone et approuvent le paiement sur leur téléphone.
Vente de produits numériques
Vous vendez des produits numériques (e-books, logiciels, modèles) à des utilisateurs mobile-first qui préfèrent le mobile money aux paiements par carte.
- Combinez avec la livraison de produits numériques de l’add-on Shop.
- Après confirmation du paiement MoMo, le lien de téléchargement est automatiquement fourni.
Réservation de services
Toute entité payable implémentant le contrat Payable peut utiliser MoMo pour le paiement,
le rendant extensible au-delà de l’add-on Shop.
Prérequis
- Larapen CMS v1.0.0 ou ultérieur
- PHP 8.3+
- MySQL 8.0+
- L’add-on Shop (dépendance requise)
- Un compte développeur MTN MoMo sur momodeveloper.mtn.com
- Un abonnement au produit Collections sur le portail développeur MTN MoMo
Installation
Étape 1 : Placer l’add-on
Copiez ou créez un lien symbolique du dossier momo dans le répertoire « extensions/addons » de votre Larapen :
Étape 2 : Activer l’add-on
Allez dans Admin → Add-ons → Add-ons installés et activez Passerelle de paiement MTN MoMo.
Étape 3 : Exécuter les migrations
Cela crée la table momo_transactions pour le suivi des références de paiement et des statuts.
Étape 4 : Définir les permissions
L’add-on enregistre 2 permissions (voir Permissions). Assignez-les aux rôles administrateur via Admin → Utilisateurs → Rôles & Permissions.
Étape 5 : Configurer
Naviguez vers Admin → MTN MoMo → Paramètres et configurez vos identifiants API. Pour les tests sandbox, utilisez la fonctionnalité de Provisionnement pour générer automatiquement les identifiants. Voir Configuration.
Configuration
Tous les paramètres sont gérés dans Admin → MTN MoMo → Paramètres
(stockés dans la table settings, groupe momo).
Les valeurs par défaut de configuration sont définies dans config/momo.php.
| Paramètre | Description | Défaut |
|---|---|---|
momo_subscription_key |
Ocp-Apim-Subscription-Key du portail développeur MTN MoMo. Stockée chiffrée. | (vide) |
momo_api_user_id |
UUID v4 de l’utilisateur API. Généré pendant le provisionnement ou obtenu depuis le portail partenaire MTN. Stocké chiffré. | (vide) |
momo_api_key |
Clé API générée pour l’utilisateur API. Stockée chiffrée. | (vide) |
momo_environment |
Environnement de déploiement : sandbox ou production. |
sandbox |
momo_target_environment |
Valeur de l’en-tête d’environnement cible. sandbox pour les tests, ou un code spécifique au pays pour la production (voir Options de paiement). |
sandbox |
momo_currency |
Code devise pour les paiements. Doit être EUR en sandbox. Spécifique au pays en production. |
EUR |
momo_callback_host |
Votre domaine pour recevoir les callbacks webhook (production uniquement). Doit supporter HTTPS. | (vide) |
Variables d’environnement
Configuration du portail développeur MTN
- Créez un compte sur momodeveloper.mtn.com.
- Abonnez-vous au produit Collections.
- Naviguez vers votre page Profil et copiez la Clé primaire (ou Clé secondaire) : c’est votre Clé d’abonnement.
- Pour le sandbox : utilisez la fonctionnalité de Provisionnement du panneau d’administration pour générer automatiquement l’identifiant utilisateur API et la clé API.
- Pour la production : obtenez les identifiants depuis le Portail partenaire MTN MoMo et saisissez-les dans Identifiants API.
Admin : Paramètres
La page de paramètres (MTN MoMo → Paramètres) est organisée en quatre sections :
Provisionnement Sandbox
Cette section automatise le flux de génération des identifiants sandbox :
- Entrez votre Clé d’abonnement (depuis la page Profil du portail développeur MTN).
- Entrez optionnellement un Hôte de callback (par défaut
webhook.sitepour le sandbox). - Cliquez sur Générer les identifiants API.
- Le système automatiquement :
- Génère un UUID v4 pour l’identifiant utilisateur API
- Crée l’utilisateur API via
POST /v1_0/apiuser - Génère la clé API via
POST /v1_0/apiuser/{id}/apikey - Chiffre et stocke les trois identifiants dans la base de données
- Définit l’environnement à
sandboxet la devise àEUR
- Les identifiants générés sont affichés une seule fois dans une alerte de succès avec des boutons de copie. Sauvegardez-les en externe : la clé API ne peut pas être récupérée à nouveau depuis MTN.
Tester la clé
Le bouton Tester la clé effectue un appel API de diagnostic (crée un utilisateur API temporaire) pour vérifier que la clé d’abonnement est valide. Renvoie HTTP 201 en cas de succès, avec les détails de requête/réponse pour le débogage.
Identifiants API
Trois champs de type mot de passe avec des boutons de basculement de visibilité :
- Clé d’abonnement : Ocp-Apim-Subscription-Key depuis le portail MTN.
- Identifiant utilisateur API : UUID v4 créé lors du provisionnement de l’utilisateur API.
- Clé API : Générée à partir de l’utilisateur API.
Crypt::encryptString() de Laravel
avant d’être stockés en base de données. Ils ne sont déchiffrés que lorsqu’ils sont nécessaires pour les appels API.
Laissez un champ vide pour conserver la valeur actuellement stockée.
Options de paiement
- Environnement :
sandboxouproduction. Détermine quelle URL de base de l’API MTN est utilisée. - Environnement cible : Envoyé comme en-tête
X-Target-Environment. Utilisezsandboxpour les tests, ou l’une des valeurs spécifiques au pays pour la production :
| Pays | Valeur d’environnement cible | Devise |
|---|---|---|
| Ouganda | mtnuganda |
UGX |
| Ghana | mtnghana |
GHS |
| Cameroun | mtncameroon |
XAF |
| Côte d’Ivoire | mtnivorycoast |
XOF |
| Bénin | mtnbenin |
XOF |
| Congo | mtncongo |
XAF |
| Libéria | mtnliberia |
LRD |
| Sandbox | sandbox |
EUR |
- Devise : Doit correspondre à l’environnement cible (voir le tableau ci-dessus). Doit être
EURen sandbox. - Hôte de callback : Votre domaine pour recevoir les callbacks webhook (production uniquement). HTTPS est requis.
Informations d’intégration
Le bas de la page de paramètres affiche :
- L’URL de callback (
https://votre-domaine.com/momo/callback) à copier dans le portail MTN. - Une liste de référence de toutes les valeurs d’environnement cible valides par pays.
Flux de paiement
Le parcours de paiement complet du passage en caisse à la confirmation :
1. Sélection au passage en caisse
Le client sélectionne « MTN Mobile Money » comme méthode de paiement sur la page de paiement.
Un champ de saisie du numéro de téléphone est affiché (la vue Blade momo::payment-form).
2. Saisie du numéro de téléphone
Le client entre son numéro de téléphone MTN MoMo (ex. +233XXXXXXXXX).
Le numéro est normalisé (espaces, tirets et parenthèses supprimés) avant la soumission.
3. Création de la commande
Le formulaire est soumis via AJAX. L’add-on Shop crée l’enregistrement de commande,
puis appelle MomoGateway::createPaymentIntent().
4. Request to Pay
La passerelle :
- Obtient un jeton Bearer OAuth2 depuis MTN (
POST /collection/token/). - Génère un identifiant de référence UUID pour la transaction.
- Envoie un « Request to Pay » à MTN (
POST /collection/v1_0/requesttopay). - Stocke un enregistrement
MomoTransactionavec le statutPENDING. - Retourne l’identifiant de référence au frontend.
5. Approbation USSD
Le client reçoit une invite USSD sur son téléphone MTN et entre son code PIN pour approuver le paiement.
6. Vérification côté frontend
Pendant que le client approuve, le JavaScript frontend interroge GET /momo/status/{referenceId}
toutes les 5 secondes (configurable), affichant une barre de progression. Voir Mécanisme de vérification.
7. Confirmation
Lorsque la vérification renvoie succeeded, le frontend redirige vers GET /momo/confirm?reference_id={id}.
La méthode MomoController::confirm() vérifie le statut final, marque la commande comme payée et redirige vers la page de succès de la commande.
Webhooks
En production, MTN MoMo envoie des callbacks à votre serveur lorsque le statut d’un paiement change.
L’URL de callback est https://votre-domaine.com/momo/callback.
/momo/callback
Description
Reçoit les callbacks de statut de paiement MTN MoMo. La protection CSRF est désactivée pour ce point de terminaison. Accepte également les requêtes POST pour plus de flexibilité.
Traitement
Le WebhookController délègue à MomoGateway::handleWebhook(), qui :
- Extrait le
reference_idde l’en-têteX-Reference-Idou des données. - Trouve l’enregistrement
MomoTransactioncorrespondant. - Met à jour le statut de la transaction et l’identifiant de transaction financière.
- Si
SUCCESSFUL: marque la commande comme payée et crée un enregistrementTransactiondu Shop. - Si
FAILED: marque le paiement comme échoué et crée un enregistrementTransactionen échec.
Réponse (JSON)
Remboursements
refund() renvoie un échec avec un message explicatif.
Les remboursements doivent être traités manuellement via le Portail partenaire MTN MoMo
ou via l’API Disbursements séparée.
Intégration avec l’add-on Shop
L’add-on MoMo s’intègre avec l’add-on Shop à travers le contrat PaymentGatewayInterface :
Découverte de la passerelle
La classe MomoGateway est taguée comme payment.gateways dans le conteneur de services.
L’add-on Shop la découvre automatiquement aux côtés des autres passerelles de paiement (ex. Stripe).
Interface Payable
Le modèle Order du Shop implémente App\Contracts\Payable, qui fournit :
getPayableAmount(): le total de la commandegetPayableIdentifier(): le numéro de commandegetPaymentSuccessUrl(): URL de redirection après paiement réussigetPaymentCancelUrl(): URL de redirection après paiement échoué/annulémarkAsPaid(): met à jour le statut de la commande à COMPLETED et le statut de paiement à PAID
Enregistrement des transactions
Deux types d’enregistrements de transaction sont créés :
- MomoTransaction : suit l’identifiant de référence API MTN, le statut et le numéro de téléphone du payeur.
- Transaction Shop : créée par le gestionnaire webhook/confirmation pour l’historique de paiement de la commande.
Support polymorphique
Le modèle MomoTransaction utilise une relation morphTo (payable_type / payable_id),
permettant à tout modèle implémentant Payable d’utiliser MoMo pour les paiements : pas seulement les commandes du Shop.
Mise à jour
Étape 1 : Remplacer les fichiers
Remplacez le répertoire de l’add-on par la nouvelle version.
Étape 2 : Exécuter les migrations
Étape 3 : Vider les caches
Étape 4 : Vérifier
Visitez MTN MoMo → Paramètres et utilisez Tester la clé pour confirmer que vos identifiants fonctionnent toujours.
Dépannage
« Failed to obtain MTN MoMo access token »
Vérifiez que :
- Les trois identifiants API (Clé d’abonnement, Identifiant utilisateur API, Clé API) sont correctement configurés.
- La clé d’abonnement n’a pas expiré ou n’a pas été révoquée.
- Votre serveur peut atteindre
sandbox.momodeveloper.mtn.com(sandbox) ouproxy.momoapi.mtn.com(production). - L’identifiant utilisateur API et la clé API correspondent : ils doivent provenir de la même session de provisionnement.
Le provisionnement échoue : HTTP 401
- Vérifiez que vous êtes abonné au produit Collections sur momodeveloper.mtn.com.
- Copiez la Clé primaire depuis votre page Profil, pas depuis la page du produit.
- Assurez-vous que l’abonnement est toujours actif (non expiré).
- Vérifiez les espaces en début/fin lors du collage de la clé.
Le provisionnement échoue : HTTP 409
Un utilisateur API avec l’UUID généré existe déjà. Cliquez simplement sur Générer les identifiants API à nouveau : un nouvel UUID est généré à chaque fois.
« A phone number is required for MTN MoMo payments »
Le client n’a pas saisi son numéro de téléphone dans le formulaire de paiement.
Assurez-vous que la vue du formulaire de paiement MoMo (momo::payment-form) est correctement chargée
et que le champ de saisie du téléphone est visible lorsque MoMo est sélectionné comme méthode de paiement.
Le paiement reste « en attente » indéfiniment
- En sandbox : utilisez l’un des numéros de téléphone de test (voir Tests Sandbox).
- En production : le client n’a peut-être pas approuvé l’invite USSD sur son téléphone.
- Après le délai d’expiration de la vérification (~5 minutes), un message de délai dépassé est affiché à l’utilisateur.
- Le paiement peut encore être confirmé ultérieurement via webhook si le client approuve après le délai.
« Payment was declined or cancelled »
- Le client a refusé l’invite USSD ou a saisi un code PIN incorrect.
- Le compte MoMo du client a des fonds insuffisants.
- Le code de raison MTN est ajouté au message d’erreur pour le débogage (ex.
PAYER_NOT_FOUND,NOT_ENOUGH_FUNDS).
« Request was blocked » (réponse non JSON)
Un WAF (pare-feu d’application web) ou un proxy a bloqué la requête API. Cela peut arriver lorsque la passerelle API MTN rejette la requête au niveau de l’infrastructure. Vérifiez les journaux du serveur pour le corps de réponse complet et vérifiez votre clé d’abonnement et la configuration de l’hôte de callback.
Le webhook ne fonctionne pas en production
- Assurez-vous que
momo_callback_hostest défini sur votre domaine (sans le préfixehttps://). - L’hôte de callback dans vos paramètres doit correspondre au
providerCallbackHostdéfini lors de la création de l’utilisateur API. - Votre serveur doit accepter les requêtes PUT et POST à
/momo/callbacksans vérification CSRF. - Vérifiez que HTTPS fonctionne correctement sur votre domaine.
Erreurs de non-concordance de devise
- Le sandbox requiert
EUR: toute autre devise échouera. - La production requiert la devise spécifique au pays correspondant à l’environnement cible (voir Options de paiement).
Numéros de téléphone de test Sandbox
Utilisez ces numéros de téléphone en mode sandbox pour tester différents résultats de paiement :
| Numéro de téléphone | Résultat |
|---|---|
46733123453 |
Paiement réussi |
46733123454 |
Paiement refusé |
46733123455 |
Paiement refusé |
46733123456 |
Paiement refusé |