
M-Pesa
M-Pesa Daraja - STK Push
Déclenche une demande de paiement M-Pesa Express sur le téléphone du client et lit le callback stkCallback.
Authentification
GET https://sandbox.safaricom.co.ke/oauth/v1/generate?grant_type=client_credentialsavecAuthorization: Basic <base64(consumer_key:consumer_secret)>.- Appels métier :
Authorization: Bearer <access_token>.
Endpoints
POST https://sandbox.safaricom.co.ke/mpesa/stkpush/v1/processrequest- Requis :
BusinessShortCode,Password,Timestamp,TransactionType(CustomerPayBillOnline),Amount,PartyA,PartyB,PhoneNumber,CallBackURL,AccountReference,TransactionDesc. Password= base64(BusinessShortCode+Passkey+Timestamp).Timestampau formatYYYYMMDDHHmmss.- Réponse :
CheckoutRequestID,ResponseCode(0= demande acceptée).
- Requis :
Erreurs
ResponseCodedifférent de0: demande refusée, lireerrorMessage.- Callback
ResultCode: 1032: annulé par l'utilisateur.
Webhooks
- Safaricom appelle
CallBackURLavecBody.stkCallback:CheckoutRequestID,ResultCode,ResultDesc,CallbackMetadata.Item[]. ResultCode: 0signifie paiement réussi.MpesaReceiptNumberse trouve dansCallbackMetadata.
Idempotence et limites
- Stocker
CheckoutRequestIDpour rapprocher le callback.
Pièges courants
Ce que les LLMs inventent le plus souvent pour M-Pesa.
PhoneNumberetPartyAau format2547XXXXXXXX, sans+ni0initial.CallBackURLdoit être public en HTTPS :localhostest refusé.- Le mot de passe n'est pas la
Passkeyseule.
Exemple minimal
1export function darajaPassword(shortCode: string, passkey: string, timestamp: string): string {2 return Buffer.from(shortCode + passkey + timestamp).toString("base64");3}4 5export function darajaTimestamp(d = new Date()): string {6 const p = (n: number) => String(n).padStart(2, "0");7 return d.getFullYear() + p(d.getMonth() + 1) + p(d.getDate()) + p(d.getHours()) + p(d.getMinutes()) + p(d.getSeconds());8}Variables d'environnement
MPESA_CONSUMER_KEYMPESA_CONSUMER_SECRETMPESA_SHORTCODEMPESA_PASSKEY