Integrasi Eksternal
Lima sistem luar yang terhubung ke CRM RSI.
| Integrasi | Arah | Autentikasi | Kritis? |
|---|---|---|---|
| Jasnita ChatPanel | dua arah | OAuth2 password grant | ✅ Ya — tanpa ini tidak ada percakapan |
| Duitku | dua arah | Signature SHA-256 (keluar) + MD5 (masuk) | ✅ Ya — menyangkut uang |
| Penyedia LLM | keluar | API key per AI Agent | ⚠️ Auto-reply mati kalau bermasalah |
| SIMRS | masuk (baca) | Kredensial MySQL | ⚠️ Data klinis tidak diperbarui |
| API Inimedia | keluar | client_id + client_secret | ❌ Pelengkap lookup pasien |
1. Jasnita ChatPanel (Toschat)
Base URL: disimpan per akun di kolom gateway_base_url (produksi: https://cpapi.jasnita.co.id)
Dokumentasi vendor: koleksi Postman Toschat
Autentikasi
Empat kredensial wajib — permintaan token melempar RuntimeException bernama kalau ada yang kosong: gateway_client_id, gateway_client_secret, gateway_username, gateway_password.
Konfigurasi per akun
| Kolom | Fungsi |
|---|---|
gateway_provider | Harus jasnita agar driver Toschat dipakai |
gateway_base_url | Base URL API |
gateway_client_id / gateway_client_secret | Kredensial OAuth (secret terenkripsi) |
gateway_username / gateway_password | Kredensial OAuth (password terenkripsi) |
gateway_channel | Channel; default whatsapp_cloud |
gateway_account_id | ID pengirim; hanya perlu bila satu channel punya >1 pengirim |
webhook_verify_token | Token yang ditempel di URL webhook |
Pendaftaran webhook
Tombol "Daftarkan Webhook" di resource WhatsApp Business memanggil POST /api/v1/webhook/update dengan URL:
{APP_URL}/api/webhooks/whatsapp/{id_akun}?token={verify_token}
APP_URLdipakai eksplisit, bukanurl(). Kalau admin dibuka lewat127.0.0.1:8000, Laravel akan mengganti host jadilocalhostdan mengabaikan tunnel diAPP_URL— sehingga alamat yang didaftarkan tidak publik.channelikut dikirim sesuai channel akun. Meng-hardcode'whatsapp'membuat webhook terdaftar di channel lain dan pesan Cloud tidak pernah masuk CRM.
Batasan yang wajib diingat
| Batasan | Konsekuensi |
|---|---|
| Jendela 24 jam WhatsApp | Pesan bebas hanya boleh dikirim kalau pelanggan mengirim pesan dalam 24 jam terakhir. Di luar itu Meta membuang pesan sementara Toschat tetap menjawab "pending" — sistem tidak bisa mendeteksinya |
| Tidak ada API baca thread | Riwayat percakapan internal (whatsapp_messages) adalah milik kami sendiri; thread lama tidak bisa di-backfill |
| Media butuh Bearer token | Karena itu ada proksi /admin/chat/media |
| Endpoint ChatPanel tidak terdokumentasi publik | chatpanel/* dan GET /api/v1/contact dipakai ChatPanel sendiri; bisa berubah sewaktu-waktu tanpa pemberitahuan |
Daftar lengkap endpoint ada di Chat Rooms.
2. Duitku
Base URL: https://api-sandbox.duitku.com atau https://api-prod.duitku.com (dipilih DUITKU_ENV)
Payload createInvoice
| Field | Nilai |
|---|---|
merchantOrderId | RESV-{payment_id} |
paymentAmount | Tarif reservasi (integer) |
productDetails | "Reservasi Booking" |
email | Email pasien, fallback noreply@crmrsi.balascepat.com |
phoneNumber | Nomor WhatsApp pasien |
customerVaName | Nama lengkap pasien |
callbackUrl / returnUrl | Dari config |
expiryPeriod | DUITKU_EXPIRY_MINUTES (default 60) |
customerDetail, itemDetails | Turunan dari nilai di atas |
Invoice dianggap gagal kalau HTTP tidak sukses atau statusCode !== "00" → DuitkuException.
Yang harus didaftarkan di dashboard Duitku
Callback URL: https://crmrsi.balascepat.com/webhook/duitku
Duitku mengulang callback sampai menerima 200. Non-200 berarti callback diulang tanpa henti untuk pembayaran yang sebenarnya sudah selesai. Semua kegagalan di jalur ini ditelan dan dilog, bukan dilempar.
Detail lengkap di Booking & Pembayaran.
3. Penyedia LLM
API key disimpan per AI Agent (terenkripsi), bukan global. Artinya beberapa agent bisa memakai provider/model berbeda.
2.5-flash-liteLebih ringan dan sering punya kuota berbeda dari gemini-2.0-flash — banyak akun kena HTTP 429 atau limit 0 di 2.0.
Yang dikirim ke penyedia LLM
| Dikirim | Tidak dikirim |
|---|---|
| Prompt sistem (identitas, gaya, panduan) | Data pasien lain |
| Knowledge base (teks manual + ekstraksi berkas) | Model WRITE (keluhan/survei orang lain) |
| Dump record Dokter/Poliklinik/Paket | Model sensitif: User, Pasien, Kontak, Pengaturan, Follow-up |
| 15 giliran percakapan terakhir nomor ini | API key mana pun (llm_api_key dikecualikan) |
| Skema tool yang aktif | password, remember_token |
Fitur pendukung
| Fitur | Keterangan |
|---|---|
| Uji koneksi | LlmConnectionProbeService memeriksa kredensial; hasilnya disimpan di llm_last_probe_snapshot |
| Snapshot pemakaian | llm_last_usage_snapshot diisi setiap balasan |
| Simulator chat | Menguji agent tanpa WhatsApp — tool berjalan dalam mode dryRun (tidak menyentuh Duitku maupun database) |
| Pencatatan token | Satu baris ai_token_usages per balasan |
| Token Prices | Tarif per model untuk menghitung biaya pemakaian |
4. SIMRS (dev_simrs_b)
MySQL eksternal, hanya dibaca. Koneksi simrs dengan strict = false (karena data lama tidak selalu memenuhi mode ketat MySQL).
| Env | Default |
|---|---|
SIMRS_DB_HOST | 127.0.0.1 |
SIMRS_DB_PORT | 3306 |
SIMRS_DB_DATABASE | dev_simrs_b |
SIMRS_DB_USERNAME / SIMRS_DB_PASSWORD | kosong |
Tabel yang dibaca: b_ms_unit, b_ms_pegawai, b_ms_pasien, b_kunjungan, b_pelayanan, b_tindakan.
Detail pemetaan di SIMRS Sync.
5. API Inimedia
Layanan pencarian pasien tambahan (PasienClient + PasienApiLookup). Dipakai untuk melengkapi lookup pasien di UI dengan daftar dari API eksternal (id, no_rm, nama), di-cache per request.
| Env | Default |
|---|---|
INIMEDIA_API_BASE_URL | http://139.255.23.90/api_inimedia |
INIMEDIA_CLIENT_ID / INIMEDIA_CLIENT_SECRET | — |
Kegagalan API disimpan sebagai lastFetchError dan ditampilkan di UI, tidak menjatuhkan halaman.