diff --git a/CHANGELOG.md b/CHANGELOG.md index 235662d..f00482f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,11 @@ Format mengikuti [Keep a Changelog](https://keepachangelog.com/) dan [Semantic Versioning](https://semver.org/). +## [0.5.8] — 2026-11-05 — "gowa-qr-error" + +### Diperbaiki +- QR GOWA: pesan gagal kini menampilkan status HTTP dan respons GOWA (mis. `HTTP 401 — Unauthorized`) sehingga penyebabnya langsung terlihat, bukan lagi "pastikan GOWA berjalan". + ## [0.5.7] — 2026-11-05 — "gowa-podman" ### Ditambahkan diff --git a/README.md b/README.md index 3362a92..f515538 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@
-
+
diff --git a/package.json b/package.json
index 09d0b77..da3a9ab 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "open-isp",
- "version": "0.5.7",
+ "version": "0.5.8",
"description": "OPEN-ISP \u2014 sistem billing & manajemen ISP open-source (PWA pelanggan, multi-OLT, RADIUS, WhatsApp, QRIS)",
"main": "app-customer.js",
"scripts": {
diff --git a/routes/adminPortal.js b/routes/adminPortal.js
index 4f1bb07..182e567 100644
--- a/routes/adminPortal.js
+++ b/routes/adminPortal.js
@@ -6650,7 +6650,10 @@ router.get('/whatsapp/gowa/qr', requireAdminSession, async (req, res) => {
const dev = await gowa.ensureDevice();
if (dev && dev !== getSetting('gowa_device_id', '')) saveSettings({ gowa_device_id: dev });
const r = await gowa.getLoginQr(dev);
- if (!r.ok) return res.json({ ok: false, message: 'Gagal membuat QR (' + (r.code || 'pastikan GOWA berjalan') + ').' });
+ if (!r.ok) {
+ const detail = r.message || r.code || 'pastikan GOWA berjalan & username/password Basic Auth benar';
+ return res.json({ ok: false, status: r.status || 0, message: 'Gagal membuat QR: ' + (r.status ? 'HTTP ' + r.status + ' — ' : '') + detail + '.' });
+ }
return res.json({ ok: true, image: '/admin/whatsapp/gowa/qr.png?v=' + Date.now(), device_id: r.device_id, duration: r.duration });
} catch (e) { return res.json({ ok: false, message: e.message }); }
});
diff --git a/services/gowaWhatsappService.js b/services/gowaWhatsappService.js
index 0a33a72..78a2925 100644
--- a/services/gowaWhatsappService.js
+++ b/services/gowaWhatsappService.js
@@ -168,12 +168,29 @@ async function ensureDevice() {
async function getLoginQr(deviceId) {
const dev = deviceId || deviceHeader();
const url = baseUrl() + '/app/login' + (dev ? ('?device_id=' + encodeURIComponent(dev)) : '');
- const res = await fetch(url, { headers: commonHeaders() });
- const json = await res.json().catch(function () { return null; });
- const r = (json && json.results) || {};
- const link = r.qr_link || r.image_path || null;
- if (link) _lastQr = { link: link, at: Date.now() };
- return { ok: !!link, qr_link: link, duration: r.qr_duration || null, device_id: r.device_id || dev || null, code: (json && json.code) || null };
+ try {
+ const res = await fetch(url, { headers: commonHeaders() });
+ const text = await res.text();
+ let json = null;
+ try { json = JSON.parse(text); } catch (e) {}
+ if (!res.ok) {
+ const detail = String(
+ (json && (json.message || json.error || json.code)) || text || ''
+ ).replace(/\s+/g, ' ').trim().slice(0, 160);
+ return {
+ ok: false,
+ status: res.status,
+ code: (json && json.code) || null,
+ message: detail || ('HTTP ' + res.status)
+ };
+ }
+ const r = (json && json.results) || {};
+ const link = r.qr_link || r.image_path || null;
+ if (link) _lastQr = { link: link, at: Date.now() };
+ return { ok: !!link, qr_link: link, duration: r.qr_duration || null, device_id: r.device_id || dev || null, code: (json && json.code) || null };
+ } catch (e) {
+ return { ok: false, status: 0, code: null, message: e.message };
+ }
}
async function getLastQrImage() {
if (!_lastQr.link) return null;
diff --git a/version.txt b/version.txt
index dc2b74e..b35b9dd 100644
--- a/version.txt
+++ b/version.txt
@@ -1 +1 @@
-0.5.7
\ No newline at end of file
+0.5.8
\ No newline at end of file