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

# PHP SDK

> Install and use the LigdiCash PHP SDK in your Laravel, Symfony, or vanilla PHP backends.

The LigdiCash PHP SDK installs via Composer and works with any PHP backend. Network calls are synchronous. The SDK uses Guzzle as its HTTP client.

## Installation

```bash theme={null}
composer require ligdicash/ligdicash
```

**Requirements**: PHP ≥ 7.4. Guzzle is installed automatically as a dependency.

## Initialization

```php PHP theme={null}
require_once 'vendor/autoload.php';

$client = new \Ligdicash\Ligdicash([
    "api_key"    => "{API_KEY}",
    "auth_token" => "{AUTH_TOKEN}",
    "platform"   => "live",
]);
```

Get your `api_key` and `auth_token` from the [LigdiCash dashboard](https://dashboard.ligdicash.com) by creating an API project.

***

## Hosted payin

The customer is redirected to the payment page hosted by LigdiCash. This is the recommended flow for online stores.

```php PHP theme={null}
// 1. Create the invoice
$invoice = $client->Invoice([
    "currency"           => "xof",
    "description"        => "Order #ORD-20240512",
    "customer_firstname" => "Amadou",
    "customer_lastname"  => "Ouedraogo",
    "customer_email"     => "amadou@example.com",
    "store_name"         => "MySuperStore",
    "store_website_url"  => "https://mysuperstore.com",
]);

// 2. Add items
$invoice->addItem([
    "name"        => "Kente shirt",
    "description" => "Size M",
    "quantity"    => 2,
    "unit_price"  => 15000,
]);
$invoice->addItem([
    "name"        => "Shipping fee",
    "description" => "",
    "quantity"    => 1,
    "unit_price"  => 1500,
]);

// 3. Start the payment
$response = $invoice->payWithRedirection([
    "return_url"   => "https://mysuperstore.com/order/success",
    "cancel_url"   => "https://mysuperstore.com/order/cancel",
    "callback_url" => "https://backend.mysuperstore.com/ligdicash/callback",
    "custom_data"  => ["transaction_id" => "ORD-20240512"],
]);

// 4. Redirect the customer
$paymentUrl = $response->response_text;
header("Location: $paymentUrl");
exit;
```

<Warning>
  Never open `$paymentUrl` in an iframe — LigdiCash blocks it. Redirect in the same tab, a new tab, or a popup.
</Warning>

<Tip>
  Always leave `customer` empty (or 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 interface. You must collect their phone number and, depending on the operator, their OTP code.

```php PHP theme={null}
// 1. Create the invoice
$invoice = $client->Invoice([
    "currency"           => "xof",
    "description"        => "Order #ORD-20240512",
    "customer_firstname" => "Amadou",
    "customer_lastname"  => "Ouedraogo",
    "customer_email"     => "amadou@example.com",
    "store_name"         => "MySuperStore",
    "store_website_url"  => "https://mysuperstore.com",
]);
$invoice->addItem([
    "name" => "Kente shirt", "description" => "Size M",
    "quantity" => 2, "unit_price" => 15000,
]);

// 2. Start the payment (with OTP provided by the customer)
$response = $invoice->payWithoutRedirection([
    "otp"          => "123456",       // OTP code entered by the customer
    "customer"     => "22670123456",  // Customer phone number, no + or spaces
    "callback_url" => "https://backend.mysuperstore.com/ligdicash/callback",
    "custom_data"  => ["transaction_id" => "ORD-20240512"],
]);

// 3. Store the token for later verification
$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, salary, payout.

### To the customer's LigdiCash wallet

```php PHP theme={null}
$withdrawal = $client->Withdrawal([
    "amount"      => 5000,
    "description" => "Refund for order ORD-20240510",
    "customer"    => "22670123456",
]);

$response = $withdrawal->send([
    "type"         => "client",
    "to_wallet"    => false,  // false = automatic transfer to the linked mobile money account
    "callback_url" => "https://backend.mysuperstore.com/ligdicash/callback-payout",
    "custom_data"  => ["transaction_id" => "REFUND-20240512"],
]);

$token = $response->token;
```

### Directly to mobile money

```php PHP theme={null}
$response = $withdrawal->send([
    "type"         => "merchant",  // Direct payout, no intermediate wallet
    "callback_url" => "https://backend.mysuperstore.com/ligdicash/callback-payout",
    "custom_data"  => ["transaction_id" => "PAY-20240512"],
]);
```

<Note>
  `"type" => "client"` uses `POST /pay/v01/withdrawal/create` (via the LigdiCash wallet). `"type" => "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).

```php PHP theme={null}
$token = "eyJ0eXAiOiJ...";  // Token returned at creation

// Payin
$transaction = $client->getTransaction([
    "token" => $token,
    "type"  => "payin",  // "payin" or "payout"
]);

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

<Note>
  In PHP, the `type` parameter of `getTransaction` accepts `"payin"` or `"payout"` (not `"client_payout"` or `"merchant_payout"` as in the Python and JavaScript SDKs).
</Note>

**Fields available on `$transaction`:**

| Property        | Type     | Description                               |
| --------------- | -------- | ----------------------------------------- |
| `status`        | `string` | `"completed"`, `"pending"`, `"cancelled"` |
| `response_code` | `string` | `"00"` success, `"01"` failure            |
| `amount`        | `int`    | Transaction amount                        |
| `operator_id`   | `string` | Operator identifier                       |
| `operator_name` | `string` | Operator name                             |
| `customer`      | `string` | Customer phone number                     |
| `token`         | `string` | Transaction token                         |
| `custom_data`   | `array`  | Custom data sent at creation              |
| `wiki`          | `array`  | Links to the endpoint's error codes       |

<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

```php PHP theme={null}
try {
    $response = $invoice->payWithRedirection([
        "return_url"   => "https://mysuperstore.com/success",
        "cancel_url"   => "https://mysuperstore.com/cancel",
        "callback_url" => "https://backend.mysuperstore.com/callback",
        "custom_data"  => ["transaction_id" => "ORD-20240512"],
    ]);
} catch (\InvalidArgumentException $e) {
    // Missing or invalid parameter (currency, type, etc.)
    echo $e->getMessage();
} catch (\Exception $e) {
    // Network error or error returned by the API
    echo $e->getMessage();
}
```

<Note>
  Also check `$response->response_code` 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

* [Hosted payin — Introduction](/en/payment-api/hosted-payin/introduction)
* [Direct payin — Authentication modes](/en/payment-api/direct-payin/validation-modes)
* [Payout — Introduction](/en/payment-api/payout/introduction)
* [Callback security](/en/payment-api/callback/security)
* [transaction\_id pattern](/en/concepts/transaction-id-pattern)
