Template User Manager Voucher Hotspot MikroTik Plus QR Code Generator Modern
Manajemen hotspot berbasis MikroTik sudah menjadi standar di banyak jaringan publik dan semi publik. Sekolah, kampus, kafe, hotel, tempat ibadah, coworking space, sampai RT RW Net mengandalkan hotspot sebagai layanan utama. Tantangannya bukan hanya menyediakan internet. Tantangannya adalah mengelola akses agar aman, terkontrol, dan mudah digunakan.
User Manager MikroTik memberi kontrol user berbasis RADIUS yang kuat. Namun di lapangan, kendala sering muncul pada distribusi dan tampilan voucher. Voucher bawaan cenderung kaku dan kurang nyaman dibaca. Pengguna saat ini menuntut login yang cepat, intuitif, dan minim input manual.





Integrasi template voucher User Manager dengan QR Code Generator menjawab kebutuhan itu. Sistem ini menggabungkan kontrol akses yang rapi dengan pengalaman login yang cepat. Hasilnya, voucher terlihat modern, mudah dipakai, dan lebih profesional.
Tutorial ini menyatukan konsep dan implementasi teknis. Kamu dapat langsung menerapkan template modern ini di User Manager, termasuk QR Code auto render untuk setiap voucher. Ada versi cetak A4, versi thermal, mode direct, mode proxy POST, opsi library CDN, dan opsi file lokal.
Checklist sebelum mulai
Hotspot sudah aktif dan bisa redirect ke halaman login.
User Manager sudah terpasang dan bisa membuat user voucher.
Hotspot sudah memakai RADIUS, minimal service hotspot aktif.
Secret RADIUS sama di router dan di User Manager.
Kamu tahu URL login hotspot yang benar, umumnya http://IP/login.
Evolusi sistem voucher hotspot MikroTik
Pada awalnya, voucher hotspot fokus pada pembatasan akses. Username dan password dicetak di kertas kecil. Metode ini efektif secara fungsi, tetapi memunculkan masalah operasional. Kesalahan input sering terjadi. Proses login lambat. Pengguna meminta bantuan staf berulang kali.
Ketika smartphone menjadi perangkat utama, pola interaksi berubah. QR Code menjadi media populer untuk autentikasi dan akses layanan digital. Dalam hotspot, QR Code mempercepat login karena pengguna tidak perlu mengetik kredensial.
Integrasi QR Code bukan hanya upgrade tampilan. Ini perubahan model layanan. Hotspot tidak lagi sekadar kontrol teknis. Hotspot menjadi layanan yang mengejar pengalaman pengguna.
User Manager MikroTik sebagai fondasi sistem
User Manager adalah paket tambahan pada RouterOS yang berfungsi sebagai RADIUS server internal. User Manager menangani autentikasi, otorisasi, dan pencatatan penggunaan user hotspot.
Fungsi penting yang relevan untuk voucher.
Pembuatan akun voucher skala besar
Profil bandwidth dan limitasi
Masa aktif berbasis waktu atau kuota
Monitoring penggunaan user
Integrasi dengan Hotspot, PPP, dan wireless
Dalam arsitektur modern, User Manager adalah pusat kontrol. Template voucher dan QR Code adalah lapisan antarmuka untuk pengguna.
Konsep template voucher pada User Manager
Template voucher adalah mekanisme bawaan User Manager untuk mengatur output voucher saat dicetak atau ditampilkan. Template terdiri dari 4 bagian.
Pembuka HTML, CSS, dan script pendukung.
Row. Bagian inti voucher. Akan diulang untuk setiap user.
Footer. Penutup HTML. Biasanya memicu render ulang QR setelah semua row selesai.
Break. Pengatur pemisahan halaman saat print. Opsional tergantung layout.
Kelebihan pendekatan template. Kamu bisa mengubah desain voucher tanpa mengubah logika autentikasi hotspot.
Integrasi QR Code sebagai lapisan akses cepat
QR Code pada voucher adalah representasi digital dari kredensial login. Data yang paling praktis adalah URL login hotspot dengan parameter username dan password.
Saat QR dipindai, browser membuka URL login. Kredensial dikirim otomatis. Jika hotspot dan RADIUS benar, user langsung tersambung.
Manfaat yang biasanya terasa di lapangan.
Waktu login turun drastis
Kesalahan input hampir hilang
Pengguna awam lebih cepat paham
Distribusi voucher lebih efisien, bisa cetak atau kirim digital
Arsitektur sistem voucher hotspot modern
Lapisan 1. Router MikroTik dengan Hotspot aktif sebagai gerbang jaringan.
Lapisan 2. User Manager sebagai RADIUS server, menyimpan user dan profile.
Lapisan 3. Template voucher berbasis HTML dan CSS, menampilkan data voucher.
Lapisan 4. QR Code generator berbasis JavaScript, membuat QR otomatis.
Lapisan 5. Perangkat user, memindai QR dan login.
Pemisahan lapisan ini membuat sistem lebih mudah dipelihara dan lebih scalable.
Struktur data voucher User Manager
User Manager menyediakan variabel internal yang bisa dipanggil dalam template. Variabel berikut sering dipakai.
%u_username%
%u_password%
%u_limitUptime%
%u_timeLeft%
%u_limitDownload%
%u_shared_users%
%u_moneyPaid%
Nilai variabel akan diganti otomatis saat voucher digenerate.
IMPLEMENTASI BARU, LAYOUT GAMBAR WIFI CARD AGAR SESUAI DAN TERINTEGRASI DENGAN SOURCE CODE
Target implementasi
Gambar wifi card kamu jadi kanvas desain.
HTML hanya mengisi konten dinamis.
QR tetap bersih dan mudah discan.
Hasilnya konsisten untuk digital dan cetak.
Prinsip yang dipakai
Jadikan gambar sebagai background layer.
Tentukan area yang aman untuk teks dan QR.
Gunakan overlay tipis agar teks terbaca.
Jangan taruh pattern di belakang QR, area QR wajib putih.
Aturan ukuran agar tidak pecah saat print
Untuk A4, minimal lebar 2000 px.
Untuk penggunaan umum, 1920 px masih aman.
Format JPG untuk ukuran ringan.
PNG jika butuh transparansi.
SOURCE CODE TAMBAHAN, WIFI CARD LAYOUT, 1 VOUCHER PER HALAMAN A4
Template ini mengikuti struktur gambar wifi card.
Kiri, area logo dan kredensial.
Kanan, area instruksi, QR, dan voucher code.
Header WIFI CARD A4
<!doctype html>
<html lang="id">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Voucher WiFi Card</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/qrcodejs/1.0.0/qrcode.min.js"></script>
<style>
@page { size: A4; margin: 10mm; }
body{
margin:0;
padding:0;
font-family: Arial, Helvetica, sans-serif;
background:#ffffff;
color:#0b1220;
}
:root{
--cardUrl: none;
--ink: #0b1220;
--muted: rgba(11,18,32,0.75);
--white: #ffffff;
}
.page{
width: 190mm;
margin: 0 auto;
padding: 0;
}
.card{
position: relative;
width: 190mm;
height: 95mm;
border-radius: 6mm;
overflow: hidden;
background: #0b1220;
box-shadow: 0 10px 30px rgba(0,0,0,0.18);
}
.card::before{
content:"";
position:absolute;
inset:0;
background-image: var(--cardUrl);
background-size: cover;
background-position: center;
z-index: 0;
}
/* Overlay ringan agar teks konsisten di berbagai gambar */
.card::after{
content:"";
position:absolute;
inset:0;
background: rgba(255,255,255,0.00);
z-index: 1;
pointer-events:none;
}
.content{
position:absolute;
inset:0;
z-index: 2;
display:grid;
grid-template-columns: 44% 56%;
}
/* KIRI, meniru blok logo di gambar */
.left{
position:relative;
padding: 16mm 10mm 10mm 10mm;
}
.logoBox{
width: 62mm;
height: 62mm;
background: rgba(255,255,255,0.96);
border-radius: 5mm;
box-shadow: 0 8px 18px rgba(0,0,0,0.18);
border: 1px solid rgba(0,0,0,0.06);
display:flex;
align-items:center;
justify-content:center;
overflow:hidden;
}
.logoHint{
font-size: 16px;
font-weight: 800;
color: rgba(11,18,32,0.45);
letter-spacing: 0.3px;
}
/* Area kredensial diposisikan aman, tidak mengganggu elemen desain */
.creds{
margin-top: 6mm;
background: rgba(255,255,255,0.92);
border-radius: 4mm;
padding: 4mm 4mm;
border: 1px solid rgba(0,0,0,0.06);
}
.rowline{
display:flex;
justify-content: space-between;
gap: 6mm;
font-size: 12px;
line-height: 1.35;
margin: 1.6mm 0;
}
.k{
font-weight: 800;
color: rgba(11,18,32,0.70);
}
.v{
font-family: Consolas, "Courier New", monospace;
font-weight: 900;
color: #0b1220;
text-align: right;
word-break: break-all;
}
/* KANAN, meniru area instruksi dan voucher code pada gambar */
.right{
position:relative;
padding: 18mm 10mm 10mm 10mm;
color: #ffffff;
}
.rightOverlay{
position:absolute;
inset: 10mm 8mm 10mm 8mm;
background: rgba(5,16,40,0.35);
border-radius: 5mm;
z-index: 0;
}
.rightInner{
position:relative;
z-index: 1;
height: 100%;
display:grid;
grid-template-rows: auto auto 1fr auto;
gap: 4mm;
}
.connectTitle{
font-weight: 900;
font-size: 16px;
letter-spacing: 0.5px;
}
.steps{
font-size: 12px;
line-height: 1.5;
color: rgba(255,255,255,0.92);
}
.steps div{
margin: 1.5mm 0;
}
.qrRow{
display:grid;
grid-template-columns: 1fr 38mm;
align-items:center;
gap: 6mm;
}
.qrBox{
width: 34mm;
height: 34mm;
background: #ffffff;
border-radius: 4mm;
display:flex;
align-items:center;
justify-content:center;
overflow:hidden;
border: 1px solid rgba(255,255,255,0.35);
}
.meta{
font-size: 11px;
color: rgba(255,255,255,0.90);
line-height: 1.45;
}
.voucherCodeWrap{
background: rgba(255,255,255,0.14);
border: 1px solid rgba(255,255,255,0.22);
border-radius: 4mm;
padding: 3mm 4mm;
}
.vcTitle{
font-weight: 900;
font-size: 12px;
letter-spacing: 0.6px;
color: rgba(255,255,255,0.95);
}
.vcCode{
margin-top: 2mm;
font-family: Consolas, "Courier New", monospace;
font-weight: 900;
font-size: 18px;
letter-spacing: 1px;
color: #ffffff;
word-break: break-all;
}
.tiny{
font-size: 10px;
color: rgba(255,255,255,0.85);
}
</style>
<script>
var HOTSPOT_LOGIN_URL = "http://10.10.10.1/login";
/* Isi dengan URL gambar wifi card dari WordPress Media Library */
var ASSET_CARD_URL = "https://domainkamu.com/wp-content/uploads/wifi-card-blue.jpg";
/* Nama SSID yang ingin kamu tampilkan pada instruksi */
var HOTSPOT_SSID_NAME = "Free Wi-Fi";
/* QR Mode */
var QR_MODE = "direct";
var QR_PROXY_URL = "http://10.10.10.1/qrlogin.html";
function buildQrText(u, p){
var eu = encodeURIComponent(u || "");
var ep = encodeURIComponent(p || "");
if(QR_MODE === "proxy"){
return QR_PROXY_URL + "?u=" + eu + "&p=" + ep;
}
return HOTSPOT_LOGIN_URL + "?username=" + eu + "&password=" + ep;
}
function applyCardImage(){
var el = document.querySelector(".card");
if(!el) return;
el.style.setProperty("--cardUrl", "url(" + ASSET_CARD_URL + ")");
}
function renderQr(){
if(typeof QRCode === "undefined"){ return; }
var card = document.querySelector(".card[data-u][data-p]");
if(!card) return;
var u = card.getAttribute("data-u") || "";
var p = card.getAttribute("data-p") || "";
var box = card.querySelector(".qrBox");
if(!box) return;
while(box.firstChild) box.removeChild(box.firstChild);
new QRCode(box, {
text: buildQrText(u, p),
width: 128,
height: 128,
correctLevel: QRCode.CorrectLevel.M
});
var ssid = document.getElementById("ssidName");
if(ssid) ssid.textContent = HOTSPOT_SSID_NAME;
}
function boot(){
applyCardImage();
renderQr();
}
if(document.readyState === "loading"){
document.addEventListener("DOMContentLoaded", boot);
} else {
boot();
}
</script>
</head>
<body>
<div class="page">
Row WIFI CARD A4
<div class="card" data-u="%u_username%" data-p="%u_password%">
<div class="content">
<div class="left">
<div class="logoBox">
<div class="logoHint">LOGO</div>
</div>
<div class="creds">
<div class="rowline">
<div class="k">User</div>
<div class="v">%u_username%</div>
</div>
<div class="rowline">
<div class="k">Pass</div>
<div class="v">%u_password%</div>
</div>
</div>
</div>
<div class="right">
<div class="rightOverlay"></div>
<div class="rightInner">
<div class="connectTitle">CONNECT TO:</div>
<div class="steps">
<div>1. Select Network: <span id="ssidName">Free Wi-Fi</span></div>
<div>2. Enter Voucher Code</div>
<div>3. Enjoy Browsing</div>
</div>
<div class="qrRow">
<div class="meta">
<div>Durasi: %u_limitUptime%</div>
<div>Sisa aktif: %u_timeLeft%</div>
<div>Kuota: %u_limitDownload%</div>
<div class="tiny">Scan QR untuk login cepat</div>
</div>
<div class="qrBox"></div>
</div>
<div class="voucherCodeWrap">
<div class="vcTitle">VOUCHER CODE:</div>
<div class="vcCode">%u_username%-%u_password%</div>
</div>
</div>
</div>
</div>
</div>
Footer WIFI CARD A4
</div>
<script>
try { boot(); } catch(e) {}
</script>
</body>
</html>
Catatan penting untuk akurasi layout dengan gambar wifi card
Jika teks atau QR tidak pas, kamu hanya perlu tuning 3 titik ini.
Ukuran card, ubah height di .card.
Padding area kiri dan kanan, ubah padding di .left dan .right.
Ukuran QR, ubah ukuran .qrBox dan parameter QRCode width, height.
Jika kamu ingin QR berada tepat di area putih khusus QR pada gambar, perbaiki posisi dengan margin.
Contoh cepat yang aman.
Di .qrBox tambahkan margin-left atau margin-top kecil.
Atau atur .qrRow grid-template-columns agar QR bergerak lebih dekat ke kanan.
SOURCE CODE TAMBAHAN, WIFI CARD LAYOUT, VERSI THERMAL 80MM
Tujuan thermal.
Bukan meniru full gambar, karena thermal hitam putih.
Yang dipakai adalah struktur layout yang sama.
Header, instruksi, QR besar, dan kode.
Header WIFI CARD Thermal
<!doctype html>
<html lang="id">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Voucher WiFi Card Thermal</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/qrcodejs/1.0.0/qrcode.min.js"></script>
<style>
@page { size: 80mm auto; margin: 0; }
body{
margin:0;
padding:0;
font-family: Arial, Helvetica, sans-serif;
background:#ffffff;
color:#111827;
}
.wrap{ width: 72mm; margin: 0 auto; padding: 6mm 4mm; }
.box{
border: 1px solid #e5e7eb;
border-radius: 10px;
padding: 10px;
}
.brand{
font-weight: 900;
font-size: 14px;
text-align: center;
margin-bottom: 4px;
}
.sub{
text-align: center;
font-size: 11px;
color: #4b5563;
margin-bottom: 8px;
}
.mono{ font-family: Consolas, "Courier New", monospace; font-weight: 900; }
.line{
display:flex;
justify-content: space-between;
gap: 10px;
font-size: 12px;
margin: 3px 0;
}
.qr{
width: 180px;
height: 180px;
margin: 10px auto 6px auto;
display:flex;
align-items:center;
justify-content:center;
border: 1px solid #e5e7eb;
border-radius: 10px;
background:#ffffff;
}
.code{
margin-top: 6px;
padding: 6px;
border: 1px dashed #cbd5e1;
border-radius: 8px;
text-align: center;
}
.codeTitle{ font-size: 10px; color:#475569; font-weight: 900; }
.codeVal{ margin-top: 3px; font-size: 14px; font-weight: 900; letter-spacing: 0.4px; }
</style>
<script>
var HOTSPOT_LOGIN_URL = "http://10.10.10.1/login";
var QR_MODE = "direct";
var QR_PROXY_URL = "http://10.10.10.1/qrlogin.html";
function buildQrText(u, p){
var eu = encodeURIComponent(u || "");
var ep = encodeURIComponent(p || "");
if(QR_MODE === "proxy"){
return QR_PROXY_URL + "?u=" + eu + "&p=" + ep;
}
return HOTSPOT_LOGIN_URL + "?username=" + eu + "&password=" + ep;
}
function renderAllQrs(){
if(typeof QRCode === "undefined"){ return; }
var cards = document.querySelectorAll(".box[data-u][data-p]");
for(var i=0;i<cards.length;i++){
var card = cards[i];
var u = card.getAttribute("data-u") || "";
var p = card.getAttribute("data-p") || "";
var qrBox = card.querySelector(".qr");
if(!qrBox) continue;
while(qrBox.firstChild) qrBox.removeChild(qrBox.firstChild);
new QRCode(qrBox, {
text: buildQrText(u, p),
width: 170,
height: 170,
correctLevel: QRCode.CorrectLevel.M
});
}
}
if(document.readyState === "loading"){
document.addEventListener("DOMContentLoaded", renderAllQrs);
} else {
renderAllQrs();
}
</script>
</head>
<body>
<div class="wrap">
Row WIFI CARD Thermal
<div class="box" data-u="%u_username%" data-p="%u_password%">
<div class="brand">FREE WIFI</div>
<div class="sub">Scan QR untuk login cepat</div>
<div class="line"><div>User</div><div class="mono">%u_username%</div></div>
<div class="line"><div>Pass</div><div class="mono">%u_password%</div></div>
<div class="line"><div>Durasi</div><div>%u_limitUptime%</div></div>
<div class="line"><div>Kuota</div><div>%u_limitDownload%</div></div>
<div class="qr"></div>
<div class="code">
<div class="codeTitle">VOUCHER CODE</div>
<div class="codeVal">%u_username%-%u_password%</div>
</div>
</div>
Footer WIFI CARD Thermal
<script>
try { renderAllQrs(); } catch(e) {}
</script>
</div>
</body>
</html>
Implementasi template voucher modern dengan QR Code auto render
Bagian ini adalah inti implementasi. Kamu tinggal paste sesuai kolom di User Manager. QR Code butuh library JavaScript. Ada 2 opsi. Opsi CDN paling simpel. Opsi file lokal lebih stabil jika jaringan cetak tidak punya akses internet.
Yang wajib kamu ganti adalah HOTSPOT_LOGIN_URL. Isi dengan IP atau domain login hotspot kamu.
Langkah pasang template di User Manager
1. Buka Winbox.
2. Masuk ke User Manager.
3. Masuk ke menu Settings lalu Templates.
4. Pilih template Vouchers atau buat template baru.
5. Paste Header, Row, Footer, Break sesuai kolomnya.
6. Simpan, lalu generate voucher untuk uji cetak.
Source code modern versi A4 grid, 2 kolom
Versi ini cocok untuk cetak A4. Output rapi dan hemat kertas. QR auto render untuk setiap voucher.
Header A4 grid
<!doctype html> <html lang="id"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Voucher Hotspot</title> <script src="https://cdnjs.cloudflare.com/ajax/libs/qrcodejs/1.0.0/qrcode.min.js"></script> <!-- Opsi lokal. Aktifkan jika perlu. Simpan qrcode.min.js di web server lokal --> <!-- <script src="http://10.10.10.1/qrcode.min.js"></script> --> <style> @page { size: A4; margin: 10mm; } body{ margin:0; padding:0; font-family: Arial, Helvetica, sans-serif; background: #ffffff; color: #0b1220; } .sheet{ width: 210mm; margin: 0 auto; } .grid{ display: grid; grid-template-columns: repeat(2, 1fr); gap: 8mm; padding: 0; } .voucher{ border: 1px solid #d6dbe6; border-radius: 10px; overflow: hidden; background: #ffffff; min-height: 54mm; display: grid; grid-template-columns: 1fr 1fr; } .left{ padding: 10px 10px 10px 12px; border-right: 1px dashed #d6dbe6; } .right{ padding: 10px 12px 10px 10px; position: relative; } .brand{ display:flex; align-items:center; justify-content:space-between; gap: 10px; margin-bottom: 8px; } .title{ font-weight: 800; font-size: 14px; letter-spacing: 0.2px; color: #0b1220; } .badge{ font-weight: 800; font-size: 12px; padding: 4px 8px; border-radius: 999px; background: #eaf1ff; color: #1b4fd6; border: 1px solid #cfe0ff; white-space: nowrap; } .creds{ border: 1px solid #e7ebf3; border-radius: 10px; padding: 8px 10px; background: #f8fafc; margin-bottom: 8px; } .rowline{ display:flex; justify-content: space-between; gap: 10px; font-size: 12px; line-height: 1.4; } .k{ color: #334155; font-weight: 700; } .v{ font-family: Consolas, "Courier New", monospace; font-weight: 800; color: #0b1220; word-break: break-all; text-align: right; } .meta{ font-size: 11px; line-height: 1.45; color: #334155; } .strong{ font-weight: 800; color: #0b1220; } .qrwrap{ display:flex; align-items:center; justify-content:center; height: 100%; min-height: 54mm; } .qr{ width: 110px; height: 110px; display:flex; align-items:center; justify-content:center; border: 1px solid #e7ebf3; border-radius: 12px; background: #ffffff; } .hint{ position:absolute; left: 10px; right: 10px; bottom: 10px; font-size: 10px; color: #475569; text-align: center; } .dot{ display:inline-block; width: 6px; height: 6px; border-radius: 999px; background: #22c55e; margin-right: 6px; vertical-align: middle; } </style> <script> var HOTSPOT_LOGIN_URL = "http://10.10.10.1/login"; var QR_MODE = "direct"; var QR_PROXY_URL = "http://10.10.10.1/qrlogin.html"; function buildQrText(u, p){ var eu = encodeURIComponent(u || ""); var ep = encodeURIComponent(p || ""); if(QR_MODE === "proxy"){ return QR_PROXY_URL + "?u=" + eu + "&p=" + ep; } return HOTSPOT_LOGIN_URL + "?username=" + eu + "&password=" + ep; } function renderAllQrs(){ if(typeof QRCode === "undefined"){ return; } var cards = document.querySelectorAll(".voucher[data-u][data-p]"); for(var i=0;i<cards.length;i++){ var card = cards[i]; var u = card.getAttribute("data-u") || ""; var p = card.getAttribute("data-p") || ""; var qrBox = card.querySelector(".qr"); if(!qrBox) continue; while(qrBox.firstChild) qrBox.removeChild(qrBox.firstChild); var qrText = buildQrText(u, p); new QRCode(qrBox, { text: qrText, width: 104, height: 104, correctLevel: QRCode.CorrectLevel.M }); } } if(document.readyState === "loading"){ document.addEventListener("DOMContentLoaded", renderAllQrs); } else { renderAllQrs(); } </script> </head> <body> <div class="sheet"> <div class="grid">
Row A4 grid
<div class="voucher" data-u="%u_username%" data-p="%u_password%"> <div class="left"> <div class="brand"> <div class="title">VOUCHER HOTSPOT</div> <div class="badge">Rp %u_moneyPaid%</div> </div> <div class="creds"> <div class="rowline"> <div class="k">User</div> <div class="v">%u_username%</div> </div> <div class="rowline"> <div class="k">Pass</div> <div class="v">%u_password%</div> </div> </div> <div class="meta"> <div>Durasi: <span class="strong">%u_limitUptime%</span></div> <div>Sisa aktif: <span class="strong">%u_timeLeft%</span></div> <div>Kuota: <span class="strong">%u_limitDownload%</span></div> <div>Shared: <span class="strong">%u_shared_users%</span> user</div> </div> </div> <div class="right"> <div class="qrwrap"> <div class="qr"></div> </div> <div class="hint"><span class="dot"></span>Scan QR untuk login cepat</div> </div> </div>
Footer A4 grid
</div> </div> <script> try { renderAllQrs(); } catch(e) {} </script> </body> </html>
Break A4 grid
Break ini opsional. Jika layout printer memotong tidak konsisten, aktifkan.
<div style="page-break-after: always;"></div>
Source code modern versi thermal printer, 1 kolom
Versi ini cocok untuk printer thermal. Lebih ringkas, lebih padat, dan fokus pada scan QR.
Header thermal
<!doctype html> <html lang="id"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Voucher Thermal</title> <script src="https://cdnjs.cloudflare.com/ajax/libs/qrcodejs/1.0.0/qrcode.min.js"></script> <style> @page { size: 80mm auto; margin: 0; } body{ margin:0; padding:0; font-family: Arial, Helvetica, sans-serif; background: #ffffff; color: #111827; } .wrap{ width: 72mm; margin: 0 auto; padding: 6mm 4mm; } .box{ border: 1px solid #e5e7eb; border-radius: 10px; padding: 10px; } .brand{ font-weight: 900; font-size: 14px; text-align: center; margin-bottom: 6px; } .sub{ text-align: center; font-size: 11px; color: #4b5563; margin-bottom: 10px; } .mono{ font-family: Consolas, "Courier New", monospace; font-weight: 900; letter-spacing: 0.2px; } .line{ display:flex; justify-content: space-between; gap: 10px; font-size: 12px; margin: 4px 0; } .qr{ width: 180px; height: 180px; margin: 10px auto 6px auto; display:flex; align-items:center; justify-content:center; } .foot{ text-align: center; font-size: 10px; color: #6b7280; margin-top: 6px; } </style> <script> var HOTSPOT_LOGIN_URL = "http://10.10.10.1/login"; function buildQrText(u, p){ return HOTSPOT_LOGIN_URL + "?username=" + encodeURIComponent(u || "") + "&password=" + encodeURIComponent(p || ""); } function renderAllQrs(){ if(typeof QRCode === "undefined"){ return; } var cards = document.querySelectorAll(".box[data-u][data-p]"); for(var i=0;i<cards.length;i++){ var card = cards[i]; var u = card.getAttribute("data-u") || ""; var p = card.getAttribute("data-p") || ""; var qrBox = card.querySelector(".qr"); if(!qrBox) continue; while(qrBox.firstChild) qrBox.removeChild(qrBox.firstChild); new QRCode(qrBox, { text: buildQrText(u, p), width: 170, height: 170, correctLevel: QRCode.CorrectLevel.M }); } } if(document.readyState === "loading"){ document.addEventListener("DOMContentLoaded", renderAllQrs); } else { renderAllQrs(); } </script> </head> <body> <div class="wrap">
Row thermal
<div class="box" data-u="%u_username%" data-p="%u_password%"> <div class="brand">HOTSPOT VOUCHER</div> <div class="sub">Scan QR untuk login cepat</div> <div class="line"><div>User</div><div class="mono">%u_username%</div></div> <div class="line"><div>Pass</div><div class="mono">%u_password%</div></div> <div class="line"><div>Durasi</div><div>%u_limitUptime%</div></div> <div class="line"><div>Kuota</div><div>%u_limitDownload%</div></div> <div class="qr"></div> <div class="foot">Harga Rp %u_moneyPaid%</div> </div>
Footer thermal
<script> try { renderAllQrs(); } catch(e) {} </script> </div> </body> </html>
Opsi modern tambahan, QR mode proxy untuk login via POST
Mode direct mengirim username dan password lewat query string. Ini cepat dan sederhana. Mode proxy mengarahkan QR ke halaman perantara yang melakukan POST ke endpoint login. Ini lebih fleksibel dan lebih mudah diubah tanpa menyentuh template voucher.
Cara pakai mode proxy
Ubah QR_MODE menjadi proxy di Header A4 grid.
Pastikan QR_PROXY_URL mengarah ke qrlogin.html.
Host qrlogin.html di web server yang bisa diakses user saat terhubung ke hotspot.
Source code qrlogin.html
<!doctype html> <html lang="id"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>QR Login</title> </head> <body> <form id="f" method="post" action="/login"> <input type="hidden" name="username" id="u"> <input type="hidden" name="password" id="p"> </form> <script> function getParam(name){ var url = new URL(window.location.href); return url.searchParams.get(name) || ""; } document.getElementById("u").value = getParam("u"); document.getElementById("p").value = getParam("p"); document.getElementById("f").submit(); </script> </body> </html>
Integrasi sistem dengan hotspot MikroTik
Agar template dan QR berjalan stabil, fokus pada 4 titik ini.
Hotspot memakai RADIUS. Pastikan service hotspot aktif di konfigurasi RADIUS.
Secret konsisten. Secret di router harus sama dengan secret di User Manager.
Profile selaras. Profile user di User Manager harus sesuai kebijakan hotspot yang kamu pakai.
URL login benar. HOTSPOT_LOGIN_URL harus sesuai endpoint login hotspot kamu. Umumnya /login.
Masalah umum dan cara cepat mengatasinya
QR Code muncul tapi tidak bisa login
Periksa HOTSPOT_LOGIN_URL. Pastikan IP benar dan endpoint /login benar.
Pastikan hotspot redirect ke halaman login yang sama.
Uji akses URL login dari perangkat user saat terhubung ke SSID hotspot.
QR Code tidak muncul sama sekali
Jika pakai CDN, pastikan perangkat yang digunakan untuk cetak punya akses internet.
Jika cetak offline, pakai opsi lokal dan host qrcode.min.js di server lokal.
Pastikan browser tidak memblokir script eksternal.
Hasil cetak terpotong atau jarak tidak rapi
Ubah gap pada grid A4. Coba 6mm sampai 10mm.
Aktifkan Break jika printer memotong di titik yang tidak konsisten.
Untuk thermal, pastikan ukuran page 80mm dan margin 0.
Bagian yang menurut saya paling mantap untuk kamu tambahkan
- Hardening ringan untuk voucher
Gunakan password voucher yang tidak mudah ditebak.
Batasi shared user sesuai kebutuhan, misalnya 1 atau 2.
Batasi masa aktif. Gunakan uptime limit dan validity yang jelas.
Jika hotspot publik besar, pertimbangkan mode proxy untuk kontrol redirect. - Informasi yang meningkatkan kepercayaan pengguna
Tampilkan nama hotspot yang konsisten, termasuk domain atau IP login.
Tampilkan durasi dan kuota dengan istilah yang mudah dipahami.
Tampilkan kontak admin atau helpdesk singkat. - Optimasi produksi voucher
Untuk A4, buat layout 2 kolom atau 3 kolom sesuai ukuran voucher.
Untuk thermal, gunakan QR minimal 170×170 untuk scan cepat.
Simpan template versi A4 dan thermal sebagai dua template terpisah.
Studi kasus implementasi di lingkungan nyata
Pada hotspot publik dengan ratusan user harian, QR voucher menurunkan friksi login. Pengguna tidak lagi mengetik kredensial. Komplain turun. Staf lebih fokus pada operasional. Admin juga lebih cepat saat distribusi voucher karena bisa cetak massal atau kirim digital.
Faktor pendukung dan penghambat
Faktor pendukung.
User Manager stabil untuk manajemen voucher massal
QR Code kompatibel dengan hampir semua smartphone
Template HTML fleksibel untuk branding dan cetak
Faktor penghambat.
Router dengan resource terbatas bisa lambat saat generate besar
URL login salah akan membuat QR gagal login
CDN tidak bisa diakses saat jaringan cetak offline, gunakan file lokal
Strategi implementasi modern yang direkomendasikan
Gunakan library QR lokal jika sering cetak offline.
Uji QR di beberapa perangkat, terutama kamera low end.
Jaga background QR putih dan kontras tinggi.
Gunakan mode proxy jika kamu butuh fleksibilitas alur login dan redirect.
Tuning yang wajib kamu ganti
HOTSPOT_LOGIN_URL. Ganti dengan IP atau domain hotspot kamu. Contoh http://10.10.10.1/login
Brand dan identitas. Ubah judul voucher, harga, dan identitas layanan.
Layout grid. Default 2 kolom untuk A4. Ubah jika butuh 3 kolom.
Ukuran QR. Naikkan untuk thermal agar scan lebih cepat.
Tambahan tuning khusus untuk layout gambar wifi card
ASSET_CARD_URL. Isi URL gambar wifi card dari WordPress.
HOTSPOT_SSID_NAME. Isi nama SSID yang tampil di instruksi.
Posisi konten. Atur padding .left dan .right agar sejajar dengan elemen pada gambar.
Area QR. Pastikan .qrBox background putih, jangan transparan.
Kesimpulan dan ringkasan insight
Template voucher User Manager MikroTik yang terintegrasi QR Code Generator memberi dua manfaat utama. Kontrol akses tetap ketat dari sisi RADIUS. Pengalaman login menjadi cepat dari sisi pengguna. Dengan desain template modern dan render QR otomatis, kamu bisa meningkatkan kualitas layanan hotspot tanpa mengubah arsitektur dasar jaringan.



