# Cara Pakai Partner API — hub-control (Registrasi Tenant)

Panduan integrasi untuk partner (tim web profile, apps Android, tim lain) yang
mendaftarkan tenant ke hub-control.

Ada **dua cara** — pilih salah satu:
- **Partner API (HMAC)** — bagian 1–6, untuk tim yang punya backend/aplikasi sendiri.
- **Web Registrasi (iframe)** — bagian 7, tanpa coding: tempel form siap pakai di situs Anda.

## 1. Kredensial
Minta ke admin hub-control:
- **API Key** (mis. `p_xxxxxxxxxxxxxxxx`)
- **API Secret** (rahasia — simpan di server, jangan di browser)

## 2. Autentikasi (HMAC-SHA256)
Setiap request menyertakan 3 header:

| Header | Isi |
|---|---|
| `X-Api-Key` | API Key partner |
| `X-Timestamp` | Waktu Unix (detik). Harus dalam ±5 menit dari jam server. |
| `X-Signature` | Tanda tangan HMAC (hex) |

**String yang ditandatangani:**
```
stringToSign = X-Timestamp + "\n" + METHOD + "\n" + PATH + "\n" + body
X-Signature  = HEX( HMAC_SHA256( API_Secret, stringToSign ) )
```
Contoh: `METHOD="POST"`, `PATH="/api/public/register"`, `body` = JSON mentah persis yang dikirim.

## 3. Endpoint

### POST /api/public/register
Body (JSON):

| Field | Wajib | Keterangan |
|---|---|---|
| `email` | ya | Email pemilik (unik) |
| `business_name` | ya | Nama usaha |
| `phone` | — | No. HP |
| `full_name` | — | Nama pemilik |
| `business_field` | — | Bidang usaha |
| `npwp` | — | NPWP |
| `address` | — | Alamat |
| `subdomain` | — | Alamat aplikasi pilihan pendaftar → `{subdomain}.hub.xpanca.com` (mis. `menjala`). 3–30 karakter: huruf kecil, angka, minus; tidak diawali/diakhiri minus. **Unik** — bila sudah dipakai tenant lain, registrasi ditolak (400 "subdomain … sudah dipakai"). Kosong = dibuat otomatis dari nama usaha. |

**Respons sukses (200):**
```json
{ "status": true, "message": "Registrasi diterima. Akun Anda menunggu persetujuan admin.",
  "data": { "tenant_id": 6, "slug": "menjala", "domain": "menjala.hub.xpanca.com" } }
```

### GET /api/public/check-subdomain?name=menjala
Cek ketersediaan sebelum mendaftar (mis. saat pengguna mengetik). Header HMAC sama;
**PATH yang ditandatangani tanpa query string** (`/api/public/check-subdomain`), body kosong.
```json
{ "status": true, "message": "subdomain sudah dipakai, silakan pilih nama lain",
  "data": { "subdomain": "menjala", "domain": "menjala.hub.xpanca.com", "available": false,
            "reason": "subdomain sudah dipakai, silakan pilih nama lain" } }
```
Hasil cek bukan reservasi — nama baru terkunci saat `register` berhasil.

## 4. Contoh — Bash (openssl)
```bash
API_KEY="p_xxxx"; API_SECRET="xxxx"
TS=$(date +%s)
BODY='{"email":"owner@toko.com","business_name":"Toko Budi","phone":"08123456789"}'
STR=$(printf '%s\n%s\n%s\n%s' "$TS" "POST" "/api/public/register" "$BODY")
SIG=$(printf '%s' "$STR" | openssl dgst -sha256 -hmac "$API_SECRET" | awk '{print $NF}')
curl -X POST https://HOST/api/public/register \
  -H "Content-Type: application/json" \
  -H "X-Api-Key: $API_KEY" -H "X-Timestamp: $TS" -H "X-Signature: $SIG" \
  -d "$BODY"
```

## 5. Contoh — Node.js
```js
const crypto = require("crypto");
const API_KEY = "p_xxxx", API_SECRET = "xxxx";
const BASE = "https://HOST", path = "/api/public/register";
const body = JSON.stringify({ email:"owner@toko.com", business_name:"Toko Budi", phone:"08123456789" });
const ts = Math.floor(Date.now()/1000).toString();
const str = ts + "\n" + "POST" + "\n" + path + "\n" + body;
const sig = crypto.createHmac("sha256", API_SECRET).update(str).digest("hex");
const res = await fetch(BASE + path, {
  method: "POST",
  headers: { "Content-Type":"application/json", "X-Api-Key":API_KEY, "X-Timestamp":ts, "X-Signature":sig },
  body
});
console.log(await res.json());
```

## 6. Catatan
- **API Secret hanya di server.** Situs statis (browser) tidak boleh memegang Secret —
  buat backend kecil yang menandatangani request.
- Setelah daftar, tenant berstatus `verified` dan **menunggu persetujuan admin**.
- Endpoint dibatasi rate-limit. Error 401 = tanda tangan/kunci/timestamp tidak valid.

## 7. Alternatif tanpa coding — Web Registrasi (iframe)
Cocok untuk situs yang tidak punya backend (mis. situs statis / WordPress).
Tidak perlu API Key/Secret; pendaftar tetap tercatat sebagai pendaftaran via partner Anda.

1. Kirim **satu domain situs** Anda (mis. `https://tokoanda.com`) ke admin — versi `www.`
   otomatis ikut diizinkan. Form HANYA berjalan di domain itu: situs lain diblokir browser,
   dan link yang dibuka langsung di tab browser ditolak. (1 partner = 1 domain.)
2. Admin memberikan kode iframe berisi link khusus partner Anda, contoh:
```html
<iframe id="hubctl-reg" src="https://HOST/embed/register/e_xxxxxxxxxxxxxxxxxxxxxxxx"
  style="width:100%;max-width:600px;height:760px;border:0"
  title="Daftar Coba Gratis" loading="lazy" referrerpolicy="strict-origin-when-cross-origin"></iframe>
<script>
  window.addEventListener("message", function (e) {
    if (e.origin !== "https://HOST" || !e.data || e.data.source !== "hubctl") return;
    if (e.data.type === "resize") document.getElementById("hubctl-reg").style.height = (e.data.height + 4) + "px";
  });
</script>
```
3. Tempel di halaman situs Anda. Selesai. **Jangan hapus `referrerpolicy`** — dipakai untuk
   memastikan form hanya berjalan di situs Anda.

Form sudah memuat isian **Alamat Aplikasi** (subdomain, mis. `menjala.hub.xpanca.com`)
dengan pengecekan langsung — nama yang sudah dipakai ditolak.

**Kustomisasi** (tambahkan di URL iframe): `color=16a34a` (warna tombol, hex tanpa `#`),
`title=Teks`, `hide_title=1`, `theme=dark`.

**Event `postMessage`** ke halaman Anda: `{ source:"hubctl", type:"ready"|"resize"|"registered"|"completed" }`.
`resize` membawa `height`; `completed` = pendaftaran selesai (mis. untuk analytics). Selalu cek `e.origin`.

Bila link diganti oleh admin (mis. karena disalahgunakan), link lama langsung tidak berlaku —
pasang ulang kode yang baru.
