Guide de dépannage
Problèmes courants et solutions lors de l'intégration avec l'API ChinqIT Verify.
Note : Préférez les endpoints API v2 (POST /api/v2/notify, POST /api/v2/code, POST /api/v2/check, GET /api/v2/notify/:messageId). Les anciens endpoints v1 sont dépréciés et les réponses incluent un objet deprecation et l'en-tête Deprecation: true.
🔍 Étapes générales de dépannage
- Vérifier la clé API : Assurez-vous que votre clé API est correcte et active
- Vérifier le format de la requête : Vérifiez que le corps de votre requête correspond à la spécification de l'API
- Examiner les messages d'erreur : Consultez la réponse d'erreur pour des détails spécifiques
- Tester la connectivité : Assurez-vous que votre application peut accéder à
https://sms.chinqit.com(v2 :https://sms.chinqit.com/api/v2/notifypour l'envoi)
🔐 Problèmes d'authentification
401 Unauthorized - Clé API manquante
Symptômes :
- Code d'état 401
- Message d'erreur "API key is required"
Solutions :
-
Vérifier le nom de l'en-tête
# Doit être exactement : X-API-Key (sensible à la casse) curl -H "X-API-Key: your-key" https://sms.chinqit.com/api/v2/notify -
Vérifier le format de l'en-tête
// Correct headers: { 'X-API-Key': 'your-api-key' } // Incorrect - trait d'union manquant headers: { 'X_API_Key': 'your-api-key' } -
Vérifier que la clé API est incluse
- Vérifiez que votre clé API est envoyée dans chaque requête
- Assurez-vous qu'aucun middleware ne supprime l'en-tête
403 Forbidden - Clé API invalide
Symptômes :
- Code d'état 403
- Message d'erreur "Invalid API key"
Solutions :
-
Vérifier la clé API
- Contactez le support ChinqIT Verify pour confirmer que votre clé API est active
- Vérifiez les fautes de frappe ou les espaces supplémentaires dans votre clé API
- Assurez-vous d'utiliser la clé API correcte pour votre environnement
-
Vérifier le format de la clé API
# Assurez-vous qu'il n'y a pas d'espaces ou de caractères supplémentaires # Correct : "abc123xyz" # Incorrect : " abc123xyz " ou "abc123xyz\n" -
Régénérer la clé API
- Si votre clé API a été compromise ou révoquée, demandez-en une nouvelle auprès de ChinqIT Verify
📝 Erreurs de validation
400 Bad Request - Erreur de validation
Symptômes :
- Code d'état 400
- Message "Validation failed" avec détails de l'erreur
Erreurs de validation courantes :
Champ obligatoire manquant :
{
"success": false,
"message": "Validation failed",
"errors": [
{
"path": ["phoneNumber"],
"message": "Required"
}
]
}Format de numéro de téléphone invalide :
{
"success": false,
"message": "Validation failed",
"errors": [
{
"path": ["phoneNumber"],
"message": "Invalid phone number format"
}
]
}Solutions :
-
Vérifier le corps de la requête
// Format correct pour l'envoi de SMS { "phoneNumber": "+1234567890", "message": "Your message here" } // Format correct pour l'envoi d'OTP { "phoneNumber": "+1234567890", "language": "en", "channel": "sms" } -
Vérifier le format du numéro de téléphone
- Doit inclure l'indicatif du pays avec le préfixe
+ - Exemples :
+1234567890,+33123456789 - Pas d'espaces ou de caractères spéciaux sauf
+
- Doit inclure l'indicatif du pays avec le préfixe
-
Vérifier le contenu du message
- Le message doit contenir au moins 1 caractère
- L'OTP doit contenir exactement 6 chiffres
-
Vérifier la valeur du canal
- Pour l'OTP :
channeldoit être"sms"ou"whatsapp"(en minuscules) - Par défaut
"sms"si omis
- Pour l'OTP :
📊 Limitation de débit
429 Too Many Requests
Symptômes :
- Code d'état 429
- Message d'erreur "Rate limit exceeded"
Limites de débit :
- Envoi d'OTP : 3 requêtes par minute, 10 par heure, 20 par jour (par numéro de téléphone par clé API)
Solutions :
-
Implémenter un délai d'attente exponentiel
async function sendOTPWithRetry( phoneNumber, language, channel, maxRetries = 3, ) { for (let i = 0; i < maxRetries; i++) { try { return await client.sendOTP(phoneNumber, language, channel); } catch (error) { if (error.status === 429 && i < maxRetries - 1) { // Attendre avec délai exponentiel const waitTime = Math.pow(2, i) * 1000; // 1s, 2s, 4s await new Promise((resolve) => setTimeout(resolve, waitTime)); continue; } throw error; } } } -
Respecter les limites de débit
- Suivez la fréquence de vos requêtes
- Implémentez une limitation de débit côté client
- Attendez avant de réessayer après des erreurs 429
-
Utiliser différents numéros de téléphone
- Les limites de débit sont par numéro de téléphone
- Si vous testez, utilisez différents numéros de téléphone pour éviter d'atteindre les limites
💳 Solde insuffisant
402 Payment Required
Symptômes :
- Code d'état HTTP 402
- Message d'erreur
"Insufficient balance" - Champ
messageIdprésent dans la réponse
Solutions :
-
Vérifier le solde de votre compte
- Connectez-vous au tableau de bord ChinqIT Verify
- Consultez la section solde et historique des transactions
-
Recharger votre compte
- Utilisez BPAY pour effectuer un paiement
- Contactez votre administrateur pour un réapprovisionnement
-
Réessayer après le rechargement
- Les clés API sont réactivées après un paiement BPAY réussi ou un crédit admin (pas après récompense de parrainage ni remboursement SMS)
- Si vous recevez toujours 403
"Invalid or inactive API key", attendez jusqu'à 60 secondes (le tableau de bord doit partager Redis avec la passerelle SMS) ou contactez le support
-
Contacter le support
- Si le problème persiste après un rechargement, contactez le support ChinqIT Verify
- Fournissez votre identifiant de compte et les détails de la transaction
Messages rejetés et échoués
Un message rejeté est parvenu à l'opérateur, qui l'a refusé — le plus souvent parce que le numéro du destinataire n'est pas une destination valide. L'opérateur nous facture chaque soumission qu'il reçoit : un message rejeté est donc facturé. Son coût apparaît normalement dans le tableau de bord et dans l'export CSV.
Un message échoué n'est jamais parvenu à l'opérateur. Notre passerelle n'a pas pu le
soumettre, ou votre solde était insuffisant. Il n'est pas facturé ; tout montant déjà débité
est remboursé, affiché sous forme de coût barré accompagné du badge Remboursé, et exporté
avec Refunded=Yes.
Si vous constatez une série de messages rejetés, vérifiez les numéros des destinataires. Un taux de rejet élevé provient presque toujours d'une liste de contacts obsolète, et non d'un défaut de la plateforme.
Les destinataires invalides ne sont pas remboursés
Les rejets pour destinataire invalide (ESME_RINVDSTADR) sont facturés plutôt
que remboursés, comme tout autre rejet : l'opérateur nous facture chaque
soumission reçue, y compris celles qu'il rejette — nous répercutons donc ce
coût. Ces messages affichent status: rejected avec Refunded à No.
Si le même numéro est rejeté à nouveau dans l'heure, le message n'est pas resoumis et pas facturé : vous payez au plus une fois par heure pour un numéro mort. Les codes de vérification (OTP) sont toujours soumis et jamais supprimés.
📱 Problèmes de canal WhatsApp
502 Bad Gateway - Erreur du fournisseur WhatsApp
Symptômes :
- Code d'état 502
- Message d'erreur "WhatsApp OTP send failed"
- Détails de l'erreur de l'API WhatsApp
Solutions :
-
Vérifier le format du numéro de téléphone
- WhatsApp requiert les numéros de téléphone au format E.164 avec l'indicatif du pays
- Exemple :
+1234567890(pas1234567890)
-
Implémenter un repli vers SMS
async function sendOTPWithFallback(phoneNumber, language) { try { // Essayer WhatsApp en premier return await client.sendOTP(phoneNumber, language, "whatsapp"); } catch (error) { if (error.status === 502) { // Repli vers SMS si WhatsApp échoue console.log("WhatsApp failed, falling back to SMS"); return await client.sendOTP(phoneNumber, language, "sms"); } throw error; } } -
Gérer les erreurs du fournisseur avec élégance
- Les erreurs du fournisseur WhatsApp sont temporaires
- Implémentez une logique de nouvelle tentative avec repli vers SMS
- Enregistrez les erreurs pour la surveillance
-
Vérifier la disponibilité du service WhatsApp
- Contactez le support ChinqIT Verify si le canal WhatsApp échoue constamment
- Vérifiez si le service WhatsApp est temporairement indisponible
🔄 Problèmes d'intégration courants
Messages non envoyés
Symptômes :
- La requête réussit mais le message n'est pas reçu
- Pas d'erreur mais pas de confirmation de livraison
Solutions :
-
Vérifier le numéro de téléphone
- Assurez-vous que le numéro de téléphone est correct et actif
- Vérifiez que l'indicatif du pays est correct
- Vérifiez que le destinataire peut recevoir des SMS
-
Vérifier le contenu du message
- Assurez-vous que le message n'est pas vide
- Vérifiez que les caractères spéciaux sont correctement encodés
- Vérifiez la longueur du message (les limites SMS standard s'appliquent)
-
Gérer le traitement asynchrone
- Les messages sont mis en file d'attente et traités de manière asynchrone
- L'API retourne immédiatement après la mise en file d'attente
- La livraison peut prendre quelques secondes à quelques minutes
Échec de la vérification OTP
Symptômes :
- L'OTP est envoyé avec succès mais la vérification échoue
- Erreurs "Invalid OTP" ou "OTP not found"
Solutions :
-
Vérifier l'expiration de l'OTP
- Les OTP expirent après 10 minutes
- Assurez-vous que l'utilisateur entre l'OTP rapidement
- Demandez un nouvel OTP s'il est expiré
-
Vérifier le format de l'OTP
- L'OTP doit contenir exactement 6 chiffres
- Pas d'espaces ou de caractères spéciaux
- Exemple :
"123456"(pas"123 456"ou"123-456")
-
Vérifier la limite de tentatives
- Maximum 3 tentatives de vérification par OTP
- Après 3 échecs, l'OTP est invalidé
- Demandez un nouvel OTP si la limite de tentatives est dépassée
-
Faire correspondre le canal
- Si l'OTP a été envoyé via WhatsApp, vérifiez avec
channel: "whatsapp" - Si l'OTP a été envoyé via SMS, vérifiez avec
channel: "sms"(ou omettez, par défaut SMS)
- Si l'OTP a été envoyé via WhatsApp, vérifiez avec
-
Gérer la sensibilité à la casse
- Le numéro de téléphone doit correspondre exactement (y compris le préfixe
+) - Assurez-vous que le format du numéro de téléphone est cohérent entre l'envoi et la vérification
- Le numéro de téléphone doit correspondre exactement (y compris le préfixe
🌐 Problèmes réseau
Délai de connexion dépassé
Symptômes :
- Expiration de la requête
- Erreurs réseau
Solutions :
-
Vérifier la connexion Internet
- Vérifiez que votre application a accès à Internet
- Testez la connectivité à
https://sms.chinqit.com
-
Implémenter la gestion des délais d'attente
const controller = new AbortController(); const timeoutId = setTimeout(() => controller.abort(), 10000); // Délai de 10 secondes try { const response = await fetch("https://sms.chinqit.com/api/v2/notify", { signal: controller.signal, // ... autres options }); clearTimeout(timeoutId); } catch (error) { if (error.name === "AbortError") { console.error("Request timeout"); } } -
Logique de nouvelle tentative
- Implémentez une logique de nouvelle tentative pour les erreurs réseau transitoires
- Utilisez un délai d'attente exponentiel
- Ne réessayez pas sur les erreurs 4xx (erreurs client)
Erreurs SSL/TLS
Symptômes :
- Erreurs de certificat SSL
- Échecs de négociation TLS
Solutions :
-
Vérifier HTTPS
- Utilisez toujours
https://sms.chinqit.com(pashttp://) - Assurez-vous que votre environnement supporte TLS 1.2+
- Utilisez toujours
-
Vérifier le certificat
- Assurez-vous que l'horloge système est correcte
- Mettez à jour les certificats CA si nécessaire
- Contactez ChinqIT Verify si les problèmes de certificat persistent
🐛 Conseils de débogage
Activer la journalisation des requêtes
JavaScript :
async function sendMessage(phoneNumber, message) {
console.log("Sending message:", { phoneNumber, message });
try {
const response = await fetch("https://sms.chinqit.com/api/v2/notify", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-API-Key": process.env.API_KEY,
},
body: JSON.stringify({ phoneNumber, message }),
});
console.log("Response status:", response.status);
const data = await response.json();
console.log("Response data:", data);
return data;
} catch (error) {
console.error("Error:", error);
throw error;
}
}Python :
import requests
import logging
logging.basicConfig(level=logging.DEBUG)
def send_message(phone_number, message):
url = 'https://sms.chinqit.com/api/v2/notify'
headers = {
'Content-Type': 'application/json',
'X-API-Key': os.getenv('API_KEY')
}
data = {
'phoneNumber': phone_number,
'message': message
}
logging.debug(f'Sending request: {data}')
response = requests.post(url, json=data, headers=headers)
logging.debug(f'Response status: {response.status_code}')
logging.debug(f'Response data: {response.json()}')
return response.json()Tester la connectivité de l'API
# Tester la connectivité de base
curl -X POST https://sms.chinqit.com/api/v2/notify \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"phoneNumber": "+1234567890", "message": "Test"}'🚨 Stratégies de gestion des échecs de livraison OTP
Comprendre les scénarios d'échec de livraison
Les OTP peuvent échouer à être livrés pour plusieurs raisons :
- Problèmes réseau temporaires : Congestion réseau, maintenance
- Problèmes de fournisseur SMS : Indisponibilité du fournisseur
- Numéros invalides ou injoignables : Numéro hors service, roaming
- Limites de débit : Trop de messages envoyés
- Blocage par l'opérateur : Filtrage anti-spam
Stratégie 1 : Logique de nouvelle tentative avec backoff exponentiel
Implémentez une logique de nouvelle tentative pour les erreurs temporaires (5xx) :
class OTPService {
constructor(apiKey) {
this.apiKey = apiKey;
this.baseURL = "https://sms.chinqit.com/api/v2";
}
async sendOTPWithRetry(
phoneNumber,
language = "fr",
channel = "sms",
maxRetries = 3,
) {
let lastError;
for (let attempt = 0; attempt <= maxRetries; attempt++) {
try {
const response = await this.sendOTP(phoneNumber, language, channel);
if (response.success) {
return response;
}
// Si c'est une erreur 5xx ou réseau, retenter
if (this.isRetryableError(response)) {
if (attempt < maxRetries) {
const delay = Math.pow(2, attempt) * 1000; // Backoff exponentiel
await this.sleep(delay);
continue;
}
}
return response; // Erreur non retry-able
} catch (error) {
lastError = error;
// Erreurs réseau ou 5xx sont retry-ables
if (this.isRetryableNetworkError(error) && attempt < maxRetries) {
const delay = Math.pow(2, attempt) * 1000;
await this.sleep(delay);
continue;
}
throw error;
}
}
throw lastError;
}
isRetryableError(response) {
// Erreurs temporaires du serveur
return response.status >= 500 && response.status < 600;
}
isRetryableNetworkError(error) {
return (
error.code === "ECONNRESET" ||
error.code === "ETIMEDOUT" ||
error.code === "ENOTFOUND"
);
}
async sendOTP(phoneNumber, language, channel) {
const response = await fetch(`${this.baseURL}/code`, {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-API-Key": this.apiKey,
},
body: JSON.stringify({
phoneNumber,
language,
channel,
}),
});
return response.json();
}
sleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
}
// Utilisation
const otpService = new OTPService("YOUR_API_KEY");
try {
const result = await otpService.sendOTPWithRetry("+22238089336", "fr", "sms");
console.log("OTP envoyé avec succès:", result.messageId);
} catch (error) {
console.error("Échec définitif de l'envoi OTP:", error.message);
}Stratégie 2 : Repli entre canaux (SMS ↔ WhatsApp)
Si un canal échoue, basculez automatiquement vers l'autre :
async function sendOTPWithChannelFallback(
phoneNumber,
language = "fr",
primaryChannel = "sms",
) {
const channels =
primaryChannel === "sms" ? ["sms", "whatsapp"] : ["whatsapp", "sms"];
for (const channel of channels) {
try {
console.log(`Tentative d'envoi OTP via ${channel}...`);
const response = await fetch("https://sms.chinqit.com/api/v2/code", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-API-Key": "YOUR_API_KEY",
},
body: JSON.stringify({
phoneNumber,
language,
channel,
}),
});
const result = await response.json();
if (result.success) {
console.log(`OTP envoyé avec succès via ${channel}`);
return {
...result,
channelUsed: channel,
};
}
// Si échec définitif (pas d'erreur temporaire), essayer l'autre canal
if (!isTemporaryFailure(result)) {
console.log(
`${channel} a échoué définitivement, essai de l'autre canal...`,
);
continue;
}
// Erreur temporaire, ne pas essayer l'autre canal immédiatement
throw new Error(
`${channel} temporairement indisponible: ${result.message}`,
);
} catch (error) {
console.error(`Erreur avec ${channel}:`, error.message);
// Continuer vers l'autre canal seulement si c'est le premier essai
if (channel === channels[0]) {
continue;
}
throw error;
}
}
throw new Error("Les deux canaux ont échoué");
}
function isTemporaryFailure(result) {
// Considérer comme temporaire les erreurs 5xx ou certains messages spécifiques
return (
result.status >= 500 ||
result.message?.includes("temporarily unavailable") ||
result.message?.includes("service unavailable")
);
}
// Utilisation
try {
const result = await sendOTPWithChannelFallback("+22238089336", "fr", "sms");
console.log(`OTP envoyé via ${result.channelUsed}:`, result.messageId);
} catch (error) {
console.error("Échec sur les deux canaux:", error.message);
}Stratégie 3 : Repli vers saisie manuelle d'OTP
Quand la livraison automatique échoue, permettez la saisie manuelle :
class OTPVerificationManager {
constructor() {
this.deliveryAttempts = 0;
this.maxDeliveryAttempts = 2;
this.manualEntryEnabled = false;
}
async requestOTP(phoneNumber, language = "fr") {
this.deliveryAttempts = 0;
this.manualEntryEnabled = false;
// Essayer la livraison automatique d'abord
while (this.deliveryAttempts < this.maxDeliveryAttempts) {
try {
this.deliveryAttempts++;
console.log(
`Tentative de livraison ${this.deliveryAttempts}/${this.maxDeliveryAttempts}`,
);
const result = await this.attemptDelivery(phoneNumber, language);
if (result.success) {
return {
success: true,
method: "automatic",
messageId: result.messageId,
channel: result.channelUsed,
expiresIn: result.expiresIn,
};
}
// Si échec et c'était la dernière tentative, activer la saisie manuelle
if (this.deliveryAttempts >= this.maxDeliveryAttempts) {
console.log(
"Livraison automatique échouée, activation de la saisie manuelle",
);
this.manualEntryEnabled = true;
return {
success: false,
method: "manual_required",
reason: "delivery_failed",
message: "Veuillez saisir manuellement le code OTP reçu",
};
}
// Attendre avant la prochaine tentative
await this.sleep(2000);
} catch (error) {
console.error(
`Tentative ${this.deliveryAttempts} échouée:`,
error.message,
);
if (this.deliveryAttempts >= this.maxDeliveryAttempts) {
this.manualEntryEnabled = true;
return {
success: false,
method: "manual_required",
reason: "delivery_error",
message:
"Erreur de livraison, veuillez saisir manuellement le code OTP",
};
}
await this.sleep(2000);
}
}
}
async attemptDelivery(phoneNumber, language) {
// Utiliser la logique de fallback canal précédente
return await sendOTPWithChannelFallback(phoneNumber, language);
}
async verifyOTP(phoneNumber, otp, channel = null) {
try {
const response = await fetch("https://sms.chinqit.com/api/v2/check", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-API-Key": "YOUR_API_KEY",
},
body: JSON.stringify({
phoneNumber,
otp,
...(channel && { channel }),
}),
});
const result = await response.json();
return result;
} catch (error) {
throw new Error(`Erreur de vérification: ${error.message}`);
}
}
isManualEntryEnabled() {
return this.manualEntryEnabled;
}
sleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
}
// Exemple d'utilisation dans une interface utilisateur
async function handleOTPRequest(phoneNumber) {
const manager = new OTPVerificationManager();
// Afficher un indicateur de chargement
showLoadingSpinner();
try {
const result = await manager.requestOTP(phoneNumber);
hideLoadingSpinner();
if (result.success) {
// Livraison automatique réussie
showSuccessMessage(`Code envoyé via ${result.channel}`);
showOTPInputField();
} else if (result.method === "manual_required") {
// Activer le mode saisie manuelle
showManualEntryMode();
showInfoMessage(result.message);
// Optionnellement, permettre à l'utilisateur de demander un nouveau code
showResendButton();
}
} catch (error) {
hideLoadingSpinner();
showErrorMessage("Erreur lors de l'envoi du code. Veuillez réessayer.");
}
}
async function handleOTPVerification(phoneNumber, otp) {
const manager = new OTPVerificationManager();
try {
const result = await manager.verifyOTP(phoneNumber, otp);
if (result.success) {
showSuccessMessage("Vérification réussie !");
proceedToNextStep();
} else {
if (result.retriesLeft > 0) {
showErrorMessage(
`Code incorrect. ${result.retriesLeft} tentatives restantes.`,
);
} else {
showErrorMessage("Code incorrect. Demandez un nouveau code.");
showResendButton();
}
}
} catch (error) {
showErrorMessage("Erreur de vérification. Veuillez réessayer.");
}
}Stratégie 4 : Gestion des quotas et limites de débit
Surveillez et gérez les limites d'envoi :
class OTPRateLimiter {
constructor(maxRequestsPerMinute = 10, maxRequestsPerHour = 50) {
this.requests = [];
this.maxPerMinute = maxRequestsPerMinute;
this.maxPerHour = maxRequestsPerHour;
}
canSend(phoneNumber) {
const now = Date.now();
const oneMinuteAgo = now - 60000;
const oneHourAgo = now - 3600000;
// Nettoyer les anciennes requêtes
this.requests = this.requests.filter((req) => req.timestamp > oneHourAgo);
// Compter les requêtes pour ce numéro
const recentRequests = this.requests.filter(
(req) => req.phoneNumber === phoneNumber && req.timestamp > oneMinuteAgo,
);
const hourlyRequests = this.requests.filter(
(req) => req.phoneNumber === phoneNumber && req.timestamp > oneHourAgo,
);
return (
recentRequests.length < this.maxPerMinute &&
hourlyRequests.length < this.maxPerHour
);
}
recordRequest(phoneNumber) {
this.requests.push({
phoneNumber,
timestamp: Date.now(),
});
}
getTimeUntilNextAllowed(phoneNumber) {
if (this.canSend(phoneNumber)) {
return 0;
}
const now = Date.now();
const recentRequests = this.requests
.filter((req) => req.phoneNumber === phoneNumber)
.sort((a, b) => b.timestamp - a.timestamp);
if (recentRequests.length >= this.maxPerMinute) {
const oldestRecent = recentRequests[this.maxPerMinute - 1];
return Math.max(0, 60000 - (now - oldestRecent.timestamp));
}
return 0;
}
}
// Intégration avec le service OTP
async function sendOTPWithRateLimit(phoneNumber, language) {
const rateLimiter = new OTPRateLimiter();
if (!rateLimiter.canSend(phoneNumber)) {
const waitTime = rateLimiter.getTimeUntilNextAllowed(phoneNumber);
throw new Error(
`Trop de requêtes. Réessayez dans ${Math.ceil(waitTime / 1000)} secondes.`,
);
}
try {
const result = await sendOTPWithChannelFallback(phoneNumber, language);
rateLimiter.recordRequest(phoneNumber);
return result;
} catch (error) {
// Ne pas compter les échecs réseau comme des requêtes réussies
throw error;
}
}Bonnes pratiques pour l'expérience utilisateur
- Communication claire : Informez l'utilisateur du canal utilisé et du délai d'expiration
- Indicateurs visuels : Montrez le progrès des tentatives de livraison
- Options de secours : Toujours offrir la possibilité de saisir manuellement l'OTP
- Messages d'erreur utiles : Expliquez pourquoi la livraison a échoué et que faire ensuite
- Bouton "Renvoyer" : Permettez facilement de demander un nouveau code
- Support multi-canal : Préférez automatiquement le canal le plus fiable pour l'utilisateur
Surveillance et métriques
Suivez les taux de succès de livraison pour optimiser votre stratégie :
class OTPMetrics {
constructor() {
this.metrics = {
totalRequests: 0,
successfulDeliveries: 0,
failedDeliveries: 0,
channelUsage: { sms: 0, whatsapp: 0 },
fallbackUsage: 0,
manualEntryUsage: 0,
averageDeliveryTime: 0,
};
}
recordAttempt(channel, success, deliveryTime = null) {
this.metrics.totalRequests++;
if (success) {
this.metrics.successfulDeliveries++;
} else {
this.metrics.failedDeliveries++;
}
this.metrics.channelUsage[channel] =
(this.metrics.channelUsage[channel] || 0) + 1;
if (deliveryTime) {
this.metrics.averageDeliveryTime =
(this.metrics.averageDeliveryTime + deliveryTime) / 2;
}
}
recordFallback() {
this.metrics.fallbackUsage++;
}
recordManualEntry() {
this.metrics.manualEntryUsage++;
}
getSuccessRate() {
return this.metrics.totalRequests > 0
? (this.metrics.successfulDeliveries / this.metrics.totalRequests) * 100
: 0;
}
getChannelPreference() {
const smsRate = this.metrics.channelUsage.sms || 0;
const whatsappRate = this.metrics.channelUsage.whatsapp || 0;
const total = smsRate + whatsappRate;
return total > 0
? {
sms: (smsRate / total) * 100,
whatsapp: (whatsappRate / total) * 100,
}
: { sms: 0, whatsapp: 0 };
}
logMetrics() {
console.log("OTP Delivery Metrics:");
console.log(`- Total requests: ${this.metrics.totalRequests}`);
console.log(`- Success rate: ${this.getSuccessRate().toFixed(2)}%`);
console.log(`- Channel usage:`, this.getChannelPreference());
console.log(`- Fallback usage: ${this.metrics.fallbackUsage}`);
console.log(`- Manual entry usage: ${this.metrics.manualEntryUsage}`);
console.log(
`- Avg delivery time: ${this.metrics.averageDeliveryTime.toFixed(2)}ms`,
);
}
}
// Utilisation
const metrics = new OTPMetrics();
// Après chaque tentative de livraison
metrics.recordAttempt("sms", true, 2500);
metrics.recordFallback();
metrics.recordManualEntry();
// Afficher les métriques périodiquement
setInterval(() => metrics.logMetrics(), 3600000); // Toutes les heures🆘 Vous avez toujours des problèmes ?
-
Consultez la documentation :
- Référence API - API actuelle | Référence API v1 (Dépréciée) - Endpoints legacy
- Guide d'utilisation de l'API - Exemples de code
-
Examinez les réponses d'erreur :
- Vérifiez le champ
messagepour des détails d'erreur spécifiques - Consultez le tableau
errorspour les problèmes de validation - Notez le code d'état HTTP
- Vérifiez le champ
-
Solutions courantes :
- Vérifiez que la clé API est correcte et active
- Vérifiez que le format de la requête correspond à la spécification de l'API
- Assurez-vous que les numéros de téléphone sont au format E.164
- Implémentez une gestion appropriée des erreurs et une logique de nouvelle tentative
- Contactez le support ChinqIT Verify pour les problèmes persistants
Besoin d'aide supplémentaire ? Contactez le support ChinqIT Verify avec :
- Votre clé API (masquée)
- Message d'erreur et code d'état
- Détails de la requête (sans données sensibles)
- Étapes pour reproduire le problème