docs: EnakGame game list, API list and in-game login
integration-enakgame.md was only the flow of a play. It now also has: - §2 the games: Spin is the only one; what each reward_type needs from the client at complete; what to agree on to register a new game. - §3 the endpoints the client calls, in one table. - §5 tokens: with no token, or one the backend refuses, the game shows a customer login (POST /customer-auth/login) and repeats the request once. Standalone mode for a browser without the app finds its game_id by slug. The login errors (304, 429 with locked_until), the attempt limit and the phone formats accepted. A JS helper for all of it. The bridge loses token_expired and token: the game logs the customer in itself. Sections are renumbered. integration-mobile-customer.md: customer phone numbers are 62… (§2), a login section with its errors and the change from 900 to 304 (§2.4), 62… examples, and init carrying the access token. integration-backoffice.md: example responses are the data field, so a list is data.data in a raw response. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
a01e651709
commit
c43baa53e1
@@ -52,13 +52,19 @@ Tidak ada lagi "token". Semua yang dulu token sekarang EnakCoin.
|
||||
- Semua jumlah di request dan response berupa integer.
|
||||
- Belum ada endpoint refresh token: bila token ditolak (§2.2, `entity` `auth_handler`),
|
||||
customer login ulang.
|
||||
- **Nomor HP customer selalu disimpan dan dikembalikan dalam format `62…`** (mis.
|
||||
`6281234561234`). Di request (registrasi, login, kirim ulang OTP, cek nomor, penerima
|
||||
transfer) nomor boleh ditulis `0812…`, `+62 812…`, `62812…`, atau `812…`; backend
|
||||
mengubahnya ke `62…`. Hanya nomor HP Indonesia (`628…`) yang diterima; selain itu
|
||||
ditolak `304` `invalid phone number format`. Pengecualian: nomor penerima transfer
|
||||
yang disamarkan tetap ditampilkan dalam format lokal, `08**-****-1234` (§7.2).
|
||||
|
||||
### 2.1 Registrasi customer
|
||||
|
||||
`POST /api/v1/customer-auth/register/start` menerima `organization_id` (opsional):
|
||||
|
||||
```json
|
||||
{ "phone_number": "0812…", "name": "Budi", "birth_date": "2000-01-31", "organization_id": "648b96a0-1d1d-414e-baee-37e9d6317b4e" }
|
||||
{ "phone_number": "6281234561234", "name": "Budi", "birth_date": "2000-01-31", "organization_id": "648b96a0-1d1d-414e-baee-37e9d6317b4e" }
|
||||
```
|
||||
|
||||
- Customer terdaftar di satu organisasi, dan saldonya berlaku di semua outlet organisasi itu.
|
||||
@@ -78,6 +84,10 @@ Sukses:
|
||||
{ "success": true, "data": { … }, "errors": null }
|
||||
```
|
||||
|
||||
Semua contoh response di dokumen ini adalah isi `data`. Untuk daftar berhalaman, isi
|
||||
itu sendiri berbentuk `{ "data": [ … ], "pagination": { … } }`, jadi array-nya ada di
|
||||
`data.data` pada response mentah.
|
||||
|
||||
Gagal:
|
||||
|
||||
```json
|
||||
@@ -89,7 +99,7 @@ Gagal:
|
||||
| `303`, `310` | 400 | Request tidak lengkap / salah format | Bug di app; tampilkan pesan umum |
|
||||
| `304` | 400 | Ditolak aturan bisnis, **atau token tidak berlaku** bila `entity` = `auth_handler` | Pesan yang ramah per fitur; `cause` berbahasa Inggris, jangan tampilkan mentah. Token: login ulang |
|
||||
| `404` | 404 | Tidak ditemukan, juga untuk data milik customer lain | Tampilkan "tidak ditemukan" |
|
||||
| `429` | 429 | Minta OTP terlalu cepat | Hitung mundur sebelum boleh minta lagi |
|
||||
| `429` | 429 | Minta OTP terlalu cepat, atau terlalu banyak percobaan login (§2.4) | Hitung mundur sebelum boleh minta lagi |
|
||||
| `PIN_NOT_SET` | 403 | Belum punya PIN | Buka alur buat PIN (§6.2) |
|
||||
| `PIN_INVALID` | 400 | PIN salah | §6.5 |
|
||||
| `PIN_LOCKED` | 423 | PIN terkunci | §6.5 |
|
||||
@@ -107,6 +117,25 @@ Endpoint **tukar**, **transfer**, dan **tukar voucher** wajib header `Idempotenc
|
||||
dua kali.
|
||||
- Jangan pakai ulang key untuk transaksi yang berbeda; server menolaknya (`304`).
|
||||
|
||||
### 2.4 Login — `POST /api/v1/customer-auth/login`
|
||||
|
||||
`{ "phone_number": "…", "password": "…" }` → token di `data.data.access_token`.
|
||||
|
||||
| `errors[0].code` | HTTP | Arti | Tampilan |
|
||||
|---|---|---|---|
|
||||
| `304`, `entity` `customer_auth_service` | 400 | Nomor HP tidak terdaftar, password salah, atau pendaftaran belum selesai | "Nomor HP atau password salah." |
|
||||
| `304`, `entity` `request` | 400 | Format nomor HP salah, field kosong | "Periksa nomor HP dan password." |
|
||||
| `429` | 429 | Terlalu banyak percobaan; `data.locked_until` (RFC3339 UTC) | "Terlalu banyak percobaan. Coba lagi pukul {jam}." |
|
||||
| `900` | 500 | Error server | "Terjadi kesalahan, coba lagi" |
|
||||
|
||||
> **Berubah per 9 Okt 2026.** Sebelumnya nomor HP atau password salah dijawab `900`
|
||||
> (HTTP 500) dengan `cause` `invalid password` / `customer not found`. Bila app
|
||||
> menangani login gagal dari HTTP 500 atau teks `cause` itu, ganti ke tabel di atas.
|
||||
|
||||
Setiap nomor HP hanya boleh mencoba login 5 kali dalam 15 menit; login yang berhasil
|
||||
memulai hitungan dari nol. Percobaan ke-6 ditolak `429` sampai 15 menit itu habis, juga
|
||||
bila password-nya benar.
|
||||
|
||||
---
|
||||
|
||||
## 3. Layar yang perlu dibuat
|
||||
@@ -495,7 +524,7 @@ Jumlah yang salah ditolak sebelum PIN dicek, jadi tidak memakan jatah percobaan
|
||||
1. Pilih mata uang (EnakPoint / EnakCoin), isi nomor HP penerima dan jumlah.
|
||||
2. Cek penerima:
|
||||
|
||||
`GET /api/v1/customer/wallet/transfer/recipient?phone=081234561234`
|
||||
`GET /api/v1/customer/wallet/transfer/recipient?phone=6281234561234`
|
||||
|
||||
```json
|
||||
{ "name": "Bu*** Sa***", "phone_number": "08**-****-1234" }
|
||||
@@ -512,7 +541,7 @@ Jumlah yang salah ditolak sebelum PIN dicek, jadi tidak memakan jatah percobaan
|
||||
`POST /api/v1/customer/wallet/transfer` + header `Idempotency-Key`
|
||||
|
||||
```json
|
||||
{ "currency": "POINT", "amount": 120, "recipient_phone": "081234561234", "pin": "482913" }
|
||||
{ "currency": "POINT", "amount": 120, "recipient_phone": "6281234561234", "pin": "482913" }
|
||||
```
|
||||
|
||||
```json
|
||||
@@ -597,7 +626,7 @@ log server game dan riwayat webview.
|
||||
### 8.3 Bridge (sisi aplikasi)
|
||||
|
||||
> **Usulan.** Kontrak ini sama dengan [`integration-enakgame.md`](./integration-enakgame.md)
|
||||
> §2 dan belum diimplementasikan. Sepakati dengan tim EnakGame sebelum mulai.
|
||||
> §4 dan belum diimplementasikan. Sepakati dengan tim EnakGame sebelum mulai.
|
||||
|
||||
- Game → aplikasi: JavaScript channel webview bernama **`EnakGameHost`**; setiap pesan
|
||||
berupa JSON string.
|
||||
@@ -605,11 +634,14 @@ log server game dan riwayat webview.
|
||||
|
||||
| Pesan masuk dari game | Yang dilakukan aplikasi |
|
||||
|---|---|
|
||||
| `{ "type": "ready" }` | Kirim `{ "type": "init", "api_base_url": "<base URL>/api/v1", "token": "<token customer>", "game_id": "<id game yang dibuka>" }` |
|
||||
| `{ "type": "token_expired" }` | Login ulang customer (tidak ada refresh token), lalu kirim `{ "type": "token", "token": "<token baru>" }` |
|
||||
| `{ "type": "ready" }` | Kirim `{ "type": "init", "api_base_url": "<base URL>/api/v1", "token": "<access token customer>", "game_id": "<id game yang dibuka>" }`. Jawab setiap `ready`, termasuk setelah halaman game dimuat ulang. Access token, bukan refresh token (ditolak backend) |
|
||||
| `{ "type": "balance_changed", "coin_balance": 15 }` | Perbarui saldo EnakCoin yang ditampilkan aplikasi |
|
||||
| `{ "type": "close" }` | Tutup webview, muat ulang beranda |
|
||||
|
||||
Bila token kosong atau ditolak backend, game menampilkan layar login akun customer
|
||||
sendiri; aplikasi tidak perlu menangani apa pun, dan token hasil login di game tidak
|
||||
dikirim balik ke aplikasi.
|
||||
|
||||
Abaikan pesan dengan `type` lain. Tombol back Android jangan langsung menutup webview:
|
||||
tampilkan konfirmasi "Keluar dari game? EnakCoin yang sudah dipakai untuk main tidak
|
||||
kembali", lalu tutup. Tidak perlu mengirim pesan ke game.
|
||||
@@ -731,7 +763,9 @@ minta PIN → kirim dengan header `Idempotency-Key`:
|
||||
### 9.3 Voucher saya — `GET /customer/vouchers/redemptions?page=1&limit=20`
|
||||
|
||||
Daftar penukaran customer, terbaru di atas, dengan bentuk item sama seperti response
|
||||
§9.2 (tanpa `point_balance` dan `replayed`), dibungkus `data` + `pagination`.
|
||||
§9.2 (tanpa `point_balance` dan `replayed`). Seperti semua daftar berhalaman di dokumen
|
||||
ini, array-nya ada di `data.data` dan pagination di `data.pagination` di dalam amplop
|
||||
response (§2.2); daftar kosong berupa `[]`.
|
||||
|
||||
| `status` | Tampilan |
|
||||
|---|---|
|
||||
|
||||
Reference in New Issue
Block a user