diff --git a/CHANGELOG.md b/CHANGELOG.md
index f437804..8fac1da 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,15 @@
Format mengikuti [Keep a Changelog](https://keepachangelog.com/) dan [Semantic Versioning](https://semver.org/).
+## [0.6.4] — 2026-11-06 — "qr-custom-ux"
+
+### Diperbaiki
+- QR pada link publik kini **center**.
+- Timer hanya tampil saat QR masih aktif; berhenti/disembunyikan ketika LUNAS, ditolak, atau kedaluwarsa.
+- **Reject / Refund** kini tersedia juga untuk pembayaran yang sudah LUNAS.
+- QR kedaluwarsa: **nominal dan gambar QR disembunyikan** di link publik maupun detail dashboard.
+- Tombol **Regenerate** untuk membuat QR baru + kode unik baru dari QR yang kedaluwarsa (juga tersedia di tabel histori).
+
## [0.6.3] — 2026-11-06 — "webhook-secret-auto"
### Diperbaiki
diff --git a/README.md b/README.md
index a403e07..704cb73 100644
--- a/README.md
+++ b/README.md
@@ -11,7 +11,7 @@
-
+
diff --git a/app-customer.js b/app-customer.js
index c0cccac..72cff5d 100644
--- a/app-customer.js
+++ b/app-customer.js
@@ -2116,7 +2116,11 @@ app.get('/custom-qr/:token', (req, res) => {
const company = settings.company_header || 'OPEN-ISP';
const statusLabels = { pending: 'Menunggu Pembayaran', paid: 'LUNAS', expired: 'Kedaluwarsa', warning: 'Perlu Verifikasi Admin', rejected: 'Ditolak / Refund' };
const status = String(row.status || 'pending');
- const showQr = status !== 'paid' && status !== 'rejected';
+ const expiresMs = row.expires_at ? new Date(row.expires_at).getTime() : 0;
+ const expiredNow = status === 'expired' || (status === 'pending' && expiresMs && expiresMs < Date.now());
+ const showAmount = !expiredNow;
+ const showQr = !expiredNow && status !== 'paid' && status !== 'rejected';
+ const showTimer = status === 'pending' && !expiredNow;
const amountText = 'Rp ' + Number(row.amount_unique || 0).toLocaleString('id-ID');
const baseAmountText = 'Rp ' + Number(row.amount || 0).toLocaleString('id-ID');
const html = `
@@ -2126,7 +2130,7 @@ body{margin:0;background:#0b1220;color:#e5e7eb;font-family:system-ui,Segoe UI,Ar
.card{max-width:460px;width:100%;background:#0f172a;border:1px solid rgba(148,163,184,.2);border-radius:16px;padding:22px;text-align:center}
h1{font-size:19px;margin:0 0 4px}p{margin:6px 0;color:#94a3b8;font-size:13px}
.amt{font-size:26px;font-weight:800;color:#ADFF2F;margin:12px 0 2px}.base{font-size:12px;color:#64748b}
-.qr{background:#fff;padding:12px;border-radius:14px;display:inline-block;margin:14px 0}.qr img{display:block;width:240px;height:240px}
+.qr{background:#fff;padding:12px;border-radius:14px;display:block;width:max-content;margin:14px auto}.qr img{display:block;width:240px;height:240px}
.badge{display:inline-block;padding:5px 10px;border-radius:999px;font-size:12px;font-weight:700;margin-top:6px}
.pending{background:rgba(245,158,11,.15);color:#fbbf24}.paid{background:rgba(34,197,94,.15);color:#4ade80}
.expired{background:rgba(239,68,68,.15);color:#f87171}.warning{background:rgba(249,115,22,.15);color:#fb923c}.rejected{background:rgba(148,163,184,.15);color:#cbd5e1}
@@ -2134,20 +2138,22 @@ h1{font-size:19px;margin:0 0 4px}p{margin:6px 0;color:#94a3b8;font-size:13px}
${cqEscape(row.category || 'Pembayaran')}
${cqEscape(row.title)}
-
${amountText}
-
Nominal dasar ${baseAmountText} + kode unik ${Number(row.unique_code || 0)}
-
${cqEscape(statusLabels[status] || status)}
+${showAmount
+ ? `
${amountText}
Nominal dasar ${baseAmountText} + kode unik ${Number(row.unique_code || 0)}
`
+ : `
QR Kedaluwarsa
Nominal dan QR disembunyikan. Minta admin membuat QR baru.
`}
+
${cqEscape(expiredNow ? 'Kedaluwarsa' : (statusLabels[status] || status))}
${showQr ? `
` : ''}
-
+${showTimer ? `
` : ''}
${row.note ? `
${cqEscape(row.note)}
` : ''}
-
Bayar dengan nominal persis seperti di atas agar pembayaran otomatis tercocokkan. QR berlaku ${require('./services/customQrService').DURATION_MINUTES} menit.
+${showAmount ? `
Bayar dengan nominal persis seperti di atas agar pembayaran otomatis tercocokkan. QR berlaku ${require('./services/customQrService').DURATION_MINUTES} menit.
` : ''}
${cqEscape(company)}