Passer au contenu principal

Documentation Index

Fetch the complete documentation index at: https://developers.ligdicash.com/llms.txt

Use this file to discover all available pages before exploring further.

Pour chaque événement de transaction, LigdiCash envoie deux requêtes POST à votre callback_url :
  • Une en application/x-www-form-urlencoded
  • Une en application/json
Les deux contiennent exactement les mêmes données. Votre serveur va donc recevoir deux appels pour un seul événement. Sans déduplication, vous risquez de traiter la même transaction deux fois — livrer une commande en double, déclencher deux remboursements, créditer un compte deux fois.

Stratégie de déduplication

La méthode la plus simple consiste à marquer chaque transaction traitée dans votre base de données et à ignorer les appels suivants pour la même transaction.
1

Extraire votre transaction_id

Parsez custom_data pour extraire votre transaction_id via keyof_customdata. Voir Parser custom_data.
2

Vérifier si déjà traité

Avant tout traitement, cherchez si cet identifiant existe déjà dans votre table de transactions traitées.
3

Traiter et marquer atomiquement

Si non traité, effectuez votre traitement et marquez la transaction comme traitée dans la même transaction de base de données. L’atomicité évite les race conditions si les deux requêtes arrivent simultanément.

Implémentation

app.post('/callback', async (req, res) => {
  const entry = req.body.custom_data?.find(
    (item) => item.keyof_customdata === 'transaction_id'
  );
  const transactionId = entry?.valueof_customdata;
  if (!transactionId) return res.sendStatus(400);

  // Insertion avec contrainte d'unicité — échoue si déjà traité
  const inserted = await db.query(
    'INSERT INTO processed_callbacks (transaction_id) VALUES (?) ON CONFLICT DO NOTHING',
    [transactionId]
  );

  if (inserted.rowCount === 0) {
    // Déjà traité — deuxième requête du doublon LigdiCash
    return res.sendStatus(200);
  }

  // Première réception — traitement métier
  await processPayment(transactionId);

  res.sendStatus(200);
});
// Avec une contrainte UNIQUE sur transaction_id en base
try {
    $db->insert('processed_callbacks', ['transaction_id' => $transactionId]);
} catch (UniqueConstraintException $e) {
    // Déjà traité
    http_response_code(200);
    exit;
}

// Première réception — traitement métier
processPayment($transactionId);
La contrainte d’unicité en base de données est plus fiable qu’un simple SELECT suivi d’un INSERT — deux requêtes simultanées peuvent passer le SELECT en même temps avant que l’une des deux n’ait effectué son INSERT.

Pages associées