# Payment API

> Buat dan kelola sesi pembayaran kripto dengan 2328.io Payment API.

Payment API memungkinkan Anda membuat sesi pembayaran, mengarahkan pelanggan ke checkout terhosting, dan melacak status pembayaran.

## Buat pembayaran

Membuat sesi pembayaran dan mengembalikan URL untuk pelanggan melakukan pembayaran.

### Parameter permintaan

| Field | Tipe | Wajib | Deskripsi | Nilai |
|-------|------|----------|-------------|--------|
| `amount` | decimal | ya | Jumlah pembayaran dalam mata uang tersebut, mis. `100.00` |  |
| `currency` | string | ya | Mata uang fiat (USD, EUR, RUB, …) atau kripto (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 | ya | ID pesanan Anda, mis. `ORDER-12345` (hingga 128 karakter) |  |
| `to_currency` | string | tidak | Kripto yang sudah dipilih sebelumnya | `USDT`, `USDC`, `BTC`, `ETH`, `GRAM`, `SOL`, `TRX`, `BNB`, `POL`, `LTC`, `DASH`, `DOGE`, `ZEC`, `XRP`, `XMR` |
| `network` | string | tidak\* | Kode jaringan (wajib jika `to_currency` ditetapkan atau `currency` adalah kripto) | `TRX-TRC20`, `ETH-ERC20`, `BASE`, `BSC-BEP20`, `AVAX-C`, `POL-MATIC`, `TON`, `SOL`, `BTC`, `LTC`, `DASH`, `DOGE`, `ZEC`, `XRP`, `XMR` |
| `url_return` | string | tidak | URL pengalihan setelah pembayaran, mis. `https://your-site.com/return` |  |
| `url_success` | string | tidak | Alternatif untuk `url_return` |  |
| `url_callback` | string | ya | URL untuk notifikasi webhook, mis. `https://your-site.com/webhook` |  |
| `invite_code` | string | tidak | Kode referral |  |
| `fee_split` | decimal | tidak | Bagian biaya merchant yang dibebankan ke pembayar, 0–100 (%). 0 = merchant membayar penuh, 100 = pembayar membayar penuh. Mengganti pengaturan tingkat project. **Contoh: `30`** (pembayar menanggung 30% dari biaya). |  |
| `price_markup` | decimal | tidak | Markup atau diskon pada jumlah faktur, −99 hingga 100 (%). Mengganti pengaturan tingkat project. **Contoh: `5`** (+5%) atau `-10` (diskon 10%). |  |
| `description` | string | tidak | Deskripsi faktur opsional (maks 200 karakter). Ditampilkan kepada pembayar di halaman pembayaran. **Contoh: `Premium plan — Order #12345`**. |  |
| `ttl_seconds` | int | tidak | Masa berlaku faktur dalam detik, dari `300` (5 menit) hingga `86400` (24 jam). Setelah periode ini faktur kedaluwarsa dan tidak dapat dibayar lagi. Default: `3600` (1 jam). **Contoh: `3600`**. |  |

### Respon

```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..."
  }
}
```

- Arahkan pelanggan ke `result.url` untuk menyelesaikan pembayaran.
- `tg_deeplink` — deeplink bot Telegram untuk pembayaran melalui Telegram MiniApp.
- `qr` — kode QR berenkode Base64 (data URI) dari alamat deposit. Hadir saat alamat sudah ditetapkan (saat `network` ditetapkan bersama dengan `to_currency`, atau saat `currency` adalah kripto); jika tidak, `null`.
- `txid`, `payment_amount` — `null` hingga pelanggan membayar. Diisi setelah transaksi terdeteksi on-chain. Dengarkan webhook `payment_status: paid` untuk mengetahui kapan.
- `exchange_rate` — `null` jika konversi belum berlaku (mis. nilai tukar fiat → kripto belum terkunci). Diisi setelah mata uang pembayar dipilih.

> 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)

## Checkout yang dihosting, H2H, dan jumlah crypto yang tepat

Endpoint yang sama mendukung tiga bentuk faktur yang berbeda. Pilih salah satunya dengan sengaja; jangan mencampur semantik jumlah mereka.

### Checkout yang dihosting dengan pilihan pembayar

Kirim `amount`, `currency`, `order_id`, dan `url_callback`, tetapi hilangkan `to_currency` dan `network`. Respon berisi `result.url`; `address`, `qr`, dan kadang-kadang bidang pembayar tetap `null` sampai pembayar memilih arah di halaman yang dihosting.

```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"
}
```

### Faktur H2H alamat langsung

Kirimkan kedua `to_currency` dan `network`. 2328.io membuat faktur blockchain selama panggilan API, jadi respons yang berhasil dapat ditampilkan di dalam checkout Anda tanpa mengarahkan pelanggan.

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

Tampilkan nilai-nilai ini persis seperti dikembalikan:

- `payer_amount` dan `payer_currency` — instruksi pembayaran;
- `network` dan `address` — satu-satunya tujuan untuk faktur ini;
- `qr` — URI data untuk alamat yang sama;
- `expires_at` — batas waktu faktur;
- `url` — fallback host yang berguna ketika checkout kustom tidak dapat diselesaikan.

> **DANGER:** Jangan pernah membuat atau mengganti alamat, menggunakan kembali alamat dari faktur lain, atau menghitung `payer_amount` dari harga publik. Respon API bersifat otoritatif.

### Faktur untuk jumlah kripto yang tepat

Masukkan cryptocurrency ke dalam `currency` ketika faktur itu sendiri dinyatakan dalam crypto:

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

Nilai crypto yang diminta dipertahankan dalam `payer_currency` / `payer_amount`. Layanan ini juga dapat mempertahankan valuasi USD secara internal untuk bidang akuntansi dan nilai tukar; jangan ganti instruksi crypto yang tepat dengan valuasi tersebut. Pertahankan string desimal yang dikembalikan, termasuk presisi di belakang koma.

Untuk cryptocurrency dengan hanya satu jaringan yang didukung, jaringan dapat dipilih secara otomatis. Namun, tetap disarankan untuk secara eksplisit menyertakan `network` untuk integrasi yang deterministik. Untuk aset multi-jaringan seperti stablecoin, selalu kirimkan.

## Idempoten dan percobaan ulang

`order_id` bersifat terbatas pada proyek pedagang yang terautentikasi dan berfungsi sebagai kunci idempoten pembuatan. Jika pembayaran sudah ada, API akan mengembalikan sesi tersebut dengan `state: 0`.

> **WARNING:** Percobaan ulang dengan `order_id` yang sama berarti **not** “perbarui faktur ini.” Perubahan jumlah, mata uang, callback, markup, TTL, atau bidang arah mungkin diabaikan karena sesi yang ada dikembalikan. Simpan permintaan pertama dan tolak percobaan ulang yang bertentangan di aplikasi Anda sendiri.

Algoritma pembuatan yang disarankan:

1. Masukkan percobaan pembayaran lokal Anda dan `order_id` unik ke dalam satu transaksi basis data.
2. Kirim permintaan API yang telah ditandatangani.
3. Simpan `uuid` yang dikembalikan dan respons lengkap.
4. Jika hasil HTTP hilang, coba ulang permintaan yang sama atau query `/v1/payment/info` melalui `order_id`.
5. Jangan pernah membuat pesanan lokal kedua hanya karena permintaan hulu mengalami timeout.

## Kasus tepi pembayaran

| Situasi | Penanganan yang benar |
|-----------|------------------|
| `address` / `qr` adalah `null` | Arah pembayar belum diinisialisasi. Alihkan ke `url`, atau buat faktur H2H baru yang ditentukan dengan benar dengan `order_id` baru. |
| Kesalahan validasi HTTP `400` | Baca `errors` pada tingkat bidang; jangan mencoba ulang input yang tidak diubah. |
| HTTP `429` | Coba lagi dengan backoff eksponensial yang bervariasi dan pertahankan `order_id` yang sama. |
| HTTP `503` / `direction_disabled` | Segarkan `/v1/directions`; sembunyikan arah untuk sementara atau coba lagi nanti. |
| Waktu permintaan klien habis | Anggap hasil sebagai tidak diketahui. Tanyakan dengan `order_id` sebelum membuat yang lain. |
| `underpaid_check` | Simpan peristiwa sebagian dan tunggu isi ulang atau status selanjutnya. Jangan mengkredit dua kali ketika lebih banyak txid tiba. |
| `underpaid` | Keadaan kekurangan pembayaran akhir. Terapkan kebijakan pemenuhan/tinjauan manual yang telah dikonfigurasikan pada jumlah yang sebenarnya dikreditkan. |
| `overpaid` | Pembayaran berhasil dengan dana berlebih. Penuhi secara idempoten dan simpan jumlah yang sebenarnya untuk rekonsiliasi/kebijakan pengembalian. |
| `aml_lock` | Jangan memenuhi atau melepaskan dana secara otomatis; alihkan ke alur kerja kepatuhan/dukungan. |
| `cancel` | Faktur telah kadaluwarsa atau dibatalkan. Jangan menyimpulkan bahwa transfer on-chain terlambat tidak mungkin; rekonsiliasikan setiap peristiwa berikutnya dengan dukungan. |

URL pengembalian browser hanya untuk navigasi. Seorang pelanggan bisa membukanya tanpa membayar, menutupnya setelah membayar, atau memutarnya kembali nanti. Hanya status API/webhook yang terverifikasi yang dapat menyelesaikan pesanan pedagang.

## Info pembayaran

Dapatkan status pembayaran saat ini berdasarkan `uuid` atau `order_id`.

### Parameter permintaan

| Field | Tipe | Wajib | Deskripsi | Nilai |
|-------|------|----------|-------------|--------|
| `uuid` | string | ya\* | UUID pembayaran (dari `result.uuid` saat pembuatan) |  |
| `order_id` | string | ya\* | ID pesanan Anda |  |

> **INFO:** Setidaknya salah satu dari `uuid` atau `order_id` wajib diisi.

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

## Daftar pembayaran

Dapatkan daftar semua pembayaran dengan filter dan paginasi.

### Parameter permintaan

| Field | Tipe | Wajib | Deskripsi | Nilai |
|-------|------|----------|-------------|--------|
| `status` | string | tidak | Filter berdasarkan status pembayaran (lihat [References](/docs/references)) | `pending`, `check`, `paid`, `underpaid_check`, `underpaid`, `overpaid`, `cancel` |
| `date_from` | date | tidak | Tanggal mulai (YYYY-MM-DD), mis. `2026-01-01` |  |
| `date_to` | date | tidak | Tanggal akhir (YYYY-MM-DD), mis. `2026-01-31` |  |
| `page` | int | tidak | Nomor halaman, default `1` |  |
| `per_page` | int | tidak | Item per halaman, default `15`, maks `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)