Aller au contenu principal

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

  1. Vérifier la clé API : Assurez-vous que votre clé API est correcte et active
  2. Vérifier le format de la requête : Vérifiez que le corps de votre requête correspond à la spécification de l'API
  3. Examiner les messages d'erreur : Consultez la réponse d'erreur pour des détails spécifiques
  4. Tester la connectivité : Assurez-vous que votre application peut accéder à https://sms.chinqit.com (v2 : https://sms.chinqit.com/api/v2/notify pour 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 :

  1. 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/messages/send
  2. 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'
    }
  3. 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 :

  1. 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
  2. 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"
  3. 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 :

  1. 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"
    }
  2. 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 +
  3. Vérifier le contenu du message

    • Le message doit contenir au moins 1 caractère
    • L'OTP doit contenir exactement 6 chiffres
  4. Vérifier la valeur du canal

    • Pour l'OTP : channel doit être "sms" ou "whatsapp" (en minuscules)
    • Par défaut "sms" si omis

📊 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 :

  1. 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;
    }
    }
    }
  2. 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
  3. 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

📱 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 :

  1. 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 (pas 1234567890)
  2. 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;
    }
    }
  3. 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
  4. 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 :

  1. 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
  2. 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)
  3. 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 :

  1. 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é
  2. 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")
  3. 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
  4. 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)
  5. 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

🌐 Problèmes réseau

Délai de connexion dépassé

Symptômes :

  • Expiration de la requête
  • Erreurs réseau

Solutions :

  1. Vérifier la connexion Internet

    • Vérifiez que votre application a accès à Internet
    • Testez la connectivité à https://sms.chinqit.com
  2. 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/messages/send", {
    signal: controller.signal,
    // ... autres options
    });
    clearTimeout(timeoutId);
    } catch (error) {
    if (error.name === "AbortError") {
    console.error("Request timeout");
    }
    }
  3. 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 :

  1. Vérifier HTTPS

    • Utilisez toujours https://sms.chinqit.com (pas http://)
    • Assurez-vous que votre environnement supporte TLS 1.2+
  2. 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/messages/send", {
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/messages/send'
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/messages/send \
-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

  1. Communication claire : Informez l'utilisateur du canal utilisé et du délai d'expiration
  2. Indicateurs visuels : Montrez le progrès des tentatives de livraison
  3. Options de secours : Toujours offrir la possibilité de saisir manuellement l'OTP
  4. Messages d'erreur utiles : Expliquez pourquoi la livraison a échoué et que faire ensuite
  5. Bouton "Renvoyer" : Permettez facilement de demander un nouveau code
  6. 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 ?

  1. Consultez la documentation :

  2. Examinez les réponses d'erreur :

    • Vérifiez le champ message pour des détails d'erreur spécifiques
    • Consultez le tableau errors pour les problèmes de validation
    • Notez le code d'état HTTP
  3. 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