feat(gowa): tombol Test Koneksi (health, auth, jumlah device)
All checks were successful
CI / test (push) Successful in 2m44s
All checks were successful
CI / test (push) Successful in 2m44s
- service testReachability: /health + /devices - route POST /admin/whatsapp/test-gowa-connection - UI status warna hijau/kuning/merah - versi 0.5.11
This commit is contained in:
@@ -2,6 +2,11 @@
|
||||
|
||||
Format mengikuti [Keep a Changelog](https://keepachangelog.com/) dan [Semantic Versioning](https://semver.org/).
|
||||
|
||||
## [0.5.11] — 2026-11-05 — "gowa-test"
|
||||
|
||||
### Ditambahkan
|
||||
- Tombol **Test Koneksi** di Admin → WhatsApp → GOWA: menampilkan apakah GOWA terjangkau, status `/health`, kecocokan username/password Basic Auth, dan jumlah device terdaftar.
|
||||
|
||||
## [0.5.10] — 2026-11-05 — "gowa-mode"
|
||||
|
||||
### Ditambahkan
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
<p align="center">
|
||||
<img src="https://img.shields.io/badge/lisensi-ISC-ADFF2F" alt="Lisensi: ISC">
|
||||
<img src="https://img.shields.io/badge/versi-0.5.10_gowa--mode-ADFF2F" alt="Versi 0.5.10 (gowa-mode)">
|
||||
<img src="https://img.shields.io/badge/versi-0.5.11_gowa--test-ADFF2F" alt="Versi 0.5.11 (gowa-test)">
|
||||
<img src="https://img.shields.io/badge/Node.js-%E2%89%A520-339933" alt="Node.js >= 20">
|
||||
<img src="https://img.shields.io/badge/docker-ready-2496ED?logo=docker&logoColor=white" alt="Docker">
|
||||
<a href="https://demo-openisp.oxpoe.xyz"><img src="https://img.shields.io/badge/demo-live-ADFF2F?logo=googlechrome&logoColor=black" alt="Demo"></a>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "open-isp",
|
||||
"version": "0.5.10",
|
||||
"version": "0.5.11",
|
||||
"description": "OPEN-ISP \u2014 sistem billing & manajemen ISP open-source (PWA pelanggan, multi-OLT, RADIUS, WhatsApp, QRIS)",
|
||||
"main": "app-customer.js",
|
||||
"scripts": {
|
||||
|
||||
@@ -6770,6 +6770,16 @@ router.post('/whatsapp/gateway-settings', requireAdminSession, express.urlencode
|
||||
res.redirect('/admin/whatsapp');
|
||||
});
|
||||
|
||||
router.post('/whatsapp/test-gowa-connection', requireAdminSession, async (req, res) => {
|
||||
try {
|
||||
const gowaSvc = require('../services/gowaWhatsappService');
|
||||
const r = await gowaSvc.testReachability();
|
||||
return res.json(Object.assign({ ok: r.reachable, success: r.reachable }, r));
|
||||
} catch (e) {
|
||||
return res.status(500).json({ ok: false, success: false, message: e.message });
|
||||
}
|
||||
});
|
||||
|
||||
router.post('/whatsapp/test-gowa', requireAdminSession, express.json(), async (req, res) => {
|
||||
try {
|
||||
const { phone, message } = req.body;
|
||||
|
||||
@@ -131,6 +131,41 @@ async function sendGowaDocument(toPhone, documentBuffer, filename = 'file.pdf',
|
||||
});
|
||||
return { success: true, gateway: 'gowa', raw: json };
|
||||
}
|
||||
async function testReachability() {
|
||||
const base = baseUrl();
|
||||
const out = { baseUrl: base, reachable: false, healthStatus: 0, authOk: false, devices: 0, message: '' };
|
||||
try {
|
||||
const res = await fetch(base + '/health');
|
||||
out.healthStatus = res.status;
|
||||
out.reachable = res.ok;
|
||||
} catch (e) {
|
||||
out.message = 'Tidak terjangkau: ' + e.message;
|
||||
return out;
|
||||
}
|
||||
if (!out.reachable) {
|
||||
out.message = 'GOWA menjawab, tetapi /health mengembalikan HTTP ' + out.healthStatus;
|
||||
return out;
|
||||
}
|
||||
try {
|
||||
const res = await fetch(base + '/devices', { headers: commonHeaders() });
|
||||
out.authStatus = res.status;
|
||||
const json = await res.json().catch(function () { return null; });
|
||||
const list = (json && Array.isArray(json.results)) ? json.results : [];
|
||||
if (res.ok) {
|
||||
out.authOk = true;
|
||||
out.devices = list.length;
|
||||
out.message = 'GOWA terjangkau' + (list.length ? ' — ' + list.length + ' device terdaftar' : ' — belum ada device, scan QR untuk menautkan');
|
||||
} else if (res.status === 401) {
|
||||
out.message = 'GOWA terjangkau, tetapi username/password Basic Auth salah atau kosong';
|
||||
} else {
|
||||
out.message = 'GOWA terjangkau, tetapi /devices membalas HTTP ' + res.status;
|
||||
}
|
||||
} catch (e) {
|
||||
out.message = 'GOWA terjangkau, tetapi gagal cek kredensial: ' + e.message;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
async function testGowaConnection(phone, message) {
|
||||
return await sendGowaMessage(phone, message || 'Tes koneksi GOWA berhasil ✅');
|
||||
}
|
||||
@@ -225,4 +260,4 @@ async function getLastQrImage() {
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { sendGowaMessage, sendGowaImage, sendGowaDocument, testGowaConnection, gowaStatus, listDevices, ensureDevice, getLoginQr, getLastQrImage, normalizePhoneJid, baseUrl, resolveDeviceId, invalidateDeviceCache };
|
||||
module.exports = { sendGowaMessage, sendGowaImage, sendGowaDocument, testGowaConnection, testReachability, gowaStatus, listDevices, ensureDevice, getLoginQr, getLastQrImage, normalizePhoneJid, baseUrl, resolveDeviceId, invalidateDeviceCache };
|
||||
|
||||
@@ -1 +1 @@
|
||||
0.5.10
|
||||
0.5.11
|
||||
@@ -199,6 +199,8 @@
|
||||
<div style="font-size:11.5px;color:var(--muted);margin-bottom:8px"><%- t('admin.wa.qr_hint','Klik tombol, lalu buka WhatsApp → Perangkat Tertaut → Tautkan perangkat, scan QR. QR berlaku ~30 detik & diperbarui otomatis.') %></div>
|
||||
<button type="button" class="btn btn-p btn-sm" onclick="showGowaQr()"><i class="bi bi-qr-code-scan"></i> Tampilkan QR</button>
|
||||
<a href="<%= gowaUiUrl %>" target="_blank" rel="noopener" class="btn btn-g btn-sm" style="margin-left:6px"><i class="bi bi-box-arrow-up-right"></i> Buka UI GOWA</a>
|
||||
<button type="button" class="btn btn-g btn-sm" style="margin-left:6px" onclick="testGowaConn(this)"><i class="bi bi-plug"></i> Test Koneksi</button>
|
||||
<div id="gowa_conn_status" style="display:none;margin-top:8px;font-size:12px;line-height:1.5"></div>
|
||||
<div id="gowa_qr_wrap" style="display:none;margin-top:10px;text-align:center">
|
||||
<img id="gowa_qr_img" alt="QR GOWA" style="max-width:240px;background:#fff;padding:10px;border-radius:12px" onerror="var s=document.getElementById('gowa_qr_status');if(s)s.textContent='Gambar QR gagal dimuat — cek log server (base URL/kredensial GOWA).'">
|
||||
<div id="gowa_qr_status" style="font-size:12px;color:var(--muted);margin-top:6px"></div>
|
||||
@@ -237,6 +239,25 @@
|
||||
</div>
|
||||
|
||||
<script>
|
||||
async function testGowaConn(btn) {
|
||||
var el = document.getElementById('gowa_conn_status');
|
||||
var old = btn ? btn.innerHTML : '';
|
||||
if (btn) { btn.disabled = true; btn.innerHTML = '<i class="bi bi-hourglass-split"></i> Menguji...'; }
|
||||
if (el) { el.style.display = 'block'; el.style.color = 'var(--muted)'; el.textContent = 'Menghubungi ' + (document.querySelector('input[name="gowa_base_url"]') || {}).value + ' ...'; }
|
||||
try {
|
||||
var r = await fetch('/admin/whatsapp/test-gowa-connection', { method: 'POST' });
|
||||
var d = await r.json();
|
||||
if (el) {
|
||||
el.textContent = d.message || (d.ok ? 'GOWA terjangkau.' : 'GOWA tidak terjangkau.');
|
||||
el.style.color = (d.ok && d.authOk) ? 'var(--success)' : (d.ok ? '#f59e0b' : 'var(--danger)');
|
||||
}
|
||||
} catch (e) {
|
||||
if (el) { el.style.color = 'var(--danger)'; el.textContent = 'Gagal menguji koneksi: ' + e.message; }
|
||||
} finally {
|
||||
if (btn) { btn.disabled = false; btn.innerHTML = old; }
|
||||
}
|
||||
}
|
||||
|
||||
function toggleGowaMode() {
|
||||
var mode = (document.getElementById('gowa_mode') || {}).value || 'cloud';
|
||||
var hint = document.getElementById('gowa_mode_hint');
|
||||
|
||||
Reference in New Issue
Block a user