# ZYREX SHOP — Paket integrasi reseller

Isi: client Python/PHP/Node.js, koleksi Postman, OpenAPI 3.0.3, daftar error, dan JSON request contoh. Tidak ada key pribadi dalam paket. Versi panduan: revisi 14.

## Mulai dengan cek saldo

1. Buat API Key melalui /api-reseller. Simpan key lengkap saat pertama ditampilkan.
2. Isi environment pada backend. Jangan menyimpan secret ke frontend atau repository publik.

```sh
export ZYREX_API_URL='https://DOMAIN-TOKO/api/v1'
export ZYREX_API_KEY='API_KEY_KAMU'
```

3. Pilih client. Perintah default/GET hanya membaca saldo, bukan membeli.

```sh
# Python 3.9+ dan requests
python -m pip install requests
python zyrex_client.py GET /balance

# PHP 8+ dan ekstensi cURL
php zyrex_client.php GET /balance

# Node.js 18+, built-in fetch
node zyrex_client.mjs GET /balance
```

Respons client berbentuk `{ "http_status": 200, "body": { ...respons API... } }`. Wrapper http_status adalah milik contoh client, bukan field respons API asli. Periksa keduanya; HTTP 202 bukan kegagalan final. Client tidak mengulang pembelian otomatis dan tidak membuat Idempotency-Key baru otomatis.

## Katalog dan alur server

Path relatif pada client:

- GET /services: ringkasan 5 server.
- GET /services?server=1: layanan SERVER 1; selanjutnya /countries?server=1&service_id=SERVICE_ID&provider=provider_1, lalu /offers?server=1&service_id=SERVICE_ID&country_code=COUNTRY_CODE&provider=provider_1.
- SERVER 2/4/5: /countries?server=2, /services?server=2&country_id=COUNTRY_ID, /offers?server=2&country_id=COUNTRY_ID&service_id=SERVICE_ID. Ganti server sesuai pilihan. quote_id berlaku 90 detik dan terikat akun/server/negara/layanan.
- SERVER 3: /services?server=3, /countries?server=3, /offers?server=3&country_id=COUNTRY_ID&service_id=SERVICE_ID. Pilih product_id dan salin quoted_price.

Quote/offer antarserver tidak dapat dipertukarkan. Semua price memakai rupiah. SERVER 1/3 memberi quoted_price terpisah untuk validasi harga; jangan menggantinya dengan price jual.

## Membeli secara eksplisit

Simpan satu Idempotency-Key unik 16–128 karakter bersama payload dan pesanan di database aplikasi kamu sebelum mengirim request. UUID boleh digunakan; buat sekali, contoh `python -c "import uuid; print(uuid.uuid4())"`, lalu simpan hasilnya. Jangan menjalankan generator ini lagi untuk retry order yang sama. Key yang sama dipakai untuk retry permintaan yang sama. Jangan membuat key berbeda hanya karena timeout.

Isi request.json menggunakan ID terbaru dari katalog. Template request-server2.example.json hanya placeholder. Contoh SERVER 1:

```json
{"server":1,"service_id":"SERVICE_ID","country_code":"COUNTRY_CODE","provider":"provider_1","number_id":"OFFER_ID","quoted_price":1800}
```

1800 hanya ilustrasi; salin nilai sebenarnya dari offer. SERVER 3:

```json
{"server":3,"service_id":"SERVICE_ID","country_id":"COUNTRY_ID","product_id":"PRODUCT_ID","quoted_price":1800}
```

SERVER 2/4/5:

```json
{"server":2,"service_id":"SERVICE_ID","country_id":"COUNTRY_ID","quote_id":"QUOTE_ID"}
```

Kirim dengan salah satu client:

```sh
python zyrex_client.py POST /order request.json ID_KEY_YANG_DISIMPAN
php zyrex_client.php POST /order request.json ID_KEY_YANG_DISIMPAN
node zyrex_client.mjs POST /order request.json ID_KEY_YANG_DISIMPAN
```

Jangan menjalankan ketiga perintah untuk pembelian berbeda tanpa meninjau hasil; pilih bahasa integrasi kamu. Simpan order_id yang dikembalikan. Bila menggunakan key/payload sama, pengulangan order tersimpan tidak membeli lagi.

## Status dan pembatalan

```sh
python zyrex_client.py GET /order/ORDER_ID
python zyrex_client.py POST /order/ORDER_ID/cancel
```

Path sama berlaku untuk client PHP/Node.js. Poll 5–10 detik, hentikan saat kode diterima atau status terminal, dan beri batas waktu aplikasi. Minimal pembatalan 3 menit sejak order dibuat. Kode sudah masuk tidak dapat dibatalkan untuk refund. Refund mengikuti konfirmasi server dan transaksi, bukan hanya timer lokal.

Jika HTTP 202 tanpa order_id, simpan Idempotency-Key atau reservation_ref, ulangi request asli dengan key yang sama atau hubungi Admin. Jangan poll /order/null. Timeout, 500, 502 atau 503 pada POST bisa berarti hasil belum pasti. Jangan membuat pembelian pengganti sampai status jelas.

## SMM

GET /smm/services menyediakan id, min, max, price_per_1000 dan requires_comments. POST /smm/order membutuhkan service_id, target, quantity dan Idempotency-Key. Jika requires_comments=true, kirim comments berisi satu komentar per baris; jumlah mengikuti baris. Periksa status dengan GET /smm/order/ORDER_ID. Template request-smm.example.json adalah placeholder. Refill belum tersedia.

## Postman

Impor postman_collection.json. Isi variabel base_url dan api_key secara lokal, lalu kirim Cek saldo. Isi variabel server/service/negara/offer dari katalog. idempotency_key sengaja kosong saat impor; isi satu key tetap untuk satu order dan seluruh retry-nya. Salin order_id setelah membeli untuk cek status/pembatalan. Tidak ada script yang otomatis membeli, memilih offer, atau mengganti idempotency_key. Jangan membagikan export yang berisi key pribadi.

## OpenAPI

Impor openapi.json ke tool yang mendukung OpenAPI 3.0.3. Default servers.url adalah /api/v1. Ganti ke https://DOMAIN-TOKO/api/v1 bila tool membutuhkan URL absolut. Skema request menjelaskan syarat field per server; tidak semua field wajib pada semua server.

## Batas dan masalah umum

- 20 request pembelian/menit (OTP dan SMM berbagi bucket), 180 request lain/menit per key.
- HTTP 401: periksa key aktif; HTTP 403: role tidak diberi akses. Staff tidak dapat memakai API reseller.
- HTTP 429: ikuti detik tunggu dalam message, jangan loop tanpa jeda.
- HTTP 409: baca error.code/message; tidak selalu berarti refund sudah masuk.
- Key aktif tidak menjamin setiap server aktif/stok tersedia. Konfigurasi backend toko tetap diperlukan.
- errors.json berisi daftar kode publik dan tindakan. Alur tertentu mengirim message langsung; tangani juga success/status/pending.
- Tidak ada webhook reseller, API OTP email, endpoint minta OTP ulang, atau refill SMM pada kontrak publik saat ini. Pantau status dengan polling.
- Key pengganti mencabut key aktif sebelumnya. Key penuh tidak dapat ditampilkan kembali setelah kunjungan pertama.
- Gunakan HTTPS di produksi. Client tidak mengikuti redirect untuk request API.

## Meminta bantuan

WhatsApp Admin: https://wa.me/6285167371026. Kirim ID user, server, endpoint, waktu, status HTTP, kode error, order_id/reservation_ref. Jangan kirim API key. Uji paket pada backend lokal terlebih dahulu. Contoh memakai ID placeholder dan tidak menjanjikan keberhasilan transaksi langsung.


## Harga promo OTP
Offer menyediakan `price` (harga akhir rupiah), `original_price`, `discounted`,
`discount_amount`, `promotion_title`, `promotion_expires_at` (Unix timestamp).
Tampilkan badge Diskon dan coret original_price bila discounted=true. Jangan
mengurangi diskon lagi dari price. Untuk Server 1/3, kirim expected_price=price
dalam body order bila ingin menolak perubahan harga/promo (HTTP 409 price_changed).
quoted_price tetap disalin apa adanya sebagai validasi harga dasar. Server 2/4/5
mengikat harga dengan quote_id; jika harga naik setelah promo berakhir, ambil quote
baru. Refund mengikuti nominal yang dibayar.
