lomi.

Bonnes pratiques de sécurité

Mettre en œuvre une sécurité solide est indispensable lorsque vous traitez des paiements et intégrez des API tierces comme lomi.. Suivez ces recommandations pour une intégration sécurisée.

Authentification API

Sécurité des clés API

  1. Stockage sécurisé : ne jamais coder en dur les clés API (LOMI_API_KEY) ni les commiter dans le dépôt. Utilisez des variables d’environnement ou un gestionnaire de secrets.

    import { LomiSDK } from '@lomi./sdk';
    
    // Ne pas coder la clé en dur
    const lomi = new LomiSDK({
      apiKey: process.env.LOMI_API_KEY, // Chargée depuis l’environnement
    });
  2. Rotation des clés : faites tourner vos clés API régulièrement via le Dashboard lomi.. En cas de compromission, révoquez-la immédiatement et régénérez-en une nouvelle.

  3. Séparation des environnements : utilisez strictement les clés Test (lomi_sk_test_...) pour le développement et les tests, et les clés Live (lomi_sk_live_...) uniquement en production.

  4. Contrôle d’accès : limitez l’accès aux clés API au sein de votre organisation et de votre infra aux seuls systèmes et personnes qui en ont besoin.

Sécurité des requêtes

Exigences TLS

Toute communication avec l’API lomi. doit passer par HTTPS (TLS 1.2 ou supérieur) pour chiffrer les données en transit. Vérifiez que vos clients HTTP imposent TLS.

import axios from 'axios';

const LOMI_API_BASE_URL = 'https://api.lomi.africa'; // Toujours HTTPS

const apiClient = axios.create({
  baseURL: LOMI_API_BASE_URL,
  headers: {
    Authorization: `Bearer ${process.env.LOMI_API_KEY}`,
    'Content-Type': 'application/json',
  },
});

Validation des requêtes

Validez les données côté serveur avant de les envoyer à l’API lomi..

  1. Assainissement des entrées : nettoyez les entrées utilisateur pour limiter les risques d’injection (lomi. valide aussi côté API ; la défense en profondeur reste recommandée).

    function sanitizeAmount(input: any): number | null {
      const num = Number(input);
      // Entier positif (adapter si décimales nécessaires)
      return Number.isInteger(num) && num > 0 ? num : null;
    }
    
    function sanitizePhoneNumber(phone: string | undefined): string | null {
      // Exemple : retirer les non-chiffres, vérifier la longueur (adapter au format)
      const digits = phone?.replace(/\D/g, '');
      return digits && digits.length >= 8 ? digits : null; // Ajuster le seuil
    }
  2. Validation par schéma : utilisez Zod, Joi ou équivalent pour valider structure et types avant l’appel API.

    import { z } from 'zod';
    
    const CheckoutSessionInputSchema = z.object({
      amount: z.number().positive('Amount must be positive'),
      currency_code: z.enum(['XOF']), // Ajuster les devises autorisées
      merchant_id: z.string().uuid('Invalid merchant ID'),
      success_url: z.string().url('Invalid success URL'),
      cancel_url: z.string().url('Invalid cancel URL'),
      // Autres champs...
    });
    
    function validateCheckoutRequest(data: unknown) {
      return CheckoutSessionInputSchema.safeParse(data);
    }

Sécurité des webhooks

Voir Configurer les webhooks et Traiter les webhooks pour le détail.

Vérification de signature

Vérifiez toujours l’en-tête X-Lomi-Signature des requêtes entrantes avec le Signing Secret (LOMI_WEBHOOK_SECRET) propre à votre point de terminaison. Cela empêche l’envoi d’événements malveillants ou falsifiés.

import crypto from 'crypto';
import express from 'express';

const LOMI_WEBHOOK_SECRET = process.env.LOMI_WEBHOOK_SECRET;

// Utiliser express.raw() sur la route webhook
// app.post('/your-webhook-endpoint', express.raw({ type: 'application/json' }), (req, res) => { ... });

function verifyWebhookSignature(
  rawBody: Buffer,
  signatureHeader: string | undefined,
  secret: string,
): boolean {
  if (!rawBody || !signatureHeader || !secret) {
    return false;
  }
  try {
    const hmac = crypto
      .createHmac('sha256', secret)
      .update(rawBody)
      .digest('hex');

    return crypto.timingSafeEqual(
      Buffer.from(signatureHeader),
      Buffer.from(hmac),
    );
  } catch (error) {
    console.error('Signature verification error:', error);
    return false;
  }
}

Bonnes pratiques pour le point de terminaison webhook

  1. HTTPS : uniquement des points de terminaison HTTPS pour recevoir les webhooks.
  2. Contrôle d’accès : si possible, restreignez l’accès (par ex. liste d’IPs ; note : les IPs lomi. peuvent évoluer).
  3. Réponse rapide et traitement asynchrone : répondez tout de suite avec 200 OK et traitez l’événement en arrière-plan pour éviter les timeouts.
  4. Limite de débit : appliquez du rate limiting sur le point de terminaison webhook.
  5. Gestion d’erreurs : en cas d’échec interne du traitement, journalisez, mais renvoyez toujours 200 OK à lomi. si la signature était valide.

Sécurité des données

Données sensibles

  1. Minimalisation : ne collectez et n’envoyez que les données nécessaires via l’API lomi.. Évitez les informations client sensibles superflues.

    // Recommandé : identifiants internes
    const metadata = { order_id: 'internal-order-123' };
    
    // À éviter : PII sauf nécessité avérée et traitement conforme
    // const badMetadata = { user_password: '...', full_address: '...' };
    
    const session = await lomi.checkoutSessions.createCheckoutSession({
      // ... autres paramètres
      metadata: metadata,
    });
  2. Stockage sécurisé : évitez de stocker des détails de paiement sensibles sauf nécessité et conformité (PCI DSS ; lomi. couvre le cœur du traitement conforme). Chiffrez les données au repos et contrôlez strictement les accès.

Journalisation des erreurs

Soyez prudent dans les journaux : ne tracez pas clés API, secrets webhook ou données clients complètes.

// Éviter les données sensibles dans les logs
function logError(error: Error, context?: Record<string, any>) {
  const sanitizedContext = { ...context };
  if (sanitizedContext?.apiKey) sanitizedContext.apiKey = '[REDACTED]';
  if (sanitizedContext?.customerPhone)
    sanitizedContext.customerPhone = '[REDACTED]';
  if (sanitizedContext?.rawBody) sanitizedContext.rawBody = '[REDACTED]';

  console.error('Error occurred:', {
    message: error.message,
    stack: error.stack, // Prudence avec les piles en production
    context: sanitizedContext,
  });
}

Sécurité réseau

Limitation du débit

Mettez en place du rate limiting sur vos propres endpoints qui appellent lomi. pour limiter les abus et les coûts.

import rateLimit from 'express-rate-limit';

const apiLimiter = rateLimit({
  windowMs: 15 * 60 * 1000, // 15 minutes
  max: 100, // 100 requêtes par IP et par fenêtre
  standardHeaders: true,
  legacyHeaders: false,
});

app.use('/api/', apiLimiter);

Délais d’attente

Définissez des timeouts raisonnables pour les appels à l’API lomi. afin d’éviter des blocages infinis.

import axios from 'axios';

const apiClient = axios.create({
  baseURL: 'https://api.lomi.africa',
  timeout: 15000,
  headers: { Authorization: `Bearer ${process.env.LOMI_API_KEY}` },
});

Surveillance et alertes

  1. Suivi d’activité : surveillez l’usage de l’API, les taux de succès des paiements et les erreurs (Datadog, Sentry, Prometheus/Grafana, etc.).
  2. Alertes sur comportements suspects :
    • Forte proportion d’échecs d’appels API ;
    • Échecs répétés de vérification de signature webhook ;
    • Pics ou chutes inattendus du volume de transactions ;
    • Tentatives avec des clés API révoquées.

Pratiques de développement

  1. Sécurité du code :

    • Maintenez SDKs et bibliothèques (notamment crypto) à jour ;
    • Utilisez des linters sécurité (plugins ESLint, etc.) ;
    • Réalisez des revues de code orientées sécurité ;
    • Assainissez toutes les entrées externes.
  2. Séparation des environnements : configurations distinctes (clés API, secrets webhook) pour développement, préproduction et production.

    const config = {
      development: {
        apiUrl: 'https://sandbox.api.lomi.africa',
        apiKey: process.env.LOMI_TEST_API_KEY,
        webhookSecret: process.env.LOMI_TEST_WEBHOOK_SECRET,
      },
      production: {
        apiUrl: 'https://api.lomi.africa',
        apiKey: process.env.LOMI_PROD_API_KEY,
        webhookSecret: process.env.LOMI_PROD_WEBHOOK_SECRET,
      },
    }[process.env.NODE_ENV || 'development'];
    
    const lomi = new LomiSDK({ apiKey: config.apiKey, baseUrl: config.apiUrl });
    const webhookSecret = config.webhookSecret;

Étapes suivantes

Sur cette page