fix(gowa): tampilkan status HTTP saat QR gagal (401/kredensial)
All checks were successful
CI / test (push) Successful in 3m32s

This commit is contained in:
oxpoe
2026-11-05 15:46:45 +07:00
parent e28c9debea
commit 7a5b488882
6 changed files with 35 additions and 10 deletions

View File

@@ -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

View File

@@ -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.7_gowa--podman-ADFF2F" alt="Versi 0.5.7 (gowa-podman)">
<img src="https://img.shields.io/badge/versi-0.5.8_gowa--qr-error-ADFF2F" alt="Versi 0.5.8 (gowa-qr-error)">
<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>

View File

@@ -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": {

View File

@@ -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 }); }
});

View File

@@ -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;

View File

@@ -1 +1 @@
0.5.7
0.5.8