+
diff --git a/pages/ganerate_voucher.php b/pages/ganerate_voucher.php
index 5ca3a8f..173bbc6 100644
--- a/pages/ganerate_voucher.php
+++ b/pages/ganerate_voucher.php
@@ -1,4 +1,10 @@
-
+
+
+
+
+beginTransaction();
+
+ // Ambil data paket
+ $stmt = $pdo->prepare("SELECT radius_data,durasi,nama_profile,harga_paket FROM profile_paket WHERE id = :idp");
+ $stmt->execute([':idp' => $_POST['idp']]);
+ $paket = $stmt->fetch(PDO::FETCH_ASSOC);
+
+ // ====== KIRIM KE API MIKROTIK ======
+ $stmt = $pdo->prepare("SELECT ip_address,username,password,port_api,radius_nas_data FROM setting_mikrotik WHERE id = :id");
+ $stmt->execute([':id' => $_POST['idm']]);
+ $mikrotik = $stmt->fetch(PDO::FETCH_ASSOC);
+
+ $dataMik = json_decode($mikrotik['radius_nas_data']);
+
+ if (!$paket) {
+ throw new Exception("Paket tidak ditemukan.");
+ }
+
+ $data = json_decode($paket['radius_data']);
+ $kode = $data ? 'VR' : 'VM'; // VR = Radius, VM = MikroTik
+ $jenis = $data ? 'sv-radius' : 'sv-mikrotik';
+ $karakter = "QWERTYUIOPASDFGHJKLZXCVBNM1234567890qwertyuiopasdfghjklzxcvbnm";
+ $str = $paket['durasi'];
+ $jumlah = intval($_POST['jumlah']);
+ $date = date('Y-m-d H:i:s');
+
+ // Validasi jumlah
+ if ($jumlah < 1 || $jumlah > 200) {
+ throw new Exception("Jumlah voucher harus antara 1-200.");
+ }
+
+ // Generate voucher unik
+ $voucherList = [];
+ while (count($voucherList) < $jumlah) {
+ $kodevoucher = $str . substr(str_shuffle($karakter), 0, 7) . $kode;
+
+ // Pastikan tidak duplikat di DB & array
+ $cek = $pdo->prepare("SELECT COUNT(*) FROM ganerate_voucher WHERE voucher = :voucher");
+ $cek->execute([':voucher' => $kodevoucher]);
+ if ($cek->fetchColumn() == 0 && !in_array($kodevoucher, $voucherList)) {
+ $voucherList[] = $kodevoucher;
+ }
+ }
+
+ // Kirim ke Radius atau MikroTik
+ $successVoucher = [];
+ $failVoucher = [];
+
+ if ($data) {
+ // ====== KIRIM KE RADIUS ======
+ $radius = new CrudRadiusServer();
+ $apiResponse = $radius->request('add_user', 'POST', [
+ 'jenis' => 'Hotspot',
+ 'username' => $voucherList,
+ 'password' => $voucherList,
+ 'groupname' => $data->groupname,
+ 'nasgroupname' => $dataMik->data->{'nasgroupname'}
+ ]);
+
+ foreach ($apiResponse['results'] as $res) {
+ if ($res['status'] === 'success') {
+ $successVoucher[] = $res['username'];
+ } else {
+ $failVoucher[] = $res['username'];
+ }
+ }
+
+ if (empty($successVoucher)) {
+ throw new Exception("Tidak ada voucher yang berhasil dibuat di Radius.");
+ }
+ } else {
+
+ require('router_api/routeros_api.class.php');
+ $API = new RouterosAPI();
+ $API->debug = false;
+
+ if (!$API->connect2($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password'], $mikrotik['port_api'])) {
+ throw new Exception("Gagal konek ke API MikroTik.");
+ }
+
+ foreach ($voucherList as $vcr) {
+ $result = $API->comm('/ip/hotspot/user/add', [
+ "name" => $vcr,
+ "password" => $vcr,
+ "profile" => $paket['nama_profile'], // pastikan field profile ada di DB
+ "server" => "all"
+ ]);
+
+ if (isset($result['!trap'])) {
+ $failVoucher[] = $vcr;
+ } else {
+ $successVoucher[] = $vcr;
+ }
+ }
+
+ $API->disconnect();
+
+ if (empty($successVoucher)) {
+ throw new Exception("Tidak ada voucher yang berhasil dibuat di MikroTik.");
+ }
+ }
+
+ // Insert ke DB hanya yang sukses
+ $values = [];
+ $params = [];
+ foreach ($successVoucher as $voucher) {
+ $values[] = "(?, ?, ?, ?, ?, ?, ?)";
+ $params[] = $_POST['ids']; // id_data_server
+ $params[] = $_POST['idm']; // id_setting_mikrotik
+ $params[] = $_POST['idp']; // id_profile_paket
+ $params[] = $voucher; // voucher
+ $params[] = $paket['harga_paket']; // harga
+ $params[] = $jenis; // jenis
+ $params[] = $date; // create_time
+ }
+
+ $sql = "INSERT INTO ganerate_voucher
+ (id_data_server, id_setting_mikrotik, id_profile_paket, voucher, harga, jenis, create_time)
+ VALUES " . implode(", ", $values);
+ $stmt = $pdo->prepare($sql);
+ $stmt->execute($params);
+
+ // Commit transaksi
+ $pdo->commit();
+
+ $totalSuccess = count($successVoucher);
+ $totalError = count($failVoucher);
+
+ sweetAlert("$totalSuccess voucher berhasil dibuat. Gagal: $totalError", "success");
+ } catch (Exception $e) {
+ $pdo->rollBack();
+ // sweetAlert("Gagal membuat voucher: " . $e->getMessage(), "error");
+ }
+}
+?>
+
-
+
+
+
+set_list("setting_mikrotik", $SqlDataWHId);
+?>
+
Mikrotik
+
+
+
Login Page Script
+
+
+
+ Loading script...
+
+
+
+");
+ navigator.clipboard.writeText(text).then(() => {
+ // console.log("Script berhasil disalin!");
+ });
+}
+
+
+
+
+
+
+
+
-
+
- Akumulasi Voucher
+ Voucher List
-
+
+
+
+ | Waktu |
+ Voucher |
+ Harga |
+ Biaya |
+ Saldo |
+ Status |
+ Aktif |
+ Expired |
+
+
+
@@ -227,3 +477,43 @@
// Panggil fungsi setDefaultMonth saat halaman dimuat
window.onload = fetchDataAgen();
+
+
+
+
+
diff --git a/pages/profile_paket.php b/pages/profile_paket.php
index 89078c8..78d95f5 100644
--- a/pages/profile_paket.php
+++ b/pages/profile_paket.php
@@ -41,17 +41,28 @@
+
-
@@ -94,118 +125,213 @@
- beginTransaction();
+
+ // Ambil semua server
$stmt = $pdo->prepare("SELECT * FROM setting_mikrotik WHERE id_data_server = :id_data_server");
$stmt->execute([':id_data_server' => $_POST['ids']]);
$servers = $stmt->fetchAll(PDO::FETCH_ASSOC);
- $messages = []; // Array untuk menyimpan pesan
+ $rollbackServers = [];
+ $messages = []; // pesan error
+ // === RADIUS PROCESS ===
+ if (!empty($_POST['radiuscek']) && $_POST['radiuscek'] == 1) {
+ $radius = new CrudRadiusServer();
+
+ $radiusPayload = [
+ 'jenis' => $_POST['jenis'],
+ 'groupname' => $groupname,
+ 'profile' => $profile,
+ 'use_limit' => $use_limit,
+ 'rate_limit' => $rate_limit,
+ 'session_time' => $session_time,
+ 'ip_pool' => $ip_pool,
+ 'idle_time' => $idle_time
+ ];
+
+ $radius->request('add_paket', 'POST', $radiusPayload);
+ $radius_data = json_encode($radiusPayload);
+ } else {
+ $radius_data = '';
+ }
+
+ // === LOOPING SERVER MIKROTIK ===
foreach ($servers as $server) {
$mikrotikName = $server['nama'];
$API = new RouterosAPI();
$API->debug = false;
- // Koneksi ke MikroTik
- if ($API->connect2($server['ip_address'], $server['username'], $server['password'], $server['port_api'])) {
- $profileName = $_POST['profile'];
+ if ($API->connect2(
+ $server['ip_address'],
+ $server['username'],
+ $server['password'],
+ $server['port_api']
+ )) {
+ $profileName = $_POST['profile'] ?? '';
+ $ipPool = $_POST['ip_pool'] ?? '';
+ $profileFound = false;
+ $poolFound = false;
+ // === CEK PROFILE ===
if ($_POST['jenis'] == 'PPPOE') {
- // Cek profil PPPOE
$profiles = $API->comm('/ppp/profile/print');
- $found = false;
+ } elseif ($_POST['jenis'] == 'Hotspot') {
+ $profiles = $API->comm('/ip/hotspot/user/profile/print');
+ }
- foreach ($profiles as $profile) {
- if ($profile['name'] === $profileName) {
- $found = true;
+ if (!empty($profiles)) {
+ foreach ($profiles as $p) {
+ if ($p['name'] === $profileName) {
+ $profileFound = true;
break;
}
}
-
- if (!$found) {
- $messages[] = "Profil PPPOE
$profileName di
$mikrotikName tidak ada.";
- }
} else {
- // Cek profil Hotspot
- $profiles = $API->comm('/ip/hotspot/user/profile/print');
- $found = false;
- $profileId = null;
+ $profileFound = true;
+ }
- foreach ($profiles as $profile) {
- if ($profile['name'] === $profileName) {
- $profileId = $profile['.id'];
- $found = true;
- break;
+ // === CEK IP POOL (HANYA UNTUK DHCP & HOTSPOT) ===
+ if (!empty($ipPool) && ($_POST['jenis'] == 'DHCP')) {
+ $poolcek = $API->comm('/ip/pool/print');
+ if (!empty($poolcek)) {
+ foreach ($poolcek as $pool) {
+ if ($pool['name'] === $ipPool) {
+ $poolFound = true;
+ break;
+ }
}
}
-
- if ($found) {
- // Jika status sama dengan 1
- if ($status == 1 ) {
- // Pastikan intervalFormat() sudah terdefinisi
- $interval = intervalFormat($_POST['durasi']);
-
- // Skrip On Login yang akan dipasang
- $onLoginScript = ':local nama $user; :local tanggal [/system clock get date]; :local waktu [/system clock get time]; :if ([/ip hotspot user get [find name=$nama] comment] = "") do={/ip hotspot user set [find name=$nama] comment="Login.$tanggal $waktu"; :log warning ("User " . $nama . " berhasil login.")} else={:log warning ("User " . $nama . " berhasil melakukan login ulang.")}; :if ([/system schedule find name=$nama] = "") do={/system schedule add name=$nama interval='.$interval.' on-event="/ip hotspot active remove [find user=$nama]; /ip hotspot user remove [find name=$nama]; /system schedule remove [find name=$nama]" start-date=$tanggal start-time=$waktu;}';
-
- // Update skrip On Login
- $API->comm('/ip/hotspot/user/profile/set', [
- '.id' => $profileId,
- 'on-login' => $onLoginScript,
- ]);
- }
- // else {
- // $messages[] = "Gagal Upload Script: Profil Hotspot
$profileName di
$mikrotikName tidak aktif atau status tidak sesuai.";
- // }
- } else {
- $messages[] = "Profil Hotspot
$profileName di
$mikrotikName tidak ditemukan.";
- }
+ } else {
+ // Jika tidak perlu IP Pool, dianggap ditemukan
+ $poolFound = true;
}
+
+ // === VALIDASI PROFILE & IP POOL ===
+ if (!$profileFound) {
+ $messages[] = "Profil
$profileName di
$mikrotikName tidak ditemukan.";
+ break; // gagal -> keluar loop
+ }
+
+ if (!$poolFound) {
+ $messages[] = "IP Pool
$ipPool di
$mikrotikName tidak ditemukan.";
+ break; // gagal -> keluar loop
+ }
+
+ // === JIKA HOTSPOT & STATUS AKTIF -> SET ON-LOGIN SCRIPT ===
+ if ($_POST['jenis'] == 'Hotspot' && $status == 1 && empty($_POST['radiuscek'])) {
+ $interval = intervalFormat($_POST['durasi']);
+ $onLoginScript = ':local nama $user; :local tanggal [/system clock get date]; :local waktu [/system clock get time]; :if ([/ip hotspot user get [find name=$nama] comment] = "") do={/ip hotspot user set [find name=$nama] comment="Login.$tanggal $waktu"; :log warning ("User " . $nama . " berhasil login.")} else={:log warning ("User " . $nama . " berhasil melakukan login ulang.")}; :if ([/system schedule find name=$nama] = "") do={/system schedule add name=$nama interval='.$interval.' on-event="/ip hotspot active remove [find user=$nama]; /ip hotspot user remove [find name=$nama]; /system schedule remove [find name=$nama]" start-date=$tanggal start-time=$waktu;}';
+
+ $API->comm('/ip/hotspot/user/profile/set', [
+ '.id' => $p['.id'],
+ 'on-login' => $onLoginScript,
+ ]);
+ }
+
+ // Catat server yang berhasil untuk rollback jika ada error nanti
+ $rollbackServers[] = $server;
} else {
$messages[] = "Gagal terhubung ke MikroTik
$mikrotikName.";
+ break; // gagal -> langsung keluar loop
}
}
- // Cek pesan sebelum menyimpan ke database
- if (empty($messages)) {
- $stmt = $pdo->prepare("INSERT INTO profile_paket
- (id_data_server, jenis_profile, nama_profile, durasi, nama, harga_paket, vi_agen, status)
- VALUES (:id_data_server, :jenis_profile, :nama_profile, :durasi, :nama, :harga_paket, :vi_agen, :status)");
- $stmt->bindParam(':id_data_server', $_POST['ids']);
- $stmt->bindParam(':jenis_profile', $_POST['jenis']);
- $stmt->bindParam(':nama_profile', $_POST['profile']);
- $stmt->bindParam(':durasi', $_POST['durasi']);
- $stmt->bindParam(':nama', $_POST['nama']);
- $stmt->bindParam(':harga_paket', $nominal);
- $stmt->bindParam(':vi_agen', $fee);
- $stmt->bindParam(':status', $status);
- $stmt->execute();
- sweetAlert("Profile Paket Telah ditambahkan", "success");
- } else {
- // Menampilkan pesan error jika ada
+
+ // === CEK ERROR DAN ROLLBACK JIKA PERLU ===
+ if (!empty($messages)) {
+ // Rollback ke DB
+ $pdo->rollBack();
+
+ // Rollback radius jika ada
+ if (!empty($_POST['radiuscek']) && $_POST['radiuscek'] == 1) {
+ $radius->request('delete_paket', 'DELETE', [
+ 'groupname' => $groupname
+ ]);
+ }
+
+ // Rollback ke server yang sudah diproses
+ foreach ($rollbackServers as $srv) {
+ $API = new RouterosAPI();
+ if ($API->connect2($srv['ip_address'], $srv['username'], $srv['password'], $srv['port_api'])) {
+ if ($_POST['jenis'] == 'PPPOE') {
+ $API->comm('/ppp/profile/remove', [
+ 'numbers' => $profileName
+ ]);
+ } else {
+ $API->comm('/ip/hotspot/user/profile/remove', [
+ 'numbers' => $profileName
+ ]);
+ }
+ }
+ }
+
$message = implode("
", $messages);
- detailAlert($message, strpos($message, 'tidak ada') !== false || strpos($message, 'Gagal') !== false);
+ detailAlert("Rollback! $message", true);
+ return;
}
+ // === SIMPAN KE DATABASE ===
+ $stmt = $pdo->prepare("INSERT INTO profile_paket
+ (id_data_server, jenis_profile, nama_profile, durasi, nama, harga_paket, vi_agen, status, radius_data)
+ VALUES (:id_data_server, :jenis_profile, :nama_profile, :durasi, :nama, :harga_paket, :vi_agen, :status, :radius_data)");
+ $stmt->bindParam(':id_data_server', $_POST['ids']);
+ $stmt->bindParam(':jenis_profile', $_POST['jenis']);
+ $stmt->bindParam(':nama_profile', $_POST['profile']);
+ $stmt->bindParam(':durasi', $_POST['durasi']);
+ $stmt->bindParam(':nama', $_POST['nama']);
+ $stmt->bindParam(':harga_paket', $nominal);
+ $stmt->bindParam(':vi_agen', $fee);
+ $stmt->bindParam(':status', $status);
+ $stmt->bindParam(':radius_data', $radius_data);
+ $stmt->execute();
+
+ $pdo->commit(); // commit transaksi
+ sweetAlert("Profile Paket Telah ditambahkan", "success");
+
} catch (PDOException $e) {
- // Menangani kesalahan dalam koneksi database atau query
- sweetAlert("Terjadi kesalahan: " . $e->getMessage(), "error");
+ $pdo->rollBack();
+ sweetAlert("Terjadi kesalahan DB: " . $e->getMessage(), "error");
} catch (Exception $e) {
- // Menangani kesalahan umum
+ $pdo->rollBack();
sweetAlert("Terjadi kesalahan: " . $e->getMessage(), "error");
}
}
?>
+