# API de paiement

> Créez et gérez des sessions de paiement en cryptomonnaie avec l'API de paiement 2328.io.

L'API de paiement vous permet de créer des sessions de paiement, de rediriger les clients vers une page de paiement hébergée et de suivre le statut des paiements.

## Créer un paiement

Crée une session de paiement et renvoie une URL pour que le client puisse payer.

### Paramètres de la requête

| Champ | Type | Requis | Description | Valeurs |
|-------|------|--------|-------------|---------|
| `amount` | decimal | oui | Montant du paiement dans la devise, par ex. `100.00` |  |
| `currency` | string | oui | Devise fiat (USD, EUR, RUB, …) ou cryptomonnaie (USDT, TRX, BTC, …) | `USD`, `EUR`, `RUB`, `KZT`, `UAH`, `UZS`, `USDT`, `USDC`, `BTC`, `ETH`, `GRAM`, `SOL`, `TRX`, `BNB`, `POL`, `LTC`, `DASH`, `DOGE`, `ZEC`, `XRP`, `XMR` |
| `order_id` | string | oui | Votre ID de commande, par ex. `ORDER-12345` (jusqu'à 128 caractères) |  |
| `to_currency` | string | non | Cryptomonnaie présélectionnée | `USDT`, `USDC`, `BTC`, `ETH`, `GRAM`, `SOL`, `TRX`, `BNB`, `POL`, `LTC`, `DASH`, `DOGE`, `ZEC`, `XRP`, `XMR` |
| `network` | string | non\* | Code de réseau (requis si `to_currency` est défini ou si `currency` est une cryptomonnaie) | `TRX-TRC20`, `ETH-ERC20`, `BASE`, `BSC-BEP20`, `AVAX-C`, `POL-MATIC`, `TON`, `SOL`, `BTC`, `LTC`, `DASH`, `DOGE`, `ZEC`, `XRP`, `XMR` |
| `url_return` | string | non | URL de redirection après le paiement, par ex. `https://your-site.com/return` |  |
| `url_success` | string | non | Alternative à `url_return` |  |
| `url_callback` | string | oui | URL pour les notifications webhook, par ex. `https://your-site.com/webhook` |  |
| `invite_code` | string | non | Code parrain |  |
| `fee_split` | decimal | non | Part des frais marchands à la charge du payeur, 0–100 (%). 0 = le marchand paie l'intégralité, 100 = le payeur paie l'intégralité. Surcharge le paramètre du projet. **Exemple : `30`** (le payeur prend en charge 30 % des frais). |  |
| `price_markup` | decimal | non | Majoration ou remise sur le montant de la facture, −99 à 100 (%). Surcharge le paramètre du projet. **Exemple : `5`** (+5 %) ou `-10` (10 % de remise). |  |
| `description` | string | non | Description optionnelle de la facture (max. 200 caractères). Affichée au payeur sur la page de paiement. **Exemple : `Premium plan — Order #12345`**. |  |
| `ttl_seconds` | int | non | Durée de vie de la facture en secondes, de `300` (5 minutes) à `86400` (24 heures). Au-delà, la facture expire et ne peut plus être payée. Valeur par défaut : `3600` (1 heure). **Exemple : `3600`**. |  |

### Réponse

```json
{
  "state": 0,
  "result": {
    "uuid": "abc123-def456-...",
    "order_id": "ORDER-12345",
    "amount": "100.00",
    "currency": "USD",
    "amount_usd": "100.00",
    "exchange_rate": null,
    "url": "https://2328.io/pay/abc123-def456-...",
    "tg_deeplink": "https://t.me/my2328bot?start=pay_abc123-def456-...",
    "expires_at": "2026-01-11T21:00:00Z",
    "created_at": "2026-01-11T20:00:00Z",
    "payer_currency": "USDT",
    "payer_amount": "100.50",
    "network": "TRX-TRC20",
    "address": "TXYZabc123...",
    "payment_status": "check",
    "txid": null,
    "payment_amount": null,
    "qr": "data:image/png;base64,iVBORw0..."
  }
}
```

- Redirigez le client vers `result.url` pour finaliser le paiement.
- `tg_deeplink` — deeplink du bot Telegram pour le paiement via Telegram MiniApp.
- `qr` — QR code encodé en Base64 (data URI) de l'adresse de dépôt. Présent lorsqu'une adresse est déjà attribuée (lorsque `network` est défini avec `to_currency`, ou lorsque `currency` est une cryptomonnaie) ; sinon `null`.
- `txid`, `payment_amount` — `null` jusqu'au paiement du client. Renseignés une fois la transaction détectée on-chain. Écoutez le webhook `payment_status: paid` pour savoir quand.
- `exchange_rate` — `null` si la conversion n'est pas encore applicable (par ex. le taux fiat → crypto n'a pas été verrouillé). Renseigné une fois qu'une devise de paiement est choisie.

> Use your project UUID and the endpoint-appropriate API key from the merchant dashboard.

#### Interactive request: `POST /v1/payment`
  - `amount` (decimal, required)
  - `currency` (enum, required): USD,EUR,RUB,KZT,UAH,UZS,USDT,USDC,BTC,ETH,GRAM,SOL,TRX,BNB,POL,LTC,DASH,DOGE,ZEC,XRP,XMR
  - `order_id` (string, required)
  - `to_currency` (enum): USDT,USDC,BTC,ETH,GRAM,SOL,TRX,BNB,POL,LTC,DASH,DOGE,ZEC,XRP,XMR
  - `network` (enum): TRX-TRC20,ETH-ERC20,BASE,BSC-BEP20,AVAX-C,POL-MATIC,TON,SOL,BTC,LTC,DASH,DOGE,ZEC,XRP,XMR
  - `url_return` (string)
  - `url_success` (string)
  - `url_callback` (string, required)
  - `invite_code` (string)
  - `fee_split` (decimal)
  - `price_markup` (decimal)
  - `description` (string)
  - `ttl_seconds` (integer)

## Caisse hébergée, H2H, et montants exacts en crypto

Le même point de terminaison supporte trois formes distinctes de facture. Choisissez-en une délibérément ; ne mélangez pas leur sémantique de montant.

### Caisse hébergée avec choix du payeur

Envoyez `amount`, `currency`, `order_id`, et `url_callback`, mais omettez `to_currency` et `network`. La réponse contient `result.url` ; `address`, `qr`, et parfois les champs du payeur restent `null` jusqu'à ce que le payeur sélectionne une direction sur la page hébergée.

```json
{
  "amount": "125.00",
  "currency": "EUR",
  "order_id": "ORDER-2026-1042",
  "url_callback": "https://merchant.example/webhooks/2328",
  "url_return": "https://merchant.example/orders/ORDER-2026-1042"
}
```

### Facture H2H à adresse directe

Envoyez à la fois `to_currency` et `network`. 2328.io crée la facture blockchain lors de l'appel API, donc une réponse réussie peut être affichée directement dans votre processus de paiement sans rediriger le client.

```json
{
  "amount": "100.00",
  "currency": "USD",
  "to_currency": "USDT",
  "network": "TRX-TRC20",
  "order_id": "ORDER-2026-1043",
  "url_callback": "https://merchant.example/webhooks/2328"
}
```

Rendez ces valeurs exactement telles que retournées :

- `payer_amount` et `payer_currency` — l'instruction de paiement ;
- `network` et `address` — la seule destination pour cette facture ;
- `qr` — un URI de données pour la même adresse ;
- `expires_at` — la date limite de la facture ;
- `url` — un fallback hébergé utile lorsque le processus de paiement personnalisé ne peut pas être complété.

> **DANGER:** Ne jamais générer ou remplacer une adresse, réutiliser une adresse provenant d'une autre facture, ou calculer `payer_amount` à partir d'un prix public. La réponse de l'API est autoritaire.

### Facture pour un montant exact de crypto

Placez la crypto-monnaie dans `currency` lorsque la facture elle-même est libellée en crypto :

```json
{
  "amount": "25.000000",
  "currency": "USDT",
  "network": "TRX-TRC20",
  "order_id": "ORDER-2026-1044",
  "url_callback": "https://merchant.example/webhooks/2328"
}
```

La valeur crypto demandée est conservée dans `payer_currency` / `payer_amount`. Le service peut également maintenir une valorisation en USD en interne pour la comptabilité et les champs de taux ; ne remplacez pas l'instruction exacte en crypto par cette valorisation. Conservez les chaînes décimales retournées, y compris la précision finale.

Pour une cryptomonnaie ne disposant que d'un seul réseau pris en charge, le réseau peut être sélectionné automatiquement. Il est néanmoins recommandé de fournir `network` explicitement pour une intégration déterministe. Pour les actifs multi-réseaux tels que les stablecoins, envoyez-le toujours.

## Idempotence et réessais

`order_id` est limité au projet marchand authentifié et agit comme la clé d'idempotence de création. Si un paiement existe déjà, l'API renvoie cette session avec `state: 0`.

> **WARNING:** Un réessai avec le même `order_id` fait **not** signifie « mettre à jour cette facture ». Les champs montant, devise, callback, marge, TTL ou direction modifiés peuvent être ignorés car la session existante est renvoyée. Persistez la première requête et rejetez les réessais conflictuels dans votre propre application.

Algorithme de création recommandé :

1. Insérez votre tentative de paiement locale et le `order_id` unique dans une seule transaction de base de données.
2. Envoyez la requête API signée.
3. Persistez le `uuid` retourné et la réponse complète.
4. Si le résultat HTTP est perdu, réessayez la même requête ou interrogez `/v1/payment/info` via `order_id`.
5. Ne créez jamais une deuxième commande locale simplement parce que la requête en amont a expiré.

## Cas limites de paiement

| Situation | Gestion correcte |
|-----------|------------------|
| `address` / `qr` est `null` | La direction du payeur n'a pas été initialisée. Redirigez vers `url`, ou créez une nouvelle facture H2H correctement spécifiée avec un nouveau `order_id`. |
| Erreur de validation HTTP `400` | Lisez le `errors` au niveau du champ ; ne réessayez pas avec des données inchangées. |
| HTTP `429` | Réessayez avec un retour en arrière exponentiel échelonné et conservez le même `order_id`. |
| HTTP `503` / `direction_disabled` | Actualisez `/v1/directions` ; masque temporairement la direction ou réessayez plus tard. |
| Délai d'attente de la requête client | Traitez le résultat comme inconnu. Interrogez par `order_id` avant de créer autre chose. |
| `underpaid_check` | Stockez l'événement partiel et attendez un complément ou un statut ultérieur. Ne créditez pas deux fois lorsque d'autres txids arrivent. |
| `underpaid` | État final de sous-paiement. Appliquez votre politique de réalisation/examen manuel configurée au montant réellement crédité. |
| `overpaid` | Paiement réussi avec des fonds excédentaires. Réalisez de manière idempotente et conservez les montants réels pour la politique de réconciliation/remboursement. |
| `aml_lock` | Ne réalisez pas ou ne libérez pas les fonds automatiquement ; dirigez vers le flux de travail conformité/support. |
| `cancel` | Facture expirée ou annulée. Ne supposez pas qu'un transfert tardif sur la blockchain soit impossible ; réconciliez tout événement ultérieur avec le support. |

L'URL de retour du navigateur est uniquement de navigation. Un client peut l'ouvrir sans payer, la fermer après avoir payé, ou la rejouer plus tard. Seul un état vérifié de l'API/webhook peut régler la commande du commerçant.

## Informations sur le paiement

Récupérez le statut actuel du paiement par `uuid` ou `order_id`.

### Paramètres de la requête

| Champ | Type | Requis | Description | Valeurs |
|-------|------|--------|-------------|---------|
| `uuid` | string | oui\* | UUID du paiement (depuis `result.uuid` à la création) |  |
| `order_id` | string | oui\* | Votre ID de commande |  |

> **INFO:** Au moins l'un des champs `uuid` ou `order_id` est requis.

#### Interactive request: `POST /v1/payment/info`
  - `uuid` (string)
  - `order_id` (string)

## Liste des paiements

Récupérez une liste de tous les paiements avec filtrage et pagination.

### Paramètres de la requête

| Champ | Type | Requis | Description | Valeurs |
|-------|------|--------|-------------|---------|
| `status` | string | non | Filtrer par statut de paiement (voir [References](/docs/references)) | `pending`, `check`, `paid`, `underpaid_check`, `underpaid`, `overpaid`, `cancel` |
| `date_from` | date | non | Date de début (YYYY-MM-DD), par ex. `2026-01-01` |  |
| `date_to` | date | non | Date de fin (YYYY-MM-DD), par ex. `2026-01-31` |  |
| `page` | int | non | Numéro de page, par défaut `1` |  |
| `per_page` | int | non | Éléments par page, par défaut `15`, max. `5000` |  |

#### Interactive request: `POST /v1/payment/list`
  - `status` (enum): pending,check,paid,underpaid_check,underpaid,overpaid,cancel
  - `date_from` (string)
  - `date_to` (string)
  - `page` (integer)
  - `per_page` (integer)