Update Voucher , Tiket , Dashboard
membuat perubahan dan update
This commit is contained in:
@@ -0,0 +1,21 @@
|
||||
$api = new CrudRadiusServer();
|
||||
|
||||
// Tambah user
|
||||
$api->request('add_user', 'POST', [
|
||||
'username' => 'test123',
|
||||
'password' => 'pass123'
|
||||
]);
|
||||
|
||||
// Update user
|
||||
$api->request('update_user', 'PUT', [
|
||||
'username' => 'test123',
|
||||
'password' => 'newpass'
|
||||
]);
|
||||
|
||||
// Hapus user
|
||||
$api->request('delete_user', 'DELETE', [
|
||||
'username' => 'test123'
|
||||
]);
|
||||
|
||||
// Ambil semua user
|
||||
$api->request('get_all', 'GET');
|
||||
@@ -0,0 +1,266 @@
|
||||
<?php
|
||||
|
||||
// /interface l2tp-client
|
||||
// add name=l2tp-out1 connect-to=tunnel.manjapro.net user=nta1cicukang password=nta1cicukang profile=default-encryption add-default-route=no disabled=no
|
||||
|
||||
// /ip firewall nat
|
||||
// add chain=dstnat dst-address-list=IP-Public protocol=tcp dst-port=8229 action=dst-nat to-addresses=172.18.1.206 to-ports=8728 comment="NTA 1 Cicukang"
|
||||
// add chain=dstnat dst-address-list=IP-Public protocol=tcp dst-port=144 action=dst-nat to-addresses=172.18.1.206 to-ports=144 comment="NTA 1 Cicukang"
|
||||
// /
|
||||
|
||||
|
||||
class CreateTunnel
|
||||
{
|
||||
public function addTunnel($Secret,$nasGroup)
|
||||
{
|
||||
// include "config/connect.php";
|
||||
// include "config/routeros_api.class.php";
|
||||
|
||||
$mikrotik = new RouterosAPI();
|
||||
$mikrotik->debug = false;
|
||||
|
||||
// Connect ke MikroTik
|
||||
if ($mikrotik->connect2('manjapro.net', 'apiapkmanjapro', 'apiapkmanjapro123321', '2887')) {
|
||||
|
||||
// Ambil semua remote-address yang sudah dipakai
|
||||
$secrets = $mikrotik->comm('/ppp/secret/print', [
|
||||
"?local-address" => "172.18.1.100"
|
||||
]);
|
||||
|
||||
$maxIp = 0;
|
||||
foreach ($secrets as $secret) {
|
||||
if (isset($secret['remote-address']) && filter_var($secret['remote-address'], FILTER_VALIDATE_IP)) {
|
||||
$ipParts = explode('.', $secret['remote-address']);
|
||||
if (count($ipParts) == 4 && $ipParts[0] == '172' && $ipParts[1] == '18' && $ipParts[2] == '1') {
|
||||
$lastOctet = (int)$ipParts[3];
|
||||
if ($lastOctet > $maxIp) {
|
||||
$maxIp = $lastOctet;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Hitung remote-address baru
|
||||
$nextIp = $maxIp + 1;
|
||||
$remoteAddress = "172.18.1." . $nextIp;
|
||||
|
||||
// Local address (bisa fix atau ambil dari pool)
|
||||
$localAddress = "172.18.1.100";
|
||||
|
||||
// ==============================
|
||||
// Ambil semua dst-port yang sudah digunakan
|
||||
// ==============================
|
||||
$natRules = $mikrotik->comm('/ip/firewall/nat/print');
|
||||
$usedPorts = [];
|
||||
|
||||
foreach ($natRules as $rule) {
|
||||
if (isset($rule['dst-port'])) {
|
||||
$ports = explode(',', $rule['dst-port']);
|
||||
foreach ($ports as $p) {
|
||||
$usedPorts[] = (int)$p;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Cari 2 port yang bebas mulai dari 2000
|
||||
$startPort = 200;
|
||||
$freePorts = [];
|
||||
while (count($freePorts) < 2) {
|
||||
if (!in_array($startPort, $usedPorts)) {
|
||||
$freePorts[] = $startPort;
|
||||
}
|
||||
$startPort++;
|
||||
if ($startPort > 9999) { // Batas port TCP
|
||||
break; // Hindari infinite loop
|
||||
}
|
||||
}
|
||||
|
||||
if (count($freePorts) < 2) {
|
||||
return [
|
||||
'status' => false,
|
||||
'message' => 'Tidak ada 2 port bebas yang tersedia'
|
||||
];
|
||||
}
|
||||
|
||||
$port1 = $freePorts[0];
|
||||
$port2 = $freePorts[1];
|
||||
|
||||
// ==============================
|
||||
// Generate user/pass
|
||||
// ==============================
|
||||
$secretUser = strtolower(preg_replace('/[^a-z0-9]/i', '', substr($Secret, 0, 12))) . "@manjapro.net";
|
||||
$secretPass = strtolower(substr(md5($secretUser), 0, 12));
|
||||
$nasSecret = substr(md5($secretUser), 0, 20);
|
||||
|
||||
// Tambahkan PPP secret
|
||||
$add = $mikrotik->comm('/ppp/secret/add', [
|
||||
"name" => $secretUser,
|
||||
"password" => $secretPass,
|
||||
"profile" => "default-encryption",
|
||||
"local-address" => $localAddress,
|
||||
"remote-address" => $remoteAddress,
|
||||
"service" => "any",
|
||||
"comment" => $Secret
|
||||
]);
|
||||
|
||||
// Tambahkan 2 firewall NAT rules
|
||||
$nat1 = $mikrotik->comm('/ip/firewall/nat/add', [
|
||||
"chain" => "dstnat",
|
||||
"dst-address-list" => "IP-Public",
|
||||
"dst-port" => $port1,
|
||||
"protocol" => "tcp",
|
||||
"action" => "dst-nat",
|
||||
"to-addresses" => $remoteAddress,
|
||||
"to-ports" => $port1,
|
||||
"comment" => $Secret
|
||||
]);
|
||||
|
||||
$nat2 = $mikrotik->comm('/ip/firewall/nat/add', [
|
||||
"chain" => "dstnat",
|
||||
"dst-address-list" => "IP-Public",
|
||||
"dst-port" => $port2,
|
||||
"protocol" => "tcp",
|
||||
"action" => "dst-nat",
|
||||
"to-addresses" => $remoteAddress,
|
||||
"to-ports" => $port2,
|
||||
"comment" => $Secret
|
||||
]);
|
||||
|
||||
$mikrotik->disconnect();
|
||||
|
||||
// Siapkan data response
|
||||
$data = [
|
||||
"name" => $secretUser,
|
||||
"password" => $secretPass,
|
||||
"profile" => "default-encryption",
|
||||
"local-address" => $localAddress,
|
||||
"remote-address" => $remoteAddress,
|
||||
"service" => "any",
|
||||
"nas_secret" => $nasSecret,
|
||||
"nasgroupname" => $nasGroup,
|
||||
"port-api" => $port1,
|
||||
"port-remote" => $port2
|
||||
];
|
||||
|
||||
return json_encode( [
|
||||
'status' => true,
|
||||
'message' => 'PPP secret dan NAT berhasil dibuat',
|
||||
'data' => $data
|
||||
] );
|
||||
} else {
|
||||
return json_encode ([
|
||||
'status' => false,
|
||||
'message' => 'Gagal terhubung ke MikroTik'
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
public function deleteTunnel($Data)
|
||||
{
|
||||
$data = json_decode($Data);
|
||||
|
||||
// Validasi data yang diterima
|
||||
if (!isset($data->data->{'name'}) || !isset($data->data->{'port-api'}) || !isset($data->data->{'port-remote'})) {
|
||||
http_response_code(400);
|
||||
echo json_encode([
|
||||
'success' => false,
|
||||
'message' => "Data tidak lengkap untuk menghapus tunnel"
|
||||
]);
|
||||
return;
|
||||
}
|
||||
|
||||
$name = $data->data->{'name'};
|
||||
$portApi = $data->data->{'port-api'};
|
||||
$portRemote = $data->data->{'port-remote'};
|
||||
|
||||
$mikrotik = new RouterosAPI();
|
||||
$mikrotik->debug = false;
|
||||
|
||||
// Connect ke MikroTik
|
||||
if ($mikrotik->connect2('manjapro.net', 'apiapkmanjapro', 'apiapkmanjapro123321', 2887)) {
|
||||
|
||||
try {
|
||||
// Hapus PPP Secret
|
||||
$pppSecrets = $mikrotik->comm('/ppp/secret/print', [
|
||||
"?name" => $name
|
||||
]);
|
||||
|
||||
if (!empty($pppSecrets)) {
|
||||
foreach ($pppSecrets as $secret) {
|
||||
if (isset($secret['.id'])) {
|
||||
$mikrotik->comm('/ppp/secret/remove', [
|
||||
".id" => $secret['.id']
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Hapus NAT untuk port-api
|
||||
$natApi = $mikrotik->comm('/ip/firewall/nat/print', [
|
||||
"?dst-port" => $portApi
|
||||
]);
|
||||
|
||||
if (!empty($natApi)) {
|
||||
foreach ($natApi as $rule) {
|
||||
if (isset($rule['.id'])) {
|
||||
$mikrotik->comm('/ip/firewall/nat/remove', [
|
||||
".id" => $rule['.id']
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Hapus NAT untuk port-remote
|
||||
$natRemote = $mikrotik->comm('/ip/firewall/nat/print', [
|
||||
"?dst-port" => $portRemote
|
||||
]);
|
||||
|
||||
if (!empty($natRemote)) {
|
||||
foreach ($natRemote as $rule) {
|
||||
if (isset($rule['.id'])) {
|
||||
$mikrotik->comm('/ip/firewall/nat/remove', [
|
||||
".id" => $rule['.id']
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$mikrotik->disconnect();
|
||||
|
||||
// Kirim respon sukses
|
||||
http_response_code(200);
|
||||
echo json_encode([
|
||||
'success' => true,
|
||||
'message' => "Tunnel '$name' berhasil dihapus"
|
||||
]);
|
||||
} catch (Exception $e) {
|
||||
$mikrotik->disconnect();
|
||||
http_response_code(500);
|
||||
echo json_encode([
|
||||
'success' => false,
|
||||
'message' => "Gagal menghapus tunnel: " . $e->getMessage()
|
||||
]);
|
||||
}
|
||||
} else {
|
||||
http_response_code(500);
|
||||
echo json_encode([
|
||||
'success' => false,
|
||||
'message' => "Gagal koneksi ke MikroTik"
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
// <===== CONTOH =====>
|
||||
|
||||
// $tunnel = new CreateTunnel();
|
||||
// $result = $tunnel->addSecret('user123', 'pass123');
|
||||
|
||||
// if ($result['status']) {
|
||||
// echo "✅ Berhasil: " . $result['remote-address'];
|
||||
// } else {
|
||||
// echo "❌ Gagal: " . $result['message'];
|
||||
// }
|
||||
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
class CrudRadiusServer
|
||||
{
|
||||
private $token = 'x4R7yP9@#gT1z!fL2wE8hQ%kM5vN0uS6aC';
|
||||
private $baseUrl = "http://103.242.106.56:4408/api/";
|
||||
|
||||
public function request($action, $method = 'POST', $data = [])
|
||||
{
|
||||
$url = $this->baseUrl . "?action=" . urlencode($action);
|
||||
|
||||
$ch = curl_init($url);
|
||||
|
||||
$headers = [
|
||||
'Content-Type: application/json',
|
||||
'Authorization: Bearer ' . $this->token
|
||||
];
|
||||
|
||||
// Set CURL options
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, strtoupper($method));
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
|
||||
|
||||
// Jika ada data, kirim sebagai JSON
|
||||
if (!empty($data)) {
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
|
||||
}
|
||||
|
||||
// Eksekusi request
|
||||
$response = curl_exec($ch);
|
||||
|
||||
if (curl_errno($ch)) {
|
||||
// Return error sebagai array
|
||||
return [
|
||||
'success' => false,
|
||||
'error' => curl_error($ch)
|
||||
];
|
||||
}
|
||||
|
||||
curl_close($ch);
|
||||
|
||||
// Decode JSON response
|
||||
$decoded = json_decode($response, true);
|
||||
|
||||
// Jika JSON tidak valid
|
||||
if (json_last_error() !== JSON_ERROR_NONE) {
|
||||
return [
|
||||
'success' => false,
|
||||
'error' => 'Invalid JSON response from API'
|
||||
];
|
||||
}
|
||||
|
||||
return $decoded;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
<?php
|
||||
ini_set('display_errors', 1);
|
||||
error_reporting(E_ALL);
|
||||
|
||||
include __DIR__ . "/../config/connect.php"; // koneksi DB
|
||||
|
||||
try {
|
||||
$potonganPersen = 10; // Potongan 10%
|
||||
$potongan = $potonganPersen / 100; // Konversi ke desimal (0.1)
|
||||
|
||||
// Ambil parameter DataTables
|
||||
$draw = intval($_GET['draw'] ?? 1);
|
||||
$start = intval($_GET['start'] ?? 0);
|
||||
$length = intval($_GET['length'] ?? 10);
|
||||
$searchValue = $_GET['search']['value'] ?? '';
|
||||
|
||||
// Kolom yang bisa diurutkan
|
||||
$columns = ['create_time', 'voucher', 'harga', 'status_cek', 'active_time', 'expaired_time'];
|
||||
$orderColumnIndex = $_GET['order'][0]['column'] ?? 0;
|
||||
$orderColumnDir = $_GET['order'][0]['dir'] ?? 'desc';
|
||||
$orderColumn = $columns[$orderColumnIndex] ?? 'create_time';
|
||||
|
||||
// Kondisi dasar (statis)
|
||||
$baseCondition = "id_agen_voucher IS NULL AND jenis IN ('sv-radius','sv-mikrotik','api-pw')";
|
||||
|
||||
// Hitung total data
|
||||
$totalQuery = $pdo->query("SELECT COUNT(*) FROM ganerate_voucher WHERE $baseCondition");
|
||||
$totalRecords = $totalQuery->fetchColumn();
|
||||
|
||||
// Query data + search
|
||||
$sql = "SELECT create_time, voucher, harga, status_cek, active_time, expaired_time, jenis
|
||||
FROM ganerate_voucher
|
||||
WHERE $baseCondition";
|
||||
$params = [];
|
||||
|
||||
if (!empty($searchValue)) {
|
||||
$sql .= " AND (
|
||||
create_time LIKE :search OR
|
||||
voucher LIKE :search OR
|
||||
status_cek LIKE :search OR
|
||||
active_time LIKE :search OR
|
||||
expaired_time LIKE :search
|
||||
)";
|
||||
$params[':search'] = "%$searchValue%";
|
||||
}
|
||||
|
||||
// Hitung total setelah filter
|
||||
$filteredSql = str_replace(
|
||||
"SELECT create_time, voucher, harga, status_cek, active_time, expaired_time, jenis",
|
||||
"SELECT COUNT(*)",
|
||||
$sql
|
||||
);
|
||||
$stmtFiltered = $pdo->prepare($filteredSql);
|
||||
$stmtFiltered->execute($params);
|
||||
$filteredRecords = $stmtFiltered->fetchColumn();
|
||||
|
||||
// Tambahkan ORDER BY dan LIMIT
|
||||
$sql .= " ORDER BY $orderColumn $orderColumnDir LIMIT :start, :length";
|
||||
$stmt = $pdo->prepare($sql);
|
||||
|
||||
// Binding parameter
|
||||
foreach ($params as $key => $value) {
|
||||
$stmt->bindValue($key, $value);
|
||||
}
|
||||
$stmt->bindValue(':start', $start, PDO::PARAM_INT);
|
||||
$stmt->bindValue(':length', $length, PDO::PARAM_INT);
|
||||
|
||||
$stmt->execute();
|
||||
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
// Hitung biaya & saldo, lalu format angka
|
||||
$data = [];
|
||||
foreach ($rows as $row) {
|
||||
$harga = floatval($row['harga']);
|
||||
if ($row['jenis'] === 'api-pw') {
|
||||
$biaya = $harga * $potongan;
|
||||
} else {
|
||||
$biaya = 0; // Tidak ada biaya jika bukan sv-radius
|
||||
}
|
||||
$saldo = $harga - $biaya;
|
||||
|
||||
$data[] = [
|
||||
$row['create_time'],
|
||||
$row['voucher'],
|
||||
number_format($harga), // harga
|
||||
number_format($biaya), // biaya
|
||||
number_format($saldo), // saldo
|
||||
$row['status_cek'],
|
||||
$row['active_time'],
|
||||
$row['expaired_time'],
|
||||
];
|
||||
}
|
||||
|
||||
// Kirim response JSON ke DataTables
|
||||
$response = [
|
||||
"draw" => $draw,
|
||||
"recordsTotal" => $totalRecords,
|
||||
"recordsFiltered" => $filteredRecords,
|
||||
"data" => $data,
|
||||
];
|
||||
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode($response);
|
||||
} catch (Exception $e) {
|
||||
// Tangani error
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode([
|
||||
"error" => $e->getMessage()
|
||||
]);
|
||||
}
|
||||
Reference in New Issue
Block a user