ChinqIT Verify

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/api/v2/notify
  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

💳 Solde insuffisant

402 Payment Required

Symptômes :

  • Code d'état HTTP 402
  • Message d'erreur "Insufficient balance"
  • Champ messageId présent dans la réponse

Solutions :

  1. Vérifier le solde de votre compte

    • Connectez-vous au tableau de bord ChinqIT Verify
    • Consultez la section solde et historique des transactions
  2. Recharger votre compte

    • Utilisez BPAY pour effectuer un paiement
    • Contactez votre administrateur pour un réapprovisionnement
  3. 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
  4. 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

📱 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/api/v2/notify", {
        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/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

  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

On this page