> ## 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.

# Modes de validation

> Les six modes de validation du payin sans redirection : OTP USSD, USSD Push, USSD guidé, OTP SMS, Redirection LigdiCash, Redirection opérateur. Comprendre les flux et adapter votre UX.

Avec le payin sans redirection, c'est l'opérateur qui décide comment le client confirme son paiement. Ce mécanisme s'appelle le **mode de validation**. Il détermine le flux exact que vous devez implémenter côté interface : quand collecter un OTP, quand afficher un message d'attente, quand soumettre une seconde requête, ou quand rediriger le client vers une page externe.

**Ces six modes sont indépendants.** Chaque opérateur en utilise un (parfois deux en cas de fallback). Vous n'implémentez que le mode correspondant à l'opérateur que vous intégrez. Consultez la [page dédiée à chaque opérateur](/api-paiement/payin-sans-redirect/operateurs/orange-burkina) pour savoir quel mode appliquer.

<Note>
  Tous les modes utilisent **le même endpoint** `POST /pay/v01/straight/checkout-invoice/create`. La différence se joue côté UX et flux : OTP à collecter ou non, message d'attente, redirection éventuelle vers une URL retournée dans `response_text`. Ne confondez pas avec le [payin avec redirection](/api-paiement/payin-redirect/introduction) qui utilise un endpoint distinct (`/redirect/...`) et expose une page de paiement LigdiCash multi-opérateurs.
</Note>

## Détail de chaque mode

<Tabs>
  <Tab title="OTP USSD">
    Le client génère lui-même un code OTP en composant un code USSD sur son téléphone, **avant que vous n'appeliez l'API**. Vous collectez le numéro et l'OTP en même temps dans votre formulaire, puis soumettez une seule requête avec les deux.

    **Flux :**

    <Steps>
      <Step title="Le client compose le code USSD">
        Avant de remplir votre formulaire, le client compose le code USSD de son opérateur sur son téléphone (ex. `*144*4*6#` pour Orange Burkina Faso). Un OTP à usage unique s'affiche sur son écran.
      </Step>

      <Step title="Le client saisit ses informations">
        Votre formulaire collecte le numéro de téléphone et l'OTP en même temps.
      </Step>

      <Step title="Vous soumettez la requête API">
        Une seule requête avec le numéro dans `customer` et l'OTP dans `otp`. Aucun second appel nécessaire.
      </Step>

      <Step title="Confirmation par callback">
        LigdiCash vous notifie du résultat via votre `callback_url`.
      </Step>
    </Steps>

    ```mermaid theme={null}
    sequenceDiagram
        actor Client
        participant UI as Votre interface
        participant Backend as Votre backend
        participant LC as LigdiCash

        Client->>Client: Compose le code USSD (*144*4*6# pour Orange BF)
        Client->>Client: Obtient un OTP à usage unique
        Client->>UI: Saisit numéro + OTP dans le formulaire
        UI->>Backend: numéro + OTP
        Backend->>LC: POST /create — customer: numéro, otp: code
        LC-->>Backend: token (transaction pending)
        LC->>Backend: POST /callback_url (résultat final)
    ```

    **UX recommandée :** affichez le code USSD à composer avec des instructions claires avant que le client ne remplisse le formulaire.

    <Note>
      L'OTP généré via USSD a une durée de validité courte. Invitez le client à saisir son OTP immédiatement après l'avoir généré.
    </Note>

    **Opérateurs utilisant ce mode :** Orange Burkina Faso.
  </Tab>

  <Tab title="USSD Push">
    Après votre requête API, l'opérateur envoie directement un écran USSD push sur le téléphone du client. Le client valide avec son code PIN sur cet écran. Vous n'avez pas besoin de re-soumettre de requête.

    **Flux :**

    <Steps>
      <Step title="Le client saisit son numéro">
        Votre formulaire collecte uniquement le numéro de téléphone. Aucun OTP à collecter.
      </Step>

      <Step title="Vous soumettez la requête API">
        Requête avec le numéro dans `customer` et `otp: ""`.
      </Step>

      <Step title="L'opérateur envoie le push USSD">
        Un menu USSD apparaît automatiquement sur le téléphone du client. Il valide le paiement avec son code PIN.
      </Step>

      <Step title="Confirmation par callback">
        LigdiCash vous notifie du résultat via votre `callback_url`.
      </Step>
    </Steps>

    ```mermaid theme={null}
    sequenceDiagram
        actor Client
        participant UI as Votre interface
        participant Backend as Votre backend
        participant LC as LigdiCash

        Client->>UI: Saisit son numéro de téléphone
        UI->>Backend: numéro
        Backend->>LC: POST /create — customer: numéro, otp: ""
        LC-->>Backend: token (transaction pending)
        LC->>Client: Push USSD sur le téléphone du client
        Client->>Client: Valide avec son code PIN
        LC->>Backend: POST /callback_url (résultat final)
    ```

    **UX recommandée :** après la soumission de la requête API, affichez un message demandant au client de valider sur son téléphone. Mettez en place un indicateur d'attente et basculez sur le résultat à la réception du callback (ou via polling sur l'endpoint `confirm`).

    **Opérateurs utilisant ce mode :** Moov Africa Burkina Faso, Moov Africa Bénin, MTN Mobile Money Bénin, Moov Africa Côte d'Ivoire, Vodacom RDC, Airtel RDC, Africell RDC, Airtel Niger, Moov Africa Niger, YAS Togo, Moov Africa Togo.
  </Tab>

  <Tab title="USSD guidé">
    Après votre requête API, l'opérateur envoie un SMS au client contenant les instructions et le code USSD à composer. Le client compose ce code sur son téléphone pour valider. Vous n'avez pas besoin de re-soumettre de requête.

    **Flux :**

    <Steps>
      <Step title="Le client saisit son numéro">
        Votre formulaire collecte uniquement le numéro de téléphone.
      </Step>

      <Step title="Vous soumettez la requête API">
        Requête avec le numéro dans `customer` et `otp: ""`.
      </Step>

      <Step title="L'opérateur envoie un SMS">
        Le client reçoit un SMS contenant les instructions et le code USSD à composer.
      </Step>

      <Step title="Le client compose le USSD">
        Le client suit les instructions du SMS et valide le paiement depuis son menu USSD.
      </Step>

      <Step title="Confirmation par callback">
        LigdiCash vous notifie du résultat via votre `callback_url`.
      </Step>
    </Steps>

    ```mermaid theme={null}
    sequenceDiagram
        actor Client
        participant UI as Votre interface
        participant Backend as Votre backend
        participant LC as LigdiCash

        Client->>UI: Saisit son numéro de téléphone
        UI->>Backend: numéro
        Backend->>LC: POST /create — customer: numéro, otp: ""
        LC-->>Backend: token (transaction pending)
        LC->>Client: SMS avec instructions + code USSD à composer
        Client->>Client: Compose le code USSD reçu par SMS
        LC->>Backend: POST /callback_url (résultat final)
    ```

    **UX recommandée :** après la soumission de la requête API, affichez un message indiquant au client qu'il va recevoir un SMS avec les instructions à suivre.

    **Exemples de SMS reçus par le client :**

    <CodeGroup>
      ```text MTN Côte d'Ivoire theme={null}
      Vous avez recu une demande de debit avec la reference 1692100357.
      Tapez *133# puis choisissez l option retrait pour approuver.
      ```

      ```text Moov Côte d'Ivoire (fallback) theme={null}
      Vous avez une transaction 0000000433 - LIGDICASH_CI en attente.
      Faites *155*15# pour payer.
      ```
    </CodeGroup>

    <Note>
      Ce mode est parfois utilisé en fallback du USSD Push quand le push n'aboutit pas (ex. Moov Africa Burkina Faso, Moov Africa Côte d'Ivoire).
    </Note>

    **Opérateurs utilisant ce mode :** MTN Côte d'Ivoire (principal), Zamani Niger (principal), Moov Africa Burkina Faso (fallback), Moov Africa Côte d'Ivoire (fallback).
  </Tab>

  <Tab title="OTP SMS">
    Après votre première requête API, l'opérateur envoie un code OTP par SMS au client. Le client vous communique ce code, et vous soumettez une seconde requête API avec l'OTP.

    **Flux :**

    <Steps>
      <Step title="Le client saisit son numéro">
        Votre formulaire collecte le numéro de téléphone. Aucun OTP à ce stade.
      </Step>

      <Step title="Première requête API">
        Requête avec le numéro dans `customer` et `otp: ""`. LigdiCash déclenche l'envoi de l'OTP par SMS.
      </Step>

      <Step title="Le client reçoit l'OTP">
        L'opérateur envoie un code OTP par SMS sur le numéro du client.
      </Step>

      <Step title="Le client saisit l'OTP">
        Votre interface affiche un second champ de saisie pour l'OTP reçu par SMS.
      </Step>

      <Step title="Seconde requête API">
        Vous soumettez à nouveau la requête, cette fois avec l'OTP dans le champ `otp`.
      </Step>

      <Step title="Confirmation par callback">
        LigdiCash vous notifie du résultat via votre `callback_url`.
      </Step>
    </Steps>

    ```mermaid theme={null}
    sequenceDiagram
        actor Client
        participant UI as Votre interface
        participant Backend as Votre backend
        participant LC as LigdiCash

        Client->>UI: Saisit son numéro de téléphone
        UI->>Backend: numéro
        Backend->>LC: POST /create — customer: numéro, otp: ""
        LC-->>Backend: token (transaction pending)
        LC->>Client: SMS avec code OTP
        Client->>UI: Saisit le code OTP reçu par SMS
        UI->>Backend: OTP
        Backend->>LC: POST /create — customer: numéro, otp: code
        LC-->>Backend: confirmation
        LC->>Backend: POST /callback_url (résultat final)
    ```

    **UX recommandée :** adoptez un formulaire en deux étapes — d'abord le numéro, puis l'OTP après réception du SMS. Prévoyez un bouton « Renvoyer le code » avec une temporisation.

    <Warning>
      Ce mode nécessite deux appels API distincts. Attendez que le client ait saisi l'OTP reçu par SMS avant d'envoyer la seconde requête.
    </Warning>

    **Opérateurs utilisant ce mode :** Wallet LigdiCash.
  </Tab>

  <Tab title="Redirection LigdiCash">
    Pour certains opérateurs, l'intégration LigdiCash passe actuellement par une **page web LigdiCash dédiée** plutôt que par un traitement direct via l'API. Vous appelez le même endpoint `/straight/checkout-invoice/create` en préremplissant `customer` avec le numéro du client. LigdiCash répond avec une URL de page de paiement où **seul l'opérateur du numéro est proposé** et le numéro est prérempli. Vous redirigez le client vers cette URL — il confirme depuis la page LigdiCash et le paiement procède selon le mode propre à l'opérateur.

    <Warning>
      Le préremplissage de `customer` est **obligatoire** pour ces opérateurs. Sans `customer`, le filtrage par numéro ne fonctionne pas et la page de paiement n'affiche pas le bon opérateur. Ne pas confondre avec les autres modes du payin sans redirection, où `customer` est toujours fourni mais sert simplement à initier la transaction sans filtrage.
    </Warning>

    **Flux :**

    <Steps>
      <Step title="Le client saisit son numéro">
        Votre formulaire collecte uniquement le numéro de téléphone. Aucun OTP à collecter.
      </Step>

      <Step title="Vous soumettez la requête API">
        Requête sur `POST /pay/v01/straight/checkout-invoice/create` avec `customer` rempli avec le numéro du client et `otp: ""`.
      </Step>

      <Step title="LigdiCash retourne une URL de page de paiement">
        La réponse contient le token de transaction et le champ `response_text` rempli avec l'URL de la page de paiement LigdiCash dédiée à cette transaction.
      </Step>

      <Step title="Vous redirigez le client">
        Redirigez le navigateur du client vers l'URL reçue. La page de paiement LigdiCash affiche le numéro prérempli et l'opérateur déjà sélectionné — le client ne peut ni changer de numéro ni d'opérateur.
      </Step>

      <Step title="Confirmation par callback">
        Le client confirme depuis la page LigdiCash et le paiement procède selon le mode propre à l'opérateur (USSD push, OTP, etc.). LigdiCash vous notifie le résultat final via votre `callback_url`.
      </Step>
    </Steps>

    ```mermaid theme={null}
    sequenceDiagram
        actor Client
        participant UI as Votre interface
        participant Backend as Votre backend
        participant LC as LigdiCash
        participant LCWeb as Page LigdiCash

        Client->>UI: Saisit son numéro de téléphone
        UI->>Backend: numéro
        Backend->>LC: POST /straight/create — customer: numéro, otp: ""
        LC-->>Backend: token + response_text (URL page LigdiCash)
        Backend-->>UI: URL page LigdiCash
        UI->>LCWeb: Redirection du client
        Client->>LCWeb: Confirme le paiement (numéro et opérateur préremplis)
        LCWeb-->>LC: Validation
        LC->>Backend: POST /callback_url (résultat final)
    ```

    **UX recommandée :** redirigez immédiatement le client vers l'URL retournée dans `response_text`. Déclenchez en parallèle un état d'attente côté backend et basculez vers la confirmation à la réception du callback.

    <Note>
      Ce mode utilise bien l'endpoint `/straight/checkout-invoice/create` (payin sans redirection). Ne pas confondre avec le [payin avec redirection](/api-paiement/payin-redirect/introduction), qui utilise un endpoint distinct (`/redirect/...`) et expose une page de paiement multi-opérateurs où le client choisit son moyen de paiement.
    </Note>

    **Opérateurs utilisant ce mode :** Orange Money RD Congo, Orange Money Guinée Conakry, MTN Mobile Money Guinée Conakry, Orange Money Sénégal, Wave Sénégal, Free Sénégal.
  </Tab>

  <Tab title="Redirection opérateur">
    Pour certains opérateurs, l'intégration LigdiCash passe par **le portail web de l'opérateur** pour authentifier le client. Après votre requête API, LigdiCash répond avec l'URL d'un portail externe (Orange Money, par exemple). Vous redirigez le client vers cette URL — il s'y authentifie et confirme le paiement. Le résultat final arrive par callback.

    **Flux :**

    <Steps>
      <Step title="Le client saisit son numéro">
        Votre formulaire collecte uniquement le numéro de téléphone. Aucun OTP à collecter.
      </Step>

      <Step title="Vous soumettez la requête API">
        Requête sur `POST /pay/v01/straight/checkout-invoice/create` avec le numéro dans `customer` et `otp: ""`.
      </Step>

      <Step title="LigdiCash retourne une URL de portail">
        La réponse contient le token de transaction et le champ `response_text` rempli avec l'URL du portail de l'opérateur (ex. `https://mpayment.orange-money.com/...`).
      </Step>

      <Step title="Vous redirigez le client">
        Redirigez le navigateur du client vers l'URL reçue. Le client s'authentifie sur le portail de l'opérateur et confirme le paiement.
      </Step>

      <Step title="Confirmation par callback">
        À l'issue du parcours sur le portail, LigdiCash vous notifie du résultat via votre `callback_url`. Le retour navigateur du client peut être asynchrone — fiez-vous au callback, pas au retour utilisateur.
      </Step>
    </Steps>

    ```mermaid theme={null}
    sequenceDiagram
        actor Client
        participant UI as Votre interface
        participant Backend as Votre backend
        participant LC as LigdiCash
        participant Portail as Portail opérateur

        Client->>UI: Saisit son numéro de téléphone
        UI->>Backend: numéro
        Backend->>LC: POST /create — customer: numéro, otp: ""
        LC-->>Backend: token + response_text (URL portail)
        Backend-->>UI: URL portail
        UI->>Portail: Redirection du client
        Client->>Portail: S'authentifie et confirme
        Portail-->>LC: Résultat du paiement
        LC->>Backend: POST /callback_url (résultat final)
    ```

    **Exemple de réponse de création :**

    ```json theme={null}
    {
      "response_code": "00",
      "token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...",
      "response_text": "https://mpayment.orange-money.com/ml/mpayment/abstract/v1nd8lrkjniiezp3gus76kvmlgztvuylkcs2y5kiir6stko13emvuabrv95oaufb",
      "description": "",
      "custom_data": {
        "transaction_id": "59257c61dab04a70a009af019cd34040",
        "logfile": "202605111744086a021568f2037"
      },
      "wiki": "https://client.ligdicash.com/wiki/createInvoice"
    }
    ```

    **UX recommandée :** redirigez immédiatement le client vers l'URL retournée dans `response_text`. Côté backend, déclenchez en parallèle un état d'attente sur la transaction et basculez vers la confirmation à la réception du callback.

    <Warning>
      Le retour navigateur du client après le portail de l'opérateur n'est pas garanti — l'utilisateur peut fermer l'onglet, perdre le réseau, ou ne jamais revenir. **Le callback reste la seule source de vérité**, comme pour les autres modes. Ne validez jamais le paiement uniquement sur le retour du client.
    </Warning>

    <Note>
      Ce mode utilise bien l'endpoint `/straight/checkout-invoice/create` (payin sans redirection), mais le parcours utilisateur inclut une redirection externe. Ne pas confondre avec le [payin avec redirection](/api-paiement/payin-redirect/introduction), qui utilise un endpoint distinct et expose la page de paiement LigdiCash.
    </Note>

    **Opérateurs utilisant ce mode :** Orange Money Côte d'Ivoire, Orange Money Mali.
  </Tab>
</Tabs>

## Récapitulatif

| Mode                      | Requêtes API | OTP collecté                            | Ce que fait le client                                          |
| ------------------------- | ------------ | --------------------------------------- | -------------------------------------------------------------- |
| **OTP USSD**              | 1            | Avant d'appeler l'API (via USSD)        | Compose un USSD, donne l'OTP au marchand                       |
| **USSD Push**             | 1            | Aucun                                   | Valide sur le push USSD reçu                                   |
| **USSD guidé**            | 1            | Aucun                                   | Compose un USSD après réception d'un SMS                       |
| **OTP SMS**               | 2            | Après la première requête API (via SMS) | Reçoit un OTP par SMS, le communique au marchand               |
| **Redirection LigdiCash** | 1            | Aucun                                   | Est redirigé vers une page LigdiCash pré-filtrée et y confirme |
| **Redirection opérateur** | 1            | Aucun                                   | Est redirigé vers le portail de l'opérateur et y confirme      |

Pour connaître le mode de validation de chaque opérateur, consultez sa page dédiée dans la section [Intégration par opérateur](/api-paiement/payin-sans-redirect/operateurs/orange-burkina).
