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

# Dart / Flutter SDK

> Install and use the LigdiCash Dart SDK in your Flutter iOS and Android applications.

The LigdiCash Dart SDK is built for Flutter. It uses Dart conventions — named parameters, enums, `Future<>` — and fits naturally into your widgets and services.

## Installation

Add the dependency to your `pubspec.yaml`:

```yaml pubspec.yaml theme={null}
dependencies:
  ligdicash: ^1.0.2
```

Then install:

```bash theme={null}
flutter pub get
```

**Requirements**: Dart SDK ≥ 3.4.1 / Flutter ≥ 3.x.

## Initialization

```dart Dart theme={null}
import 'package:ligdicash/ligdicash.dart';

final client = Ligdicash(
  apikey: '{API_KEY}',
  authToken: '{AUTH_TOKEN}',
  platform: PlatformType.live,
);
```

Get your `apikey` and `authToken` from the [LigdiCash dashboard](https://dashboard.ligdicash.com) by creating an API project. Store them in environment variables, never hardcoded in your Flutter code.

***

## Hosted payin

The customer is redirected to the LigdiCash-hosted payment page inside a WebView. This is the recommended mobile flow.

```dart Dart theme={null}
// 1. Create the invoice
final invoice = client.Invoice(
  currency: 'xof',
  description: 'Order #ORD-20240512',
  customerFirstname: 'Amadou',
  customerLastname: 'Ouedraogo',
  customerEmail: 'amadou@example.com',
  storeName: 'MySuperStore',
  storeWebsiteUrl: 'https://mysuperstore.com',
);

// 2. Add items
invoice.addItem(
  name: 'Kente shirt',
  description: 'Size M',
  quantity: 2,
  unitPrice: 15000,
);
invoice.addItem(
  name: 'Shipping fee',
  description: '',
  quantity: 1,
  unitPrice: 1500,
);

// 3. Start the payment
final response = await invoice.payWithRedirection(
  returnUrl: 'https://mysuperstore.com/order/success',
  cancelUrl: 'https://mysuperstore.com/order/cancel',
  callbackUrl: 'https://backend.mysuperstore.com/ligdicash/callback',
  customData: {'transaction_id': 'ORD-20240512'},
);

// 4. Open the WebView with the payment URL
final paymentUrl = response.responseText;
```

<Warning>
  On Flutter, open `paymentUrl` in a **native WebView** (`webview_flutter` package). Never display it in an HTML iframe-based WebView — LigdiCash blocks it.
</Warning>

<Tip>
  Detect the return URL (`returnUrl` / `cancelUrl`) in the WebView's `onNavigationRequest` callback to close it automatically and resume the app flow.
</Tip>

<Tip>
  Always leave `customer` absent in hosted payin. If you pass a number, LigdiCash filters the payment page to show only the operators tied to that number.
</Tip>

***

## Direct payin

The customer pays directly from your Flutter interface. You must collect their phone number and, depending on the operator, their OTP code.

```dart Dart theme={null}
// 1. Create the invoice
final invoice = client.Invoice(
  currency: 'xof',
  description: 'Order #ORD-20240512',
  customerFirstname: 'Amadou',
  customerLastname: 'Ouedraogo',
  customerEmail: 'amadou@example.com',
  storeName: 'MySuperStore',
  storeWebsiteUrl: 'https://mysuperstore.com',
);
invoice.addItem(
  name: 'Kente shirt',
  description: 'Size M',
  quantity: 2,
  unitPrice: 15000,
);

// 2. Start the payment (with OTP provided by the customer)
final response = await invoice.payWithoutRedirection(
  otp: '123456',            // OTP code entered by the customer
  customer: '22670123456',  // Customer phone number, no + or spaces
  callbackUrl: 'https://backend.mysuperstore.com/ligdicash/callback',
  customData: {'transaction_id': 'ORD-20240512'},
);

// 3. Store the token for later verification
final token = response.token;
```

<Note>
  The OTP mode varies by operator. For example, with a USSD operator, the customer generates the OTP on their phone **before** you submit. For an approval-mode operator (e.g. Moov Africa), send `otp: ''` — the customer approves directly in their app. See the [operator page](/en/payment-api/direct-payin/introduction) for details.
</Note>

***

## Payout

Send money to a customer — refund, payout, salary.

### To the customer's LigdiCash wallet

```dart Dart theme={null}
final withdrawal = client.Withdrawal(
  amount: 5000,
  description: 'Refund for order ORD-20240510',
  customer: '22670123456',
);

final response = await withdrawal.send(
  type: WithdrawalType.client,
  toWallet: false,  // false = automatic transfer to the linked mobile money account
  callbackUrl: 'https://backend.mysuperstore.com/ligdicash/callback-payout',
  customData: {'transaction_id': 'REFUND-20240512'},
);

final token = response.token;
```

### Directly to mobile money

```dart Dart theme={null}
final response = await withdrawal.send(
  type: WithdrawalType.merchant,  // Direct payout, no intermediate wallet
  callbackUrl: 'https://backend.mysuperstore.com/ligdicash/callback-payout',
  customData: {'transaction_id': 'PAY-20240512'},
);
```

<Note>
  `WithdrawalType.client` uses `POST /pay/v01/withdrawal/create` (via the LigdiCash wallet). `WithdrawalType.merchant` uses `POST /pay/v01/straight/payout` (direct mobile money, slower). See [Payout — Introduction](/en/payment-api/payout/introduction).
</Note>

***

## Status verification

Call `getTransaction` with the token stored at **creation** (not the callback token, which is different).

```dart Dart theme={null}
final token = 'eyJ0eXAiOiJ...';  // Token returned at creation

// Payin
final transaction = await client.getTransaction(
  token: token,
  type: TransactionType.payin,
);

// Client payout (withdrawal/create)
// final transaction = await client.getTransaction(
//   token: token,
//   type: TransactionType.clientPayout,
// );

if (transaction.status == 'completed') {
  // Deliver the order / validate the payment
} else if (transaction.status == 'pending') {
  // Payment in progress — retry in a few seconds
} else {
  // Payment failed or cancelled
}
```

**`TransactionType` values:**

| Value                          | Endpoint checked                         |
| ------------------------------ | ---------------------------------------- |
| `TransactionType.payin`        | `GET /redirect/checkout-invoice/confirm` |
| `TransactionType.clientPayout` | `GET /withdrawal/confirm`                |

**Fields available on `transaction`:**

| Property       | Type                   | Description                               |
| -------------- | ---------------------- | ----------------------------------------- |
| `status`       | `String`               | `"completed"`, `"pending"`, `"cancelled"` |
| `responseCode` | `String`               | `"00"` success, `"01"` failure            |
| `amount`       | `double`               | Transaction amount                        |
| `operatorId`   | `String`               | Operator identifier                       |
| `operatorName` | `String`               | Operator name                             |
| `customer`     | `String`               | Customer phone number                     |
| `token`        | `String`               | Transaction token                         |
| `customData`   | `Map<String, dynamic>` | Custom data sent at creation              |

<Warning>
  Never deliver an order solely based on an incoming callback. Always call `getTransaction` with the token stored at creation to confirm the status on the LigdiCash server side. See [Callback security](/en/payment-api/callback/security).
</Warning>

***

## Error handling

```dart Dart theme={null}
try {
  final response = await invoice.payWithRedirection(
    returnUrl: 'https://mysuperstore.com/success',
    cancelUrl: 'https://mysuperstore.com/cancel',
    callbackUrl: 'https://backend.mysuperstore.com/callback',
    customData: {'transaction_id': 'ORD-20240512'},
  );

  if (response.responseCode != '00') {
    // Error returned by the API — read response.wiki
    debugPrint('API error: ${response.responseText}');
  }
} catch (e) {
  // Network error or unexpected exception
  debugPrint('Error: $e');
}
```

<Note>
  Check `response.responseCode` after every call: `"00"` indicates success, `"01"` an error. On error, read `response.wiki` to get the URL with sub-code details.
</Note>

***

## Useful links

* [Guide — Flutter mobile integration](/en/guides/mobile-quickstart)
* [Hosted payin — Mobile integration](/en/payment-api/hosted-payin/mobile-integration)
* [Payout — Introduction](/en/payment-api/payout/introduction)
* [Callback security](/en/payment-api/callback/security)
* [transaction\_id pattern](/en/concepts/transaction-id-pattern)
* [ligdicash-dart GitHub repository](https://github.com/Ligdicash/ligdicash-dart)
