Gérer les échecs de paiement
Comprendre les raisons d'échec des paiements et comment les gérer
Vue d'ensemble
Les paiements peuvent échouer pour diverses raisons. Ce guide vous aide à comprendre les erreurs courantes et comment les gérer dans votre application.
Statuts de paiement
Important : Seules les demandes de paiement (payment_requests) ont un statut. Les liens de paiement (payment_links) n'ont pas de statut.
Les demandes de paiement peuvent avoir les statuts suivants :
pending: Le paiement est en attente de confirmationsuccess: Le paiement a été effectué avec succèserror: Le paiement a échoué
Pour les liens de paiement, utilisez le champ canReceivePayments (booléen) pour vérifier si le lien peut accepter de nouveaux paiements.
Erreurs communes
Lien expiré
Erreur : link_expired ou payment_link_expired
Message : "Payment link has expired"
Cause : Le lien de paiement a expiré et ne peut plus accepter de paiements.
Solution :
- Vérifiez toujours
canReceivePaymentsavant de diriger un client vers un lien - Créez un nouveau lien de paiement si le lien a expiré
- Informez le client que le lien a expiré et proposez de créer un nouveau lien
Exemple de gestion :
async function checkAndRedirectToPayment(paymentLinkId) {
// Vérifier la disponibilité du lien
const response = await fetch(
`https://api.jeko.africa/partner_api/payment_links/${paymentLinkId}`,
{
headers: {
'X-API-KEY': apiKey,
'X-API-KEY-ID': apiKeyId
}
}
);
const paymentLink = await response.json();
if (!paymentLink.canReceivePayments) {
// Le lien a expiré ou a été utilisé
if (paymentLink.allowMultiplePayments === false) {
// Lien à usage unique - créer un nouveau lien
const newLink = await createNewPaymentLink(paymentLink.storeId, paymentLink.amount);
return newLink.link;
} else {
// Lien expiré - informer l'utilisateur
throw new Error('Le lien de paiement a expiré. Veuillez créer un nouveau lien.');
}
}
return paymentLink.link;
}Lien déjà utilisé
Erreur : link_used ou payment_link_already_used
Message : "Payment link has already been used"
Cause : Le lien de paiement est à usage unique (allowMultiplePayments: false) et a déjà été utilisé pour un paiement réussi.
Solution :
- Vérifiez
canReceivePaymentsavant de diriger un client vers un lien - Pour les liens à usage unique, créez un nouveau lien pour chaque paiement
- Informez le client que le lien a déjà été utilisé
Exemple de gestion :
async function handlePaymentLink(paymentLinkId) {
const paymentLink = await getPaymentLink(paymentLinkId);
if (!paymentLink.canReceivePayments) {
if (paymentLink.allowMultiplePayments === false) {
// Lien à usage unique déjà utilisé
// Créer un nouveau lien
const newLink = await createPaymentLink({
storeId: paymentLink.storeId,
title: paymentLink.title,
amountCents: paymentLink.amount.amount,
currency: paymentLink.amount.currency,
allowMultiplePayments: false
});
return {
error: 'LINK_USED',
message: 'Ce lien a déjà été utilisé. Un nouveau lien a été créé.',
newLink: newLink.link
};
}
}
return { link: paymentLink.link };
}Demande de paiement non trouvée (404 Not Found)
Erreur : payment_request_not_found
Message : "Payment request not found"
Cause : La demande de paiement n'existe pas ou n'appartient pas à votre entreprise.
Solution :
- Vérifiez que l'ID de la demande de paiement est correct
- Vérifiez que la demande appartient à votre entreprise
- Vérifiez que la demande n'a pas été supprimée
Magasin non trouvé (404 Not Found)
Erreur : store_not_found
Message : "Store not found"
Cause : Le storeId fourni n'existe pas ou n'appartient pas à votre entreprise.
Solution :
- Vérifiez que le
storeIdest correct - Utilisez l'endpoint
/partner_api/storespour lister vos magasins - Assurez-vous que le magasin existe et est actif
Dispositif non trouvé (422 Validation Error)
Erreur : validation_error
Message : "The paymentDetails.data.deviceId field is required when paymentDetails.type is soundbox"
Cause : Pour les paiements soundbox, le deviceId est requis mais manquant ou invalide.
Solution :
- Vérifiez que le
deviceIdest fourni pour les paiements soundbox - Vérifiez que le
deviceIdexiste via l'endpoint/partner_api/devices - Assurez-vous que le dispositif est actif et associé au bon magasin
Erreur de validation (422 Unprocessable Entity)
Erreur : validation_error
Message : "Validation error"
Cause : Les données fournies ne respectent pas les règles de validation.
Problèmes courants :
- Montant inférieur au minimum (100 centimes pour payment_requests, 10000 centimes pour payment_links)
- Code devise invalide (doit être ISO 4217, 3 caractères)
- Référence manquante ou invalide (1-100 caractères)
- Titre manquant ou invalide pour payment_links (10-255 caractères)
- URLs de callback invalides (doivent être HTTPS valides)
- Méthode de paiement invalide
Solution :
- Vérifiez que tous les champs requis sont présents
- Vérifiez que les valeurs respectent les contraintes (montant minimum, longueur, format)
- Vérifiez que les URLs sont valides et utilisent HTTPS
Paiement échoué
Erreur : payment_failed ou transaction_failed
Message : "Payment failed"
Cause : Le paiement a échoué côté opérateur (Mobile Money ou banque).
Solution :
- Vérifiez que le client a suffisamment de fonds
- Vérifiez que le compte du client est actif
- Proposez au client de réessayer
- Contactez le support si le problème persiste
Clé API invalide (401 Unauthorized)
Erreur : unauthorized
Message : "Unauthorized"
Cause : Les clés API sont invalides, manquantes ou expirées.
Solution :
- Vérifiez que les en-têtes
X-API-KEYetX-API-KEY-IDsont présents - Vérifiez que les clés API sont correctes
- Régénérez vos clés API depuis le Jeko Cockpit si nécessaire
Accès interdit (403 Forbidden)
Erreur : forbidden ou forbidden_action
Message : "Forbidden" ou "Action interdite"
Cause : La clé API n'a pas la permission d'accéder à cette ressource ou d'effectuer cette action.
Solution :
- Vérifiez les permissions de votre clé API
- Contactez le support pour vérifier les permissions de votre compte
Conflit de référence (409 Conflict)
Erreur : payment_request_exists_with_reference
Message : "Une demande de paiement avec cette référence existe déjà"
Cause : Une demande de paiement avec la même référence existe déjà.
Solution :
- Utilisez des références uniques pour chaque demande de paiement
- Incluez un identifiant unique (timestamp, UUID, orderId) dans la référence
Gestion des erreurs dans votre application
Vérification préventive
Avant de créer un paiement, effectuez ces vérifications :
- Vérifier l'existence du magasin :
curl -X GET "https://api.jeko.africa/partner_api/stores/{storeId}" \
-H "X-API-KEY: your_api_key_here" \
-H "X-API-KEY-ID: your_api_key_id_here"- Pour les paiements soundbox, vérifier le dispositif :
curl -X GET "https://api.jeko.africa/partner_api/devices" \
-H "X-API-KEY: your_api_key_here" \
-H "X-API-KEY-ID: your_api_key_id_here"- Pour les liens de paiement, vérifier la disponibilité :
curl -X GET "https://api.jeko.africa/partner_api/payment_links/{paymentLinkId}" \
-H "X-API-KEY: your_api_key_here" \
-H "X-API-KEY-ID: your_api_key_id_here"Gestion des erreurs dans le code
async function createPaymentRequest(paymentData) {
try {
// Vérifications préventives
await validateStore(paymentData.storeId);
if (paymentData.type === 'soundbox') {
await validateDevice(paymentData.deviceId);
}
// Créer la demande de paiement
const response = await fetch('https://api.jeko.africa/partner_api/payment_requests', {
method: 'POST',
headers: {
'X-API-KEY': apiKey,
'X-API-KEY-ID': apiKeyId,
'Content-Type': 'application/json'
},
body: JSON.stringify(paymentData)
});
if (!response.ok) {
const error = await response.json();
// Gérer les erreurs spécifiques
switch (error.id) {
case 'payment_request_exists_with_reference':
throw new Error('Une demande avec cette référence existe déjà. Utilisez une référence unique.');
case 'store_not_found':
throw new Error('Magasin introuvable. Vérifiez le storeId.');
case 'validation_error':
throw new Error(`Erreur de validation: ${error.extras?.errors?.map(e => e.message).join(', ')}`);
case 'unauthorized':
throw new Error('Clés API invalides. Vérifiez vos identifiants.');
default:
throw new Error(`Erreur: ${error.message}`);
}
}
return await response.json();
} catch (error) {
console.error('Erreur lors de la création du paiement:', error);
throw error;
}
}
async function handlePaymentLink(paymentLinkId) {
try {
// Vérifier la disponibilité du lien
const response = await fetch(
`https://api.jeko.africa/partner_api/payment_links/${paymentLinkId}`,
{
headers: {
'X-API-KEY': apiKey,
'X-API-KEY-ID': apiKeyId
}
}
);
if (!response.ok) {
const error = await response.json();
if (error.id === 'payment_link_not_found') {
throw new Error('Lien de paiement introuvable.');
}
throw new Error(`Erreur: ${error.message}`);
}
const paymentLink = await response.json();
if (!paymentLink.canReceivePayments) {
if (paymentLink.allowMultiplePayments === false) {
throw new Error('LINK_USED', 'Ce lien a déjà été utilisé.');
} else {
throw new Error('LINK_EXPIRED', 'Ce lien a expiré.');
}
}
return paymentLink.link;
} catch (error) {
console.error('Erreur lors de la vérification du lien:', error);
throw error;
}
}Utilisation des webhooks pour le suivi
Configurez des webhooks pour être notifié automatiquement des changements de statut des paiements. Cela vous permet de :
- Suivre les paiements en temps réel
- Gérer les échecs automatiquement
- Mettre à jour votre système lorsque le statut change
Consultez la documentation Webhooks pour plus d'informations.
Bonnes pratiques
- Vérifications préventives : Toujours vérifier les prérequis avant de créer un paiement
- Gestion d'erreurs robuste : Implémentez une gestion d'erreurs complète pour tous les cas d'échec
- Logging : Enregistrez toutes les erreurs pour le débogage et l'analyse
- Messages utilisateur : Informez l'utilisateur des erreurs de manière claire et actionnable
- Retry logic : Pour les erreurs temporaires, implémentez une logique de réessai avec backoff exponentiel
- Monitoring : Surveillez les taux d'échec pour identifier les problèmes récurrents
- Vérification des liens : Toujours vérifier
canReceivePaymentsavant de diriger un client vers un lien
Support
Si vous rencontrez des erreurs persistantes ou des problèmes non documentés, contactez le support JEKO à hello@jeko.africa.