Passer au contenu principal
Lorsque vous créez une transaction via l’API LigdiCash, vous recevez un token en retour. Ce token n’est pas stable : sa valeur dans le callback diffère de celle obtenue à la création. Si vous vous appuyez sur lui pour identifier vos transactions, vous perdrez le fil entre ce que vous avez initié et ce que vous avez confirmé. La solution est simple : générez votre propre identifiant côté marchand, stockez-le avant d’appeler l’API, et passez-le dans le champ custom_data. LigdiCash vous le renverra intact dans le callback, et l’affichera dans votre dashboard.

Le problème : le token change entre création et callback

À la création d’une transaction, l’API retourne un token :
{
  "response_code": "00",
  "token": "abc123-creation",
  ...
}
Lorsque LigdiCash vous notifie du résultat via le callback, ce même champ contient une valeur différente :
{
  "token": "xyz789-callback",
  ...
}
Les deux tokens désignent la même transaction, mais vous ne pouvez pas les relier directement. Sans identifiant propre à votre système, la réconciliation est impossible.

La solution : injecter votre transaction_id dans custom_data

Le champ custom_data de chaque requête est un objet JSON dont vous définissez librement les clés. C’est ici que vous injectez votre identifiant :
"custom_data": {
  "transaction_id": "COMMANDE-20240815-00042"
}
Dans le callback, LigdiCash transforme cet objet en un tableau. Votre transaction_id y apparaît sous cette forme :
"custom_data": [
  {
    "keyof_customdata": "transaction_id",
    "valueof_customdata": "COMMANDE-20240815-00042",
    "datecreation_customdata": "2026-02-17 06:56:46.55245"
  }
]
Filtrez sur keyof_customdata pour extraire votre valeur — ne vous fiez pas à la position dans le tableau, d’autres entrées peuvent être présentes.

Format du transaction_id

Vous êtes libre de choisir le format qui correspond à votre métier :
FormatExempleUsage typique
Référence commandeORD-2026-00042E-commerce — affiché au client
Code court lisiblePAY-8KXZSupport client, mémorisable
UUID v4f47ac10b-58cc-4372-a567-0e02b2c3d479Systèmes distribués, usage interne
Timestamp + aléatoire1723718400-a3f9File de jobs
ID interneorder_8821Application existante
Si vous affichez le transaction_id à vos clients — par exemple sur le reçu ou dans l’interface de suivi — privilégiez un format court et lisible comme ORD-2026-00042. Cela facilite les échanges avec votre support : le client peut le dicter ou le recopier sans erreur.
Si le transaction_id reste purement interne, un UUID v4 est un bon choix par défaut : garanti unique sans coordination entre serveurs.
Évitez les identifiants purement séquentiels exposés côté client (ex : order_1, order_2) — ils révèlent votre volume de transactions. Préférez un préfixe + compteur non trivial, ou un identifiant aléatoire.

Cycle de vie recommandé

1

Générez le transaction_id

Avant d’appeler l’API, générez votre identifiant unique côté serveur.
2

Persistez-le en base

Enregistrez-le en base de données avec le statut pending avant d’appeler l’API. Si l’appel échoue, vous avez quand même la trace.
3

Passez-le dans custom_data

Incluez-le dans le tableau custom_data de votre requête de création.
4

Stockez le token de création

Conservez également le token retourné par l’API — il sera nécessaire pour appeler l’endpoint confirm lors de la re-vérification du callback.
5

Retrouvez-le dans le callback

Quand LigdiCash vous notifie, extrayez votre transaction_id depuis custom_data et mettez à jour le statut en base.

Retrouver le transaction_id dans le callback

Le payload du callback contient un champ custom_data. Sa forme varie selon le flux (voir Parser custom_data), mais pour un payin il s’agit d’un tableau :
function extractTransactionId(customData) {
  if (!Array.isArray(customData)) return null;
  const entry = customData.find(
    (item) => item.keyof_customdata === "transaction_id"
  );
  return entry?.valueof_customdata ?? null;
}
function extractTransactionId(array $customData): ?string {
    foreach ($customData as $item) {
        if ($item['keyof_customdata'] === 'transaction_id') {
            return $item['valueof_customdata'];
        }
    }
    return null;
}
def extract_transaction_id(custom_data: list) -> str | None:
    for item in custom_data:
        if item.get("keyof_customdata") == "transaction_id":
            return item.get("valueof_customdata")
    return None
Le callback contient aussi un champ transaction_id à la racine du payload. LigdiCash le construit en concaténant les valueof_customdata de toutes les entrées dont la clé contient id (ex : transaction_id, partner_id, event_id…), séparés par ;. Si vous avez injecté plusieurs champs de ce type, cette valeur racine sera un mélange — pas votre identifiant seul. Préférez toujours l’extraction depuis le tableau custom_data.

Visibilité dans le dashboard LigdiCash

Le transaction_id que vous injectez dans custom_data est affiché dans le dashboard LigdiCash, dans le tableau des transactions — aussi bien pour les payin que pour les payout. Cela vous permet de réconcilier visuellement vos transactions sans avoir à interroger votre propre base de données.

Exemple de requête complet

curl -X POST https://app.ligdicash.com/pay/v01/redirect/checkout-invoice/create \
  -H "Apikey: {API_KEY}" \
  -H "Authorization: Bearer {AUTH_TOKEN}" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{
    "commande": {
      "invoice": {
        "items": [{ "name": "Abonnement Pro", "price": 5000, "quantity": 1 }],
        "total_amount": 5000,
        "devise": "XOF",
        "description": "Abonnement Pro — Janvier 2025",
        "customer": "",
        "customer_firstname": "Amadou",
        "customer_lastname": "Diallo",
        "customer_email": "amadou@exemple.com"
      },
      "store": {
        "name": "MonApp",
        "website_url": "https://monapp.com"
      },
      "actions": {
        "cancel_url": "https://monapp.com/paiement/annule",
        "return_url": "https://monapp.com/paiement/succes",
        "callback_url": "https://monapp.com/api/callback/ligdicash"
      },
      "custom_data": {
        "transaction_id": "COMMANDE-20240815-00042"
      }
    }
  }'
import { randomUUID } from "crypto";

const transactionId = randomUUID(); // ou votre propre format

// Persistez transactionId en base avec statut "pending" avant ce fetch
await db.orders.update({ id: orderId, ligdicash_tx_id: transactionId, status: "pending" });

const response = await fetch(
  "https://app.ligdicash.com/pay/v01/redirect/checkout-invoice/create",
  {
    method: "POST",
    headers: {
      Apikey: process.env.LIGDICASH_API_KEY,
      Authorization: `Bearer ${process.env.LIGDICASH_AUTH_TOKEN}`,
      Accept: "application/json",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      commande: {
        invoice: {
          items: [{ name: "Abonnement Pro", price: 5000, quantity: 1 }],
          total_amount: 5000,
          devise: "XOF",
          description: "Abonnement Pro — Janvier 2025",
          customer: "",
          customer_firstname: "Amadou",
          customer_lastname: "Diallo",
          customer_email: "amadou@exemple.com",
        },
        store: { name: "MonApp", website_url: "https://monapp.com" },
        actions: {
          cancel_url: "https://monapp.com/paiement/annule",
          return_url: "https://monapp.com/paiement/succes",
          callback_url: "https://monapp.com/api/callback/ligdicash",
        },
        custom_data: { transaction_id: transactionId },
      },
    }),
  }
);

const data = await response.json();
// Stockez data.token pour la re-vérification ultérieure
await db.orders.update({ ligdicash_tx_id: transactionId, ligdicash_token: data.token });

Pages associées