# DOKUMENTASI INSTALASI CPANEL — JAGUAR SEASON 6 + MIDTRANS

Dokumentasi ini mengikuti struktur aplikasi asli:

- Frontend: HTML/CSS/JavaScript statis di `frontend/jaguarseason6/`
- Backend: Node.js + Express di `backend/`
- Database: PostgreSQL
- Payment gateway: **Midtrans Snap + Payment Notification/Webhook**

Tidak ada perubahan arsitektur menjadi PHP/MySQL dan tidak ada penghapusan halaman/folder asli.

---

## 1. Persyaratan hosting cPanel

Agar seluruh aplikasi berjalan langsung di cPanel, paket hosting harus menyediakan:

1. **Node.js Application / Setup Node.js App / Application Manager**
2. Node.js **18+** (disarankan Node.js 20 LTS jika tersedia)
3. **PostgreSQL Database**
4. SSL/HTTPS aktif pada domain frontend dan domain/subdomain backend
5. Terminal/SSH cPanel atau menu untuk menjalankan `npm install` dan command Node.js

> Jika hosting cPanel hanya mendukung PHP + MySQL dan tidak menyediakan Node.js/PostgreSQL, frontend tetap bisa di-host di cPanel tetapi backend aplikasi ini tidak dapat dijalankan tanpa konversi arsitektur. Konversi itu sengaja tidak dilakukan karena permintaan Anda adalah mempertahankan struktur asli.

---

## 2. Rekomendasi susunan domain

Contoh yang paling rapi:

- Frontend: `https://domainanda.com`
- Backend API: `https://api.domainanda.com`
- Endpoint API: `https://api.domainanda.com/api`
- Webhook Midtrans: `https://api.domainanda.com/api/midtrans/webhook`

Gunakan HTTPS. Webhook Midtrans harus dapat diakses dari internet tanpa login, tanpa VPN, dan jangan diarahkan/redirect ke URL lain.

---

## 3. Upload file ke cPanel

### Frontend

1. Masuk **cPanel → File Manager**.
2. Buka folder `public_html/`.
3. Upload isi folder:

   `frontend/jaguarseason6/`

   ke dalam `public_html/`.
4. Hasil akhirnya sebaiknya seperti:

```text
public_html/
├── index.html
├── checkout.html
├── voting-berhasil.html
├── css/
├── js/
├── admin/
└── ...
```

Jangan upload folder `jaguarseason6` sebagai satu tingkat tambahan jika Anda ingin situs langsung terbuka dari `https://domainanda.com/`.

### Backend

Upload folder `backend/` ke lokasi di luar `public_html`, misalnya:

```text
/home/CPANELUSER/jaguar-backend/
```

Isi folder tersebut harus memiliki:

```text
package.json
package-lock.json
src/
sql/
.env
```

Backend sebaiknya tidak diletakkan sebagai file publik di `public_html`.

---

## 4. Buat PostgreSQL di cPanel

Di cPanel buka menu **PostgreSQL Databases** lalu:

1. Buat database, misalnya `jaguar`.
2. Buat user database, misalnya `jaguaruser`.
3. Buat password database yang kuat.
4. Tambahkan user ke database dan berikan semua privilege yang diperlukan.

Pada banyak cPanel nama akhirnya otomatis memakai prefix akun, misalnya:

```text
Database : CPANELUSER_jaguar
User     : CPANELUSER_jaguaruser
Host     : 127.0.0.1
Port     : 5432
```

Bentuk `DATABASE_URL`:

```text
postgres://CPANELUSER_jaguaruser:PASSWORD@127.0.0.1:5432/CPANELUSER_jaguar
```

Jika password memiliki karakter khusus seperti `@`, `:`, `/`, `?`, `#`, `[`, atau `]`, URL-encode bagian password terlebih dahulu.

---

## 5. Buat file `.env` backend

Di folder backend, salin `.env.cpanel.example` menjadi `.env`.

Contoh:

```env
DATABASE_URL=postgres://CPANELUSER_jaguaruser:PASSWORD@127.0.0.1:5432/CPANELUSER_jaguar
JWT_SECRET=random_string_panjang_dan_rahasia

SEED_ADMIN_EMAIL=admin@domainanda.com
SEED_ADMIN_PASSWORD=password_admin_yang_kuat

MIDTRANS_SERVER_KEY=SB-Mid-server-xxxxxxxxxxxxxxxxxxxxxxxx
MIDTRANS_CLIENT_KEY=SB-Mid-client-xxxxxxxxxxxxxxxxxxxxxxxx
MIDTRANS_IS_PRODUCTION=false

FRONTEND_ORIGIN=https://domainanda.com,https://www.domainanda.com
```

### Penting

- **Server Key Midtrans hanya boleh berada di backend**.
- Jangan memasukkan `MIDTRANS_SERVER_KEY` ke JavaScript frontend.
- `.env` jangan dibuat dapat diunduh dari web.

---

## 6. Buat aplikasi Node.js di cPanel

Nama menu berbeda tergantung provider, biasanya:

- **Setup Node.js App**
- **Application Manager**
- **Node.js Selector**

Contoh konfigurasi:

```text
Node.js version  : 18 atau 20
Application mode : Production
Application root : jaguar-backend
Application URL  : https://api.domainanda.com
Startup file     : src/server.js
```

Jika cPanel memiliki form Environment Variables, masukkan semua variabel dari `.env` di sana. Jika tidak, aplikasi ini sudah memakai `dotenv`, jadi file `.env` di application root dapat digunakan.

Setelah aplikasi dibuat, buka terminal yang disediakan cPanel atau aktifkan virtual environment Node.js yang ditampilkan oleh panel.

---

## 7. Install dependency Node.js

Masuk ke application root:

```bash
cd ~/jaguar-backend
npm ci --omit=dev
```

Jika `npm ci` tidak dapat digunakan oleh hosting Anda:

```bash
npm install --omit=dev
```

Pastikan tidak ada error pada package `pg`, `express`, dan `midtrans-client`.

---

## 8. Buat tabel database + admin pertama

Jalankan:

```bash
cd ~/jaguar-backend
npm run migrate
```

Command tersebut akan:

- menjalankan `sql/schema.sql`;
- membuat tabel yang belum ada;
- membuat admin pertama jika database belum memiliki admin dan `SEED_ADMIN_PASSWORD` sudah diisi.

Setelah berhasil, restart Node.js App dari cPanel.

> `npm run seed` hanya diperlukan jika Anda memang ingin memasukkan data contoh/seed yang disediakan proyek. Untuk instalasi production baru, jangan menjalankannya tanpa memeriksa isi seed terlebih dahulu.

---

## 9. Tes backend

Buka:

```text
https://api.domainanda.com/api/health
```

Respons normal:

```json
{"ok":true,"time":"..."}
```

Jika muncul 503/500:

1. cek log Node.js/Passenger di cPanel;
2. cek `DATABASE_URL`;
3. cek dependency sudah ter-install;
4. restart aplikasi Node.js;
5. pastikan domain/subdomain API sudah mengarah ke aplikasi Node.js yang benar.

---

## 10. Sambungkan frontend ke backend

Edit:

```text
public_html/js/config.js
```

### Sandbox Midtrans

```js
const API_BASE_URL = "https://api.domainanda.com/api";
const MIDTRANS_CLIENT_KEY = "SB-Mid-client-xxxxxxxxxxxxxxxxxxxxxxxx";
const MIDTRANS_SNAP_URL = "https://app.sandbox.midtrans.com/snap/snap.js";
```

`MIDTRANS_CLIENT_KEY` memang digunakan di browser. Jangan pernah menaruh Server Key di file ini.

Setelah menyimpan, lakukan hard refresh / clear cache browser atau cache CDN jika memakai Cloudflare.

---

## 11. Ambil API Key Midtrans

Gunakan **Sandbox** dahulu.

Di dashboard Midtrans buka bagian Access Keys/Credentials dan ambil:

- Server Key Sandbox
- Client Key Sandbox

Masukkan:

### Backend `.env`

```env
MIDTRANS_SERVER_KEY=SB-Mid-server-xxxxxxxxxxxxxxxxxxxxxxxx
MIDTRANS_CLIENT_KEY=SB-Mid-client-xxxxxxxxxxxxxxxxxxxxxxxx
MIDTRANS_IS_PRODUCTION=false
```

### Frontend `js/config.js`

```js
const MIDTRANS_CLIENT_KEY = "SB-Mid-client-xxxxxxxxxxxxxxxxxxxxxxxx";
const MIDTRANS_SNAP_URL = "https://app.sandbox.midtrans.com/snap/snap.js";
```

Restart Node.js App sesudah mengubah `.env`.

---

## 12. Set Payment Notification/Webhook Midtrans

Di dashboard Midtrans, set **Payment Notification URL** ke:

```text
https://api.domainanda.com/api/midtrans/webhook
```

Webhook ini menerima status transaksi dari Midtrans dan backend akan:

1. memverifikasi signature Midtrans;
2. memastikan `order_id` ada di database;
3. memastikan nominal Midtrans sama dengan nominal invoice lokal;
4. mengubah status transaksi;
5. menambahkan suara hanya setelah status pembayaran valid;
6. mencegah suara dihitung dua kali jika Midtrans mengirim notifikasi ulang.

Webhook **bukan** halaman yang perlu dibuka pengguna.

### Syarat webhook

- gunakan HTTPS;
- gunakan domain, bukan IP langsung;
- gunakan port standar HTTPS/443;
- tidak boleh dilindungi login/basic auth;
- jangan redirect URL webhook;
- endpoint harus bisa diakses dari internet.

---

## 13. Redirect URL Midtrans

Untuk Snap, Anda dapat mengatur URL redirect di dashboard Midtrans bila diperlukan.

Contoh Finish Redirect URL:

```text
https://domainanda.com/voting-berhasil.html
```

Aplikasi ini tetap menentukan status pembayaran dari webhook/backend. Redirect browser bukan bukti final bahwa transaksi sudah lunas.

---

## 14. Tes transaksi Sandbox

1. Buka halaman frontend.
2. Pilih sekolah/cabang lomba/paket.
3. Isi nama, email, dan nomor telepon.
4. Klik **Bayar Sekarang**.
5. Snap Midtrans harus muncul.
6. Pilih metode pembayaran Sandbox.
7. Selesaikan simulasi pembayaran sesuai simulator Midtrans.
8. Setelah notifikasi masuk, cek status transaksi di admin/database.
9. Pastikan suara hanya bertambah satu kali.

Endpoint status transaksi aplikasi:

```text
GET https://api.domainanda.com/api/checkout/ORDER_ID/status
```

Contoh:

```text
https://api.domainanda.com/api/checkout/INV-2026-123456/status
```

Status yang digunakan aplikasi:

```text
Pending
Paid
Failed
Expired
Refunded
```

---

## 15. Pindah dari Sandbox ke Production

Setelah akun Midtrans production aktif, lakukan semua perubahan berikut.

### Backend `.env`

```env
MIDTRANS_SERVER_KEY=Mid-server-xxxxxxxxxxxxxxxxxxxxxxxx
MIDTRANS_CLIENT_KEY=Mid-client-xxxxxxxxxxxxxxxxxxxxxxxx
MIDTRANS_IS_PRODUCTION=true
```

### Frontend `js/config.js`

```js
const MIDTRANS_CLIENT_KEY = "Mid-client-xxxxxxxxxxxxxxxxxxxxxxxx";
const MIDTRANS_SNAP_URL = "https://app.midtrans.com/snap/snap.js";
```

Kemudian:

1. restart Node.js App;
2. pastikan Payment Notification URL juga sudah dikonfigurasi di environment **Production** Midtrans;
3. clear cache browser/CDN;
4. lakukan transaksi kecil untuk pengujian production.

Sandbox key dan Production key berbeda. Jangan mencampur Server Key/Client Key antar-environment.

---

## 16. CORS jika checkout gagal

Backend hanya mengizinkan domain yang terdaftar di `FRONTEND_ORIGIN`.

Contoh:

```env
FRONTEND_ORIGIN=https://domainanda.com,https://www.domainanda.com
```

Jika frontend memakai subdomain lain, tambahkan juga domain itu secara lengkap termasuk `https://`.

Setelah perubahan, restart Node.js App.

---

## 17. Jika memakai Cloudflare

Untuk frontend dan API:

- SSL/TLS gunakan konfigurasi HTTPS yang valid (disarankan Full/Full Strict jika origin memiliki sertifikat valid);
- jangan membuat rule yang meng-cache endpoint `/api/*`;
- jangan membuat redirect pada `/api/midtrans/webhook`;
- jika WAF memblokir webhook, periksa Security Events dan buat rule yang tetap aman agar notifikasi Midtrans dapat masuk.

Jangan menonaktifkan semua proteksi hanya untuk membuat webhook bekerja.

---

## 18. Error umum

### `Gagal membuat transaksi pembayaran`

Periksa:

- `MIDTRANS_SERVER_KEY` benar;
- mode Sandbox/Production sesuai;
- koneksi internet server aktif;
- package `midtrans-client` ter-install;
- log backend Node.js.

### Snap tidak muncul

Periksa browser Console dan:

- `MIDTRANS_CLIENT_KEY` benar;
- `MIDTRANS_SNAP_URL` sesuai environment;
- tidak ada CSP/adblock yang memblokir Midtrans;
- backend mengembalikan `token` checkout.

### Pembayaran sukses tetapi suara tidak bertambah

Periksa:

- Payment Notification URL benar;
- URL webhook tidak redirect;
- webhook bisa menerima POST dari internet;
- Server Key backend sama dengan environment Midtrans;
- log Node.js menunjukkan signature/amount mismatch atau error database;
- status order lewat endpoint `/api/checkout/ORDER_ID/status`.

### CORS / `Origin tidak diizinkan`

Perbaiki `FRONTEND_ORIGIN`, lalu restart Node.js App.

### Database error

Periksa:

- nama database/user dengan prefix cPanel;
- password;
- host `127.0.0.1` atau host PostgreSQL yang diberikan provider;
- port PostgreSQL;
- privilege user database;
- format `DATABASE_URL`.

---

## 19. File penting terkait pembayaran Midtrans

Backend:

```text
backend/src/utils/midtrans.js
backend/src/routes/checkout.routes.js
backend/src/routes/midtrans.routes.js
backend/.env
```

Frontend:

```text
frontend/jaguarseason6/js/config.js
frontend/jaguarseason6/js/checkout.js
```

Database:

```text
backend/sql/schema.sql
```

Struktur file-file lain tidak perlu diubah hanya untuk memasang Midtrans.

---

## 20. Checklist sebelum live

- [ ] Node.js App backend status Running
- [ ] PostgreSQL terkoneksi
- [ ] `npm run migrate` berhasil
- [ ] `/api/health` menampilkan `ok: true`
- [ ] Frontend memakai URL API production yang benar
- [ ] CORS domain frontend benar
- [ ] Midtrans Server Key hanya di backend
- [ ] Midtrans Client Key benar di frontend
- [ ] `MIDTRANS_IS_PRODUCTION=true` saat benar-benar live
- [ ] Snap URL production = `https://app.midtrans.com/snap/snap.js`
- [ ] Payment Notification URL production sudah diisi
- [ ] HTTPS aktif
- [ ] Webhook tidak redirect dan tidak dilindungi login
- [ ] Satu transaksi sukses hanya menambah suara satu kali
- [ ] Backup database tersedia sebelum melakukan perubahan production

