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

# SDK Python

> Installez et utilisez le SDK Python LigdiCash pour vos backends Django, Flask, FastAPI ou scripts serveur.

Le SDK Python LigdiCash expose trois objets principaux — `Invoice`, `Withdrawal` et `get_transaction` — qui couvrent l'ensemble des flux de paiement. Contrairement aux autres SDK, l'initialisation se fait via des variables globales de module, pas via une instance de classe.

## Installation

```bash theme={null}
pip install ligdicash
```

**Prérequis :** Python ≥ 3.0. La dépendance `requests` est installée automatiquement.

## Initialisation

```python Python theme={null}
import ligdicash

ligdicash.api_key   = "{API_KEY}"
ligdicash.auth_token = "{AUTH_TOKEN}"
ligdicash.platform  = "live"
```

Obtenez votre `api_key` et votre `auth_token` depuis le [dashboard LigdiCash](https://dashboard.ligdicash.com) en créant un projet API.

***

## Payin avec redirection

Le client est redirigé vers la page de paiement hébergée par LigdiCash. C'est le flux recommandé pour les boutiques en ligne.

```python Python theme={null}
import ligdicash

# 1. Décrire la facture
invoice = ligdicash.Invoice(
    currency="xof",
    description="Commande #ORD-20240512",
    customer_firstname="Amadou",
    customer_lastname="Ouédraogo",
    customer_email="amadou@exemple.com",
    store_name="MaSuperBoutique",
    store_website_url="https://masuperboutique.com",
)

# 2. Ajouter les articles
invoice.add_item(name="Chemise kente", description="Taille M", quantity=2, unit_price=15000)
invoice.add_item(name="Frais de livraison", description="", quantity=1, unit_price=1500)

# 3. Lancer le paiement
response = invoice.pay_with_redirection(
    return_url="https://masuperboutique.com/commande/succes",
    cancel_url="https://masuperboutique.com/commande/annulation",
    callback_url="https://backend.masuperboutique.com/ligdicash/callback",
    custom_data={"transaction_id": "ORD-20240512"},
)

# 4. Rediriger le client
payment_url = response.response_text
redirect_user(payment_url)
```

<Warning>
  Ne jamais ouvrir `payment_url` dans une iframe — LigdiCash la bloque. Redirigez dans le même onglet, un nouvel onglet, ou un popup. Sur mobile natif, utilisez une WebView.
</Warning>

<Tip>
  Laissez toujours `customer` vide dans le payin avec redirection (c'est le comportement par défaut). Si vous passez un numéro, LigdiCash filtre la page de paiement pour ne montrer que les opérateurs de ce numéro.
</Tip>

***

## Payin sans redirection

Le client paie directement depuis votre interface. Vous devez collecter son numéro de téléphone et, selon l'opérateur, son code OTP.

```python Python theme={null}
import ligdicash

# 1. Décrire la facture (identique au payin avec redirection)
invoice = ligdicash.Invoice(
    currency="xof",
    description="Commande #ORD-20240512",
    customer_firstname="Amadou",
    customer_lastname="Ouédraogo",
    customer_email="amadou@exemple.com",
    store_name="MaSuperBoutique",
    store_website_url="https://masuperboutique.com",
)
invoice.add_item(name="Chemise kente", description="Taille M", quantity=2, unit_price=15000)

# 2. Lancer le paiement (avec OTP fourni par le client)
response = invoice.pay_without_redirection(
    otp="123456",             # Code OTP saisi par le client
    customer="22670123456",   # Numéro du client, sans + ni espaces
    callback_url="https://backend.masuperboutique.com/ligdicash/callback",
    custom_data={"transaction_id": "ORD-20240512"},
)

# 3. Stocker le token pour vérification ultérieure
token = response.token
```

<Note>
  Le mode OTP varie selon l'opérateur. Par exemple, pour un opérateur en mode USSD, le client génère son OTP sur son téléphone **avant** que vous ne soumetttiez. Pour un opérateur en mode approbation (ex. Moov Africa), envoyez `otp=""` — le client approuve directement sur son application. Consultez la [page de l'opérateur](/api-paiement/payin-sans-redirect/introduction) concerné.
</Note>

***

## Payout

Envoyez de l'argent vers un client — remboursement, salaire, gain.

### Vers le wallet LigdiCash du client

```python Python theme={null}
import ligdicash

withdrawal = ligdicash.Withdrawal(
    amount=5000,
    description="Remboursement commande ORD-20240510",
    customer="22670123456",
)

response = withdrawal.send(
    type="client",
    to_wallet=False,   # False = virement automatique vers le mobile money lié
    callback_url="https://backend.masuperboutique.com/ligdicash/callback-payout",
    custom_data={"transaction_id": "REFUND-20240512"},
)

token = response.token
```

### Directement vers le mobile money

```python Python theme={null}
response = withdrawal.send(
    type="merchant",   # Payout direct, sans wallet intermédiaire
    callback_url="https://backend.masuperboutique.com/ligdicash/callback-payout",
    custom_data={"transaction_id": "PAY-20240512"},
)
```

<Note>
  `type="client"` utilise l'endpoint `POST /pay/v01/withdrawal/create` (via wallet LigdiCash). `type="merchant"` utilise `POST /pay/v01/straight/payout` (mobile money direct, plus lent). Voir [Payout — Introduction](/api-paiement/payout/introduction).
</Note>

***

## Vérification de statut

Appelez `get_transaction` avec le token stocké à la **création** (pas le token du callback, qui est différent).

```python Python theme={null}
import ligdicash

token = "eyJ0eXAiOiJ..."   # Token retourné lors de la création

# Payin
transaction = ligdicash.get_transaction(token, "payin")

# Payout client (withdrawal/create)
# transaction = ligdicash.get_transaction(token, "client_payout")

# Payout marchand (straight/payout)
# transaction = ligdicash.get_transaction(token, "merchant_payout")

if transaction.status == "completed":
    # Livrer la commande / valider le paiement
    pass
elif transaction.status == "pending":
    # Paiement en cours — relancer dans quelques secondes
    pass
else:
    # Paiement échoué ou annulé
    pass
```

**Champs disponibles sur `transaction` :**

| Attribut        | Type   | Description                                   |
| --------------- | ------ | --------------------------------------------- |
| `status`        | `str`  | `"completed"`, `"pending"`, `"cancelled"`     |
| `response_code` | `str`  | `"00"` succès, `"01"` échec                   |
| `amount`        | `int`  | Montant de la transaction                     |
| `operator_id`   | `str`  | Identifiant de l'opérateur                    |
| `operator_name` | `str`  | Nom de l'opérateur                            |
| `customer`      | `str`  | Numéro du client                              |
| `token`         | `str`  | Token de la transaction                       |
| `custom_data`   | `dict` | Données personnalisées envoyées à la création |
| `wiki`          | `list` | Liens vers les codes d'erreur de l'endpoint   |

<Warning>
  Ne livrez jamais une commande uniquement sur la base d'un callback entrant. Appelez toujours `get_transaction` avec le token stocké à la création pour confirmer le statut côté serveur LigdiCash. Voir [Sécurisation du callback](/api-paiement/callback/securisation).
</Warning>

***

## Gestion des erreurs

Toutes les erreurs héritent de `ligdicash.LigdicashError` et exposent `.code` et `.message`.

```python Python theme={null}
import ligdicash

try:
    response = invoice.pay_with_redirection(
        return_url="https://masuperboutique.com/succes",
        cancel_url="https://masuperboutique.com/annulation",
        callback_url="https://backend.masuperboutique.com/callback",
        custom_data={"transaction_id": "ORD-20240512"},
    )
except ligdicash.AuthenticationError as e:
    # Clé API ou token d'authentification invalide
    print(e.message)
except ligdicash.MerchantPayinDisabledError as e:
    # La fonctionnalité payin n'est pas activée pour ce projet
    print(e.message)
except ligdicash.InvalidAmountError as e:
    # Montant hors de la plage [20 ; 1 000 000] XOF
    print(e.message)
except ligdicash.LigdicashError as e:
    # Toute autre erreur LigdiCash
    print(f"{e.code}: {e.message}")
```

**Classes d'erreur disponibles :**

| Classe                                | Déclenchée quand                             |
| ------------------------------------- | -------------------------------------------- |
| `AuthenticationError`                 | `api_key` ou `auth_token` invalide           |
| `ApplicationAuthenticationError`      | Application non authentifiée                 |
| `MerchantPayinDisabledError`          | Payin non activé sur le projet               |
| `MerchantPayoutDisabledError`         | Payout non activé sur le projet              |
| `MerchantBalanceLowError`             | Solde marchand insuffisant                   |
| `CustomerDoesNotExistError`           | Client non enregistré sur la plateforme      |
| `InvalidAmountError`                  | Montant hors de la plage \[20 ; 1 000 000]   |
| `InvalidTokenError`                   | Token invalide ou absent                     |
| `InvoiceNotFoundError`                | Facture introuvable                          |
| `TransactionAlreadyExistError`        | Transaction déjà créée                       |
| `RecipientOperatorNotIdentifiedError` | Opérateur du destinataire non identifié      |
| `FeatureNotTestableError`             | Fonctionnalité indisponible en mode `"test"` |

***

## Liens utiles

* [Payin avec redirection — Introduction](/api-paiement/payin-redirect/introduction)
* [Payin sans redirection — Modes d'authentification](/api-paiement/payin-sans-redirect/modes-validation)
* [Payout — Introduction](/api-paiement/payout/introduction)
* [Sécurisation du callback](/api-paiement/callback/securisation)
* [Pattern transaction\_id](/concepts/transaction-id-pattern)
* [Package PyPI ligdicash](https://pypi.org/project/ligdicash/)
