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.
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:
dependencies:
ligdicash: ^1.0.2
Then install:
Requirements: Dart SDK ≥ 3.4.1 / Flutter ≥ 3.x.
Initialization
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 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.
// 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;
On Flutter, open paymentUrl in a native WebView (webview_flutter package). Never display it in an HTML iframe-based WebView — LigdiCash blocks it.
Detect the return URL (returnUrl / cancelUrl) in the WebView’s onNavigationRequest callback to close it automatically and resume the app flow.
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.
Direct payin
The customer pays directly from your Flutter interface. You must collect their phone number and, depending on the operator, their OTP code.
// 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;
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 for details.
Payout
Send money to a customer — refund, payout, salary.
To the customer’s LigdiCash wallet
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
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'},
);
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.
Status verification
Call getTransaction with the token stored at creation (not the callback token, which is different).
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 |
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.
Error handling
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');
}
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.
Useful links