
MTN MoMo
MTN MoMo - Collection (Request to Pay)
Demande un paiement MoMo avec X-Reference-Id, puis interroge le statut ou reçoit le callback.
Même prompt, avec et sans ce contexte
Les passages barrés sont ceux que l'IA a inventés. Basculez pour voir la sortie avec le contexte.
› Demande un paiement MTN MoMo de 100 sur le numéro du client (sandbox).
1await fetch("https://sandbox.momodeveloper.mtn.com/collection/v1/payments", {Endpoint inexistant2 method: "POST",3 headers: { Authorization: "Bearer " + token },4 body: JSON.stringify({ amount: 100, currency: "XOF", phone: msisdn }),Sandbox : EUR uniquement, Champ inconnu5});Authentification
- Jeton :
POST https://sandbox.momodeveloper.mtn.com/collection/token/avecAuthorization: Basic <base64(api_user:api_key)>. - Header
Ocp-Apim-Subscription-Key: <clé primaire du produit Collection>sur tous les appels. - Appels métier :
Authorization: Bearer <access_token>.
Endpoints
POST /collection/v1_0/requesttopay- Headers :
X-Reference-Id(UUID v4 généré par vous),X-Target-Environment(sandboxou l'environnement du pays),X-Callback-Urloptionnel. - Corps :
amount(string),currency,externalId,payer: { partyIdType: "MSISDN", partyId },payerMessage,payeeNote. - Réponse :
202 Acceptedsans corps.
- Headers :
GET /collection/v1_0/requesttopay/:referenceIdrenvoiestatus:PENDING,SUCCESSFUL,FAILED.
Erreurs
409X-Reference-Iddéjà utilisé : générer un nouvel UUID.400corps invalide oupartyIdmal formaté.401jeton expiré.500en sandbox avec certains numéros de test : voir les numéros de test documentés.
Webhooks
- Si
X-Callback-Urlest fourni, MTN appelle cette URL avec le statut final. - Le callback n'est pas signé : toujours confirmer avec
GET /requesttopay/:referenceId.
Idempotence et limites
X-Reference-Idest la clé d'idempotence : un UUID par demande.- Interroger le statut avec un intervalle croissant, pas en boucle serrée.
Pièges courants
Ce que les LLMs inventent le plus souvent pour MTN MoMo.
- En sandbox, la seule devise acceptée est
EUR. - La réponse de
requesttopayest vide : l'identifiant est celui que vous avez envoyé. amountest une chaîne.- Pas de
transactionIdrenvoyé à la création.
Exemple minimal
1export async function requestToPay(token: string, msisdn: string, amount: number): Promise<string> {2 const referenceId = crypto.randomUUID();3 const res = await fetch("https://sandbox.momodeveloper.mtn.com/collection/v1_0/requesttopay", {4 method: "POST",5 headers: {6 Authorization: "Bearer " + token,7 "X-Reference-Id": referenceId,8 "X-Target-Environment": process.env.MOMO_TARGET_ENV ?? "sandbox",9 "Ocp-Apim-Subscription-Key": process.env.MOMO_SUBSCRIPTION_KEY ?? "",10 "Content-Type": "application/json",11 },12 body: JSON.stringify({13 amount: String(amount),14 currency: "EUR",15 externalId: referenceId,16 payer: { partyIdType: "MSISDN", partyId: msisdn },17 payerMessage: "Commande",18 payeeNote: "Commande",19 }),20 });21 if (res.status !== 202) throw new Error("MoMo " + res.status);22 return referenceId;23}Variables d'environnement
MOMO_API_USERMOMO_API_KEYMOMO_SUBSCRIPTION_KEYMOMO_TARGET_ENV