fix(wa): notifikasi LUNAS lewat gateway aktif + approve APK
All checks were successful
CI / test (push) Successful in 2m26s
All checks were successful
CI / test (push) Successful in 2m26s
- isConnected GOWA: tangani /devices array (state connected) - app-customer payment-notif: pakai waNotify, bukan Baileys - customerAPI approve kolektor + payment-unmatched: kirim WA lunas - versi 0.5.13
This commit is contained in:
@@ -2,6 +2,13 @@
|
||||
|
||||
Format mengikuti [Keep a Changelog](https://keepachangelog.com/) dan [Semantic Versioning](https://semver.org/).
|
||||
|
||||
## [0.5.13] — 2026-11-05 — "lunas-notify"
|
||||
|
||||
### Diperbaiki
|
||||
- Notifikasi WA **LUNAS** memakai gateway aktif (GOWA/Fonnte/Meta/Baileys), bukan hanya Baileys.
|
||||
- Deteksi koneksi GOWA membaca status device dari `/devices` (array) — sebelumnya dianggap tidak terhubung bila Device ID kosong, sehingga notifikasi lunas dilewati.
|
||||
- Approve pembayaran kolektor dari APK admin dan pencocokan notifikasi pembayaran manual kini mengirim WA lunas ke pelanggan.
|
||||
|
||||
## [0.5.12] — 2026-11-05 — "gowa-test-unsaved"
|
||||
|
||||
### Diperbaiki
|
||||
|
||||
@@ -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.12_gowa--test2-ADFF2F" alt="Versi 0.5.12 (gowa-test-unsaved)">
|
||||
<img src="https://img.shields.io/badge/versi-0.5.13_lunas--notify-ADFF2F" alt="Versi 0.5.13 (lunas-notify)">
|
||||
<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>
|
||||
|
||||
@@ -628,8 +628,8 @@ async function trySendWaPaymentSuccess(settings, invoiceId, methodLabel) {
|
||||
if (!inv) return;
|
||||
const phone = String(inv.customer_phone || '').trim();
|
||||
if (!phone) return;
|
||||
const { sendWA, whatsappStatus } = await import('./services/whatsappBot.mjs');
|
||||
if (whatsappStatus.connection !== 'open') throw new Error('Bot WhatsApp belum terhubung');
|
||||
// Pakai gateway aktif (GOWA/Fonnte/Meta/Baileys), bukan hanya Baileys.
|
||||
const waNotify = require('./services/waNotifyService');
|
||||
|
||||
const appUrl = (settings.public_base_url || '').replace(/\/$/, '');
|
||||
const portalUrl = appUrl ? `${appUrl}/customer` : '';
|
||||
@@ -654,7 +654,7 @@ async function trySendWaPaymentSuccess(settings, invoiceId, methodLabel) {
|
||||
});
|
||||
|
||||
logger.info(`[WEBHOOK][payment-notif] Sending WA success notif to ${phone} inv=${invoiceId} method=${metode}`);
|
||||
await sendWA(phone, msg);
|
||||
await waNotify.sendText(phone, msg);
|
||||
} catch (e) {
|
||||
logger.error(`[WEBHOOK][payment-notif] WA success notif failed: ${e?.message || e}`);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "open-isp",
|
||||
"version": "0.5.12",
|
||||
"version": "0.5.13",
|
||||
"description": "OPEN-ISP \u2014 sistem billing & manajemen ISP open-source (PWA pelanggan, multi-OLT, RADIUS, WhatsApp, QRIS)",
|
||||
"main": "app-customer.js",
|
||||
"scripts": {
|
||||
|
||||
@@ -4925,6 +4925,29 @@ router.post('/payment-unmatched/:id/match', requireAdminSession, express.urlenco
|
||||
if (!unpaid) await customerSvc.activateCustomer(inv.customer_id);
|
||||
}
|
||||
} catch (e) {}
|
||||
|
||||
// Notifikasi WA lunas ke pelanggan
|
||||
try {
|
||||
const cust = customerSvc.getCustomerById(inv.customer_id);
|
||||
if (cust && cust.phone) {
|
||||
const pkg = cust.package_id ? customerSvc.getPackageById(cust.package_id) : null;
|
||||
await sendPaymentSuccessWA(
|
||||
cust.phone,
|
||||
cust.name,
|
||||
`${inv.period_month}/${inv.period_year}`,
|
||||
Number(inv.amount || 0).toLocaleString('id-ID'),
|
||||
'Manual (Webhook)',
|
||||
{
|
||||
customerId: cust.id,
|
||||
invoiceId: inv.id,
|
||||
username: cust.pppoe_username || cust.id,
|
||||
customerCode: cust.customer_code || '',
|
||||
packageName: pkg?.name || cust.package_name || '-',
|
||||
paidAt: new Date(), method: 'Manual (Webhook)'
|
||||
}
|
||||
);
|
||||
}
|
||||
} catch (e) {}
|
||||
req.session._msg = { type: 'success', text: 'Invoice #' + invId + ' ditandai LUNAS & notif dicocokkan.' };
|
||||
} catch (e) {
|
||||
req.session._msg = { type: 'error', text: 'Gagal cocokkan: ' + e.message };
|
||||
|
||||
@@ -2359,6 +2359,37 @@ router.post('/app/admin/collector-payments/approve', requireAdminApiAuth, async
|
||||
if (unpaidCount === 0) {
|
||||
try { await customerSvc.activateCustomer(pay.customer_id); } catch (_) {}
|
||||
}
|
||||
|
||||
// Notifikasi WA lunas ke pelanggan (gateway aktif)
|
||||
try {
|
||||
const customer = customerSvc.getCustomerById(pay.customer_id);
|
||||
const inv = billingSvc.getInvoiceById(pay.invoice_id);
|
||||
if (customer && customer.phone && inv) {
|
||||
const settings = getSettingsWithCache();
|
||||
const waNotify = require('../services/waNotifyService');
|
||||
const whatsappService = require('../services/whatsappService');
|
||||
const pkg = customer.package_id ? customerSvc.getPackageById(customer.package_id) : null;
|
||||
const appUrl = String(settings.public_base_url || '').replace(/\/$/, '');
|
||||
const template = db.getAppSetting('whatsapp_payment_success_message', '');
|
||||
const msg = whatsappService.formatPaymentSuccessMessage({
|
||||
customerName: customer.name,
|
||||
invoiceId: inv.id,
|
||||
customerUsername: customer.pppoe_username || customer.id || '-',
|
||||
customerCode: customer.customer_code || '',
|
||||
packageName: pkg?.name || customer.package_name || '-',
|
||||
periodMonth: inv.period_month,
|
||||
periodYear: inv.period_year,
|
||||
amount: inv.amount,
|
||||
paymentMethod: collectorLabel,
|
||||
paidAt: new Date(),
|
||||
companyName: settings.company_header || 'OPEN-ISP',
|
||||
companyPhone: settings.company_phone || '',
|
||||
portalUrl: appUrl ? appUrl + '/customer' : '',
|
||||
customTemplate: template
|
||||
});
|
||||
await waNotify.sendText(customer.phone, msg);
|
||||
}
|
||||
} catch (_) {}
|
||||
}
|
||||
res.json({ success: true, message: 'Pembayaran berhasil di-approve dan tagihan ditandai LUNAS' });
|
||||
} catch (e) { res.status(500).json({ success: false, message: e.message }); }
|
||||
|
||||
@@ -140,8 +140,12 @@ async function isConnected() {
|
||||
try {
|
||||
if (gw === 'gowa') {
|
||||
const st = await require('./gowaWhatsappService').gowaStatus();
|
||||
const d = (st && st.data && st.data.results) || (st && st.data) || {};
|
||||
val = !!(d.is_connected || d.is_logged_in || d.connected);
|
||||
const raw = (st && st.data && st.data.results) || (st && st.data) || {};
|
||||
const list = Array.isArray(raw) ? raw : [raw];
|
||||
val = list.some(function (d) {
|
||||
return !!(d && (d.is_connected || d.is_logged_in || d.connected ||
|
||||
d.state === 'connected' || d.state === 'logged_in'));
|
||||
});
|
||||
} else if (gw === 'baileys') {
|
||||
const mod = await import('./whatsappBot.mjs');
|
||||
const s = mod.whatsappStatus;
|
||||
|
||||
@@ -1 +1 @@
|
||||
0.5.12
|
||||
0.5.13
|
||||
Reference in New Issue
Block a user