API direct (encaissement direct fournisseur)
Envoyer le payeur droit chez son opérateur, sans passer par la page de paiement hébergée par Jèko
L'API direct est une variante du paiement en ligne. Au lieu de renvoyer le payeur vers la page de paiement hébergée par Jèko, elle appelle son opérateur dès la création de la demande.
Ce que vous y gagnez dépend du réseau, et c'est la première chose à savoir : sur Orange, Wave et Djamo, vous récupérez l'URL de l'opérateur au lieu de celle de Jèko, et le payeur revient sur vos pages plutôt que sur les nôtres. Sur MTN et Moov, l'opérateur pousse une demande de code sur le téléphone du payeur et il n'y a plus de page à ouvrir du tout.
Pour plus de détails : Create payment request (Partner API)
Quand la choisir
Le flux hébergé reste le choix par défaut. Il pose lui-même au payeur la question du moyen de
paiement, et il vous évite d'avoir à traiter un redirectUrl qui ne veut pas dire la même chose
selon le réseau.
L'API direct a du sens dans deux cas :
- Vous voulez maîtriser l'écran de paiement et vous connaissez déjà le moyen de paiement choisi. Le payeur passe directement chez l'opérateur, puis revient sur vos pages.
- Vous encaissez sur MTN ou Moov et vous connaissez le numéro du payeur. L'opérateur l'appelle en USSD, et il n'y a aucune page à ouvrir.
Si vous ne connaissez pas le moyen de paiement avant de créer la demande, restez sur le paiement en ligne.
Activer le mode direct
L'API direct utilise le même endpoint et le même type que le paiement en ligne,
avec
paymentDetails.type: "redirect". Deux champs de paymentDetails.data s'y ajoutent.
forceProviderDirect:truepour activer ce mode. Omis oufalse, vous obtenez le flux hébergé standard.payerPhone: numéro mobile ivoirien du payeur, indicatif 225 obligatoire (+225ou225), suivi de01,05ou07puis huit chiffres.+2250765432108et2250765432108sont valides,0765432108est refusé. Obligatoire dès queforceProviderDirectvauttrue.
Tous les autres champs sont ceux du paiement en ligne :
storeId, amountCents, currency, reference, paymentMethod, successUrl et errorUrl.
Comment ça marche
La création se déroule en deux temps :
- Jèko crée la demande de paiement, comme pour un paiement en ligne classique.
- Jèko appelle immédiatement l'opérateur, en lui transmettant vos
successUrleterrorUrl.
C'est le second appel qui distingue l'API direct, et il a trois conséquences que vous devez traiter,
détaillées plus bas : le contenu de redirectUrl dépend de l'opérateur, vos URLs de retour
remplacent la page Jèko comme point d'arrivée du payeur, et un échec de cet appel consomme votre
référence.
Exemple de requête
curl -X POST "https://api.jeko.africa/partner_api/payment_requests" \
-H "X-API-KEY: your_api_key_here" \
-H "X-API-KEY-ID: your_api_key_id_here" \
-H "Content-Type: application/json" \
-d '{
"storeId": "59ae202a-f583-4a15-970f-9e99bd1e0baa",
"amountCents": 10000,
"currency": "XOF",
"reference": "PAY-DIRECT-2024-001",
"paymentDetails": {
"type": "redirect",
"data": {
"paymentMethod": "orange",
"forceProviderDirect": true,
"payerPhone": "+2250765432108",
"successUrl": "https://myapp.com/payment/success?reference=PAY-DIRECT-2024-001",
"errorUrl": "https://myapp.com/payment/error?reference=PAY-DIRECT-2024-001"
}
}
}'Réponse réussie
{
"id": "d22c81f3-ee04-4ec5-8bd2-cd8af5dabcfc",
"storeId": "59ae202a-f583-4a15-970f-9e99bd1e0baa",
"reference": "PAY-DIRECT-2024-001",
"type": "redirect",
"paymentMethod": "orange",
"status": "pending",
"redirectUrl": "https://webpay.orange.ci/...",
"errorReason": null
}La réponse a la même forme qu'en paiement en ligne. Seul le contenu de redirectUrl change, et il
dépend de l'opérateur.
Le comportement dépend de l'opérateur
C'est le point le plus important de cette page. Les cinq moyens de paiement ne se comportent pas de la même façon en mode direct.
| Moyen de paiement | Ce que contient redirectUrl | Le numéro fourni | Ce que vous en faites |
|---|---|---|---|
orange | L'URL webpay d'Orange Money | enregistré, non utilisé | Redirigez le payeur dessus |
wave | L'URL de paiement de Wave | enregistré, non utilisé | Redirigez le payeur dessus |
djamo | L'URL de paiement de Djamo | enregistré, non utilisé | Redirigez le payeur dessus |
mtn | La page hébergée par Jèko | appelé en USSD | Voir ci-dessous |
moov | La page hébergée par Jèko | appelé en USSD | Voir ci-dessous |
MTN et Moov ne redirigent pas
Ces deux réseaux confirment le paiement par USSD : l'opérateur pousse une demande de code
directement sur le téléphone du payeur, il n'y a pas de page à ouvrir. En mode direct, redirectUrl
retombe donc sur le lien hébergé Jèko (), qui sert de
page d'attente.
Ne construisez pas votre intégration en supposant que redirectUrl mène toujours à l'opérateur.
Pour MTN et Moov, affichez plutôt votre propre écran d'attente et laissez le
webhook vous annoncer le résultat.
Prévoyez aussi le cas où rien n'arrive. Si le payeur ne voit pas la demande de code ou ne la
confirme pas, la demande reste pending et cesse d'être payable trente minutes après sa création.
Si l'appel à l'opérateur échoue
L'API répond 400 avec "id": "third_party_payment_provider_error" et un message générique,
« An error occurred while processing your payment, please retry ». Rien dans cette réponse ne vous
dit ce qui suit, et c'est pourtant l'essentiel.
La demande de paiement a déjà été créée et votre reference lui reste attachée, pour la
traçabilité. Conséquence directe : rejouer le même appel avec la même référence renvoie un
409 payment_request_exists_with_reference. Ce n'est pas une erreur de votre code, c'est la
demande de la tentative précédente.
Pour réessayer, générez une nouvelle référence. Une référence par tentative, pas une par commande.
La demande de la tentative échouée reste payable
Le premier temps a créé une demande avec son lien hébergé, et cet échec ne l'annule pas : le payeur peut encore la régler par ce lien pendant trente minutes. Si vous réessayez avec une nouvelle référence, vous avez donc deux demandes payables pour la même commande.
Tant que vous n'avez pas reçu de webhook sur la première, ne considérez pas la nouvelle tentative comme le seul encaissement possible, et réconciliez sur toutes les références essayées.
async function createDirectPayment(orderId, attempt = 1) {
const reference = `ORDER-${orderId}-T${attempt}`;
const response = await fetch('https://api.jeko.africa/partner_api/payment_requests', {
method: 'POST',
headers: {
'X-API-KEY': process.env.JEKO_API_KEY,
'X-API-KEY-ID': process.env.JEKO_API_KEY_ID,
'Content-Type': 'application/json'
},
body: JSON.stringify({
storeId: process.env.JEKO_STORE_ID,
amountCents: 10000,
currency: 'XOF',
reference,
paymentDetails: {
type: 'redirect',
data: {
paymentMethod: 'orange',
forceProviderDirect: true,
payerPhone: '+2250765432108',
successUrl: `https://myapp.com/payment/success?ref=${reference}`,
errorUrl: `https://myapp.com/payment/error?ref=${reference}`
}
}
})
});
if (!response.ok) {
// Ne rejouez jamais avec la même référence : elle est déjà consommée.
if (attempt < 3) return createDirectPayment(orderId, attempt + 1);
throw new Error('Initialisation du paiement direct impossible');
}
return response.json();
}Conservez la correspondance entre votre commande et chaque référence essayée. Le
webhook vous renvoie la référence dans transactionDetails.reference,
c'est elle qui vous permettra de réconcilier.
Les erreurs propres au mode direct
| Situation | Réponse |
|---|---|
forceProviderDirect: true sans payerPhone | 422, payerPhone requis |
payerPhone sans indicatif 225, par exemple 0765432108 | 422, format invalide |
| L'appel à l'opérateur échoue | 400 third_party_payment_provider_error |
| Référence déjà utilisée par une tentative précédente | 409 payment_request_exists_with_reference |
Un numéro dont le préfixe ne correspond pas au paymentMethod n'est pas rejeté par la validation :
l'appel part, et c'est l'opérateur qui le refuse. Vous récupérez alors le 400 ci-dessus, avec la
référence déjà consommée.
Le catalogue complet est dans Gérer les échecs.
Suivre le paiement
Rien ne change par rapport au paiement en ligne. La demande naît en pending, et le
webhook reste la seule confirmation fiable.
Sur Orange, Wave et Djamo, vos successUrl et errorUrl sont transmises à l'opérateur, qui y ramène
le payeur : c'est la différence avec le flux hébergé, où il revient sur la page Jèko. Mais une
redirection n'est pas une preuve de paiement. Sur MTN et Moov, personne ne ramène le payeur nulle
part, et le webhook est votre seul signal.