Update Banyak

This commit is contained in:
WD - Dev
2025-09-21 21:40:17 +07:00
parent c6bee729c5
commit efca8f5f80
145 changed files with 195185 additions and 1378 deletions
+76
View File
@@ -0,0 +1,76 @@
<?php
header("Content-Type: application/json; charset=UTF-8");
error_reporting(E_ALL & ~E_NOTICE & ~E_WARNING);
// ====== SECURITY LAYER ======
$apiToken = "xyz123"; // samakan dengan di JS
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
echo json_encode(["status" => false, "message" => "Gunakan POST"]);
exit;
}
if ($_SERVER['HTTP_X_API_TOKEN'] !== $apiToken) {
echo json_encode(["status" => false, "message" => "Unauthorized"]);
exit;
}
// =============================
function cekRekeningFlip($bank_code, $account_number) {
$flipKey = "JDJ5JDEzJHlkOFNYckl1a3U3VXJkZERKVnNZL3VTN1BLWmE2U3NMeUJXZC9COFV4LmZlb2VUTmdQaEN5"; // ganti dengan key kamu
$url = "https://bigflip.id/api/v2/disbursement/bank-account-inquiry";
$data = [
"bank_code" => strtolower($bank_code),
"account_number" => $account_number,
"inquiry_key" => uniqid("inq_")
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Content-Type: application/x-www-form-urlencoded",
"Accept: application/json; charset=UTF-8",
"Authorization: Basic " . base64_encode($flipKey . ":")
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
$response = curl_exec($ch);
if (curl_errno($ch)) {
$error_msg = curl_error($ch);
curl_close($ch);
return ["status" => false, "message" => $error_msg];
}
curl_close($ch);
$result = json_decode($response, true);
if (!$result) {
return ["status" => false, "message" => "Flip API tidak balas JSON", "raw" => $response];
}
if (isset($result['account_number'])) {
return [
"status" => true,
"account_number" => $result['account_number'],
"account_holder" => $result['account_holder'],
"bank_code" => $result['bank_code']
];
}
return ["status" => false, "message" => $result];
}
// ==== Eksekusi request ====
$bank_code = $_POST['bank_code'] ?? '';
$account_number = $_POST['account_number'] ?? '';
if (empty($bank_code) || empty($account_number)) {
echo json_encode(["status" => false, "message" => "Bank atau nomor rekening kosong"]);
exit;
}
echo json_encode(cekRekeningFlip($bank_code, $account_number));
+3 -1
View File
@@ -88,7 +88,9 @@ class CreateTunnel
// ==============================
// Generate user/pass
// ==============================
$secretUser = strtolower(preg_replace('/[^a-z0-9]/i', '', substr($Secret, 0, 12))) . "@manjapro.net";
// $secretUser = strtolower(preg_replace('/[^a-z0-9]/i', '', substr($Secret, 0, 12))) . "@manjapro.net";
$prefix = strtolower(preg_replace('/[^a-z0-9]/i', '', substr($Secret, 0, 10)));
$secretUser = $prefix . rand(1000, 9999) . "@manjapro.net";
$secretPass = strtolower(substr(md5($secretUser), 0, 12));
$nasSecret = substr(md5($secretUser), 0, 20);
+105
View File
@@ -0,0 +1,105 @@
<?php
include '../config/connect.php';
// Ambil parameter DataTables
$draw = isset($_POST['draw']) ? intval($_POST['draw']) : 0;
$start = isset($_POST['start']) ? intval($_POST['start']) : 0;
$length = isset($_POST['length']) ? intval($_POST['length']) : 10;
$search = isset($_POST['search']['value']) ? $_POST['search']['value'] : '';
$orderColumnIndex = $_POST['order'][0]['column'] ?? 1;
$orderDir = $_POST['order'][0]['dir'] ?? 'desc';
$status = isset($_GET['s']) ? $_GET['s'] : 'SUCCESS';
// Mapping kolom sesuai urutan table DataTable
$columns = [
0 => 'order_id',
1 => 'keterangan',
2 => 'nama',
3 => 'jumlah',
4 => 'saldo',
5 => 'biaya',
6 => 'status',
7 => 'jenis',
8 => 'input_time',
9 => 'update_time',
];
$orderColumn = $columns[$orderColumnIndex] ?? 'update_time';
// Filter server ID
$id_data_server = isset($_GET['i']) ? $_GET['i'] : 0; // bisa single atau multiple (1,2,3)
$where = "WHERE 1=1 ";
if ($id_data_server > 0) {
if ($id_data_server == 1) {
$where .= ""; // semua server
} else {
// pastikan hanya angka dan koma
$safe_ids = implode(',', array_map('intval', explode(',', $id_data_server)));
$where .= " AND id_data_server IN ($safe_ids) AND status = '$status'";
}
}
// Query untuk hitung total
try {
$stmt = $pdo->query("SELECT COUNT(*) FROM client_payment $where");
$recordsTotal = (int) $stmt->fetchColumn();
} catch (Exception $e) {
$recordsTotal = 0;
}
// Query untuk filter pencarian
$searchQuery = '';
if (!empty($search)) {
$searchQuery = " AND (update_time LIKE :search OR keterangan) ";
}
// Hitung total setelah filter
try {
$stmt = $pdo->prepare("SELECT COUNT(*) FROM client_payment $where $searchQuery");
if (!empty($search)) $stmt->bindValue(':search', "%$search%", PDO::PARAM_STR);
$stmt->execute();
$recordsFiltered = (int) $stmt->fetchColumn();
} catch (Exception $e) {
$recordsFiltered = 0;
}
// Ambil data sesuai filter + order + limit
$data = [];
try {
$sql = "SELECT order_id, keterangan, nama, jumlah, saldo, biaya, status, jenis, input_time, update_time
FROM client_payment
$where $searchQuery
ORDER BY $orderColumn $orderDir
LIMIT :start, :length";
$stmt = $pdo->prepare($sql);
if (!empty($search)) $stmt->bindValue(':search', "%$search%", PDO::PARAM_STR);
$stmt->bindValue(':start', $start, PDO::PARAM_INT);
$stmt->bindValue(':length', $length, PDO::PARAM_INT);
$stmt->execute();
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC) ?: [];
foreach ($rows as $row) {
$data[] = [
"#PGPDN" . $row['order_id'],
$row['keterangan'],
$row['nama'],
number_format((float)$row['jumlah'], 0, ',', '.'),
number_format((float)$row['saldo'], 0, ',', '.'),
number_format((float)$row['biaya'], 0, ',', '.'),
$row['status'],
$row['jenis'],
$row['input_time'],
$row['update_time'],
];
}
} catch (Exception $e) {
$data = [];
}
// Response ke DataTables
echo json_encode([
"draw" => $draw,
"recordsTotal" => $recordsTotal,
"recordsFiltered" => $recordsFiltered,
"data" => $data
]);
+21
View File
@@ -0,0 +1,21 @@
<?php
include '../config/connect.php';
$id = isset($_GET['id']) ? intval($_GET['id']) : 0;
$s = isset($_GET['s']) ? intval($_GET['s']) : 0;
if($id > 0){
if($s == 1 ){
$colum = "v_akumulasi_client_payment";
} else {
$colum = "v_akumulasi_paygw";
}
$stmt = $pdo->prepare("SELECT tersedia AS saldo FROM $colum WHERE id_data_server = :id LIMIT 1");
$stmt->execute([':id' => $id]);
$row = $stmt->fetch(PDO::FETCH_ASSOC);
echo json_encode($row ?: ["saldo" => 0]);
} else {
echo json_encode(["saldo" => 0]);
}
+172
View File
@@ -0,0 +1,172 @@
<?php
ini_set('display_errors', 1);
error_reporting(E_ALL);
require __DIR__ . "/../config/connect.php"; // koneksi PDO
require __DIR__ . "/../config/gpt_ai.php"; // koneksi PDO
$action = $_GET['action'] ?? 'list';
$id_server = isset($_GET['i']) ? $_GET['i'] : 0;
if ($action === 'list') {
$limit = isset($_POST['length']) ? intval($_POST['length']) : 20;
$start = isset($_POST['start']) ? intval($_POST['start']) : 0;
// pecah id server jadi array aman
$ids = array_filter(array_map('intval', explode(',', $id_server)));
$placeholders = implode(',', array_fill(0, count($ids), '?'));
// hitung total data distinct topik
$stmt = $pdo->prepare("SELECT COUNT(DISTINCT topik)
FROM chat_topik
WHERE id_data_server IN ($placeholders)");
$stmt->execute($ids);
$totalData = $stmt->fetchColumn();
// ambil data unik berdasarkan topik (ambil id terbesar per topik)
$stmt = $pdo->prepare("
SELECT ct.id, ct.topik, ct.deskripsi
FROM chat_topik ct
INNER JOIN (
SELECT topik, MAX(id) AS max_id
FROM chat_topik
WHERE id_data_server IN ($placeholders)
GROUP BY topik
) tmax ON ct.id = tmax.max_id
ORDER BY ct.id DESC
LIMIT ?, ?
");
// binding ids dulu
$i = 1;
foreach ($ids as $id) {
$stmt->bindValue($i++, $id, PDO::PARAM_INT);
}
// binding limit
$stmt->bindValue($i++, $start, PDO::PARAM_INT);
$stmt->bindValue($i++, $limit, PDO::PARAM_INT);
$stmt->execute();
$data = [];
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
$data[] = [
$row['topik'],
$row['deskripsi'],
["id" => $row['id']]
];
}
echo json_encode([
"draw" => intval($_POST['draw'] ?? 1),
"recordsTotal" => intval($totalData),
"recordsFiltered" => intval($totalData),
"data" => $data
]);
exit;
}
if ($action === 'detail') {
$id = intval($_POST['id'] ?? 0);
$stmt = $pdo->prepare("SELECT id, deskripsi, topik FROM chat_topik WHERE id = ?");
$stmt->execute([$id]);
$row = $stmt->fetch(PDO::FETCH_ASSOC);
echo json_encode($row ?: []);
exit;
}
if ($action === 'save') {
$id = intval($_POST['id'] ?? 0);
$deskripsi = trim($_POST['deskripsi'] ?? '');
$ids = array_filter(array_map('intval', explode(',', $_GET['i'] ?? '0')));
if ($deskripsi === '' || empty($ids)) {
echo json_encode(["status" => "error", "msg" => "Data tidak valid"]);
exit;
}
// buat metadata dari GPT
$payload = [
"model" => "gpt-3.5-turbo",
"messages" => [
["role" => "system", "content" => "Tolong rubah kalimat berikut menjadi metadata berbentuk JSON."],
["role" => "user", "content" => $deskripsi]
],
"temperature" => 0.0
];
$GPT = new Gpt_Ai_Api();
$metadata = $GPT->call_openai($payload);
// pastikan metadata berbentuk string JSON
if (is_array($metadata) || is_object($metadata)) {
$metadata = json_encode($metadata, JSON_UNESCAPED_UNICODE);
}
// pastikan metadata berbentuk string JSON
if (is_array($metadata) || is_object($metadata)) {
$metadata = json_encode($metadata, JSON_UNESCAPED_UNICODE);
}
if ($id > 0) {
// update data yang sudah ada
$stmt = $pdo->prepare("SELECT topik FROM chat_topik WHERE id = ?");
$stmt->execute([$id]);
$row = $stmt->fetch(PDO::FETCH_ASSOC);
if ($row) {
$topik = $row['topik'];
if (count($ids) > 1) {
// multi server → replace ke semua id_data_server
$pdo->beginTransaction();
try {
$stmt = $pdo->prepare("
INSERT INTO chat_topik (id_data_server, topik, deskripsi, metadata)
VALUES (?, ?, ?, ?)
ON DUPLICATE KEY UPDATE deskripsi = VALUES(deskripsi),
metadata = VALUES(metadata)
");
foreach ($ids as $sid) {
$stmt->execute([$sid, $topik, $deskripsi, $metadata]);
}
$pdo->commit();
echo json_encode(["status" => "ok"]);
} catch (Exception $e) {
$pdo->rollBack();
echo json_encode(["status" => "error", "msg" => $e->getMessage()]);
}
} else {
// single server → update biasa
$stmt = $pdo->prepare("UPDATE chat_topik SET deskripsi = ?, metadata = ? WHERE id = ?");
$ok = $stmt->execute([$deskripsi, $metadata, $id]);
echo json_encode(["status" => $ok ? "ok" : "error"]);
}
} else {
echo json_encode(["status" => "error", "msg" => "Topik tidak ditemukan"]);
}
} else {
// jika id = 0 → insert baru
try {
$pdo->beginTransaction();
$stmt = $pdo->prepare("
INSERT INTO chat_topik (id_data_server, topik, deskripsi, metadata)
VALUES (?, ?, ?, ?)
");
foreach ($ids as $sid) {
// topik bisa digenerate otomatis dari deskripsi (misalnya hash/md5)
$topik = substr(md5($deskripsi . $sid), 0, 16);
$stmt->execute([$sid, $topik, $deskripsi, $metadata]);
}
$pdo->commit();
echo json_encode(["status" => "ok"]);
} catch (Exception $e) {
$pdo->rollBack();
echo json_encode(["status" => "error", "msg" => $e->getMessage()]);
}
}
exit;
}
echo json_encode(["status" => "error", "msg" => "Action tidak valid"]);
+104
View File
@@ -0,0 +1,104 @@
<?php
require __DIR__ . "/../config/connect.php";
require __DIR__ . "/../config/encrypt.php";
$datadecrypt = decrypt_url($_GET['data']);
$dataurl = json_decode($datadecrypt, true);
$SqlSvData = $dataurl[0];
$SqlDataWHIdM = $dataurl[1];
$hotspotAktif = !empty($dataurl[2]) && $dataurl[2] == 1;
// Definisi kolom sesuai thead (No dihitung otomatis)
$columns = ['nama','nik','akun'];
if($hotspotAktif) {
$columns[] = 'user_hotspot';
}
$columns = array_merge($columns, [
'alamat','latitude','nomor_whatsapp','nama_server','nama_mikrotik','nama_paket','status_koneksi','time_start'
]);
// Paging
$limit = intval($_POST['length']);
$offset = intval($_POST['start']);
// Order
$orderIndex = intval($_POST['order'][0]['column']) - 1; // kurangi 1 karena No di kolom pertama
$orderCol = $columns[$orderIndex] ?? 'nama';
$orderDir = $_POST['order'][0]['dir'] ?? 'asc';
// Search
$search = $_POST['search']['value'] ?? '';
$where = "WHERE $SqlSvData status = 'aktif'";
if(!empty($search)) {
$where .= " AND (nama LIKE :search OR nik LIKE :search OR akun LIKE :search OR status_koneksi LIKE :search OR nomor_whatsapp LIKE :search OR nama_paket LIKE :search OR nama_server LIKE :search OR alamat LIKE :search OR time_start LIKE :search)";
}
// Hitung total
$totalStmt = $pdo->query("SELECT COUNT(id) FROM v_pelanggan WHERE $SqlSvData status = 'aktif'");
$recordsTotal = $totalStmt->fetchColumn();
// Query data
$sql = "SELECT id,akun,user_hotspot,nama,alamat,latitude,longitude,nomor_whatsapp,email,nik,
nama_server,nama_paket,time_start,status_koneksi,nama_mikrotik,id_setting_mikrotik,
time_update,ip_address
FROM v_pelanggan $where
ORDER BY $orderCol $orderDir
LIMIT :limit OFFSET :offset";
$stmt = $pdo->prepare($sql);
if(!empty($search)) $stmt->bindValue(':search', "%$search%");
$stmt->bindValue(':limit', $limit, PDO::PARAM_INT);
$stmt->bindValue(':offset', $offset, PDO::PARAM_INT);
$stmt->execute();
$data = $stmt->fetchAll(PDO::FETCH_ASSOC);
// Format data
$no = $offset + 1;
$dataArray = [];
foreach($data as $row) {
$latlong = (substr($row['latitude'],0,1) != '-')
? "<a href='https://google.com/maps/?q={$row['latitude']}' target='_blank'>{$row['latitude']}</a>"
: "<a href='https://google.com/maps/?q={$row['latitude']},{$row['longitude']}' target='_blank'>{$row['latitude']}, {$row['longitude']}</a>";
$wa = "{$row['nomor_whatsapp']} <a href='https://wa.me/{$row['nomor_whatsapp']}' target='_blank' class='btn btn-sm btn-success' style='border-radius:20px;'><i class='fab fa-whatsapp'></i></a><br>{$row['email']}";
$status = $row['status_koneksi'];
if($status == 'On') {
$status .= " <a href='?".encrypt_url("user_remote|{$row['id']}|{$row['id_setting_mikrotik']}")."' class='btn btn-sm btn-success ml-1' style='border-radius: 20px;'>Remote</a><br>{$row['ip_address']}";
}
$status .= "<br>{$row['time_update']}";
$aksi = "<a href='?".encrypt_url("user_detail|{$row['id']}")."' class='btn btn-sm btn-info m-1'>Detail</a>";
// Build row sesuai urutan thead
$rowData = [
$no++,
$row['nama'],
$row['nik'],
$row['akun']
];
if($hotspotAktif) {
$rowData[] = $row['user_hotspot'];
}
$rowData[] = $row['alamat'];
$rowData[] = $latlong;
$rowData[] = $wa;
$rowData[] = $row['nama_server'];
$rowData[] = $row['nama_mikrotik'];
$rowData[] = $row['nama_paket'];
$rowData[] = $status;
$rowData[] = $row['time_start'];
$rowData[] = $aksi;
$dataArray[] = $rowData;
}
echo json_encode([
"draw" => intval($_POST['draw']),
"recordsTotal" => $recordsTotal,
"recordsFiltered" => $recordsTotal,
"data" => $dataArray
]);
+111
View File
@@ -0,0 +1,111 @@
<?php
include '../config/connect.php';
// Ambil parameter DataTables
$draw = isset($_POST['draw']) ? intval($_POST['draw']) : 0;
$start = isset($_POST['start']) ? intval($_POST['start']) : 0;
$length = isset($_POST['length']) ? intval($_POST['length']) : 10;
$search = isset($_POST['search']['value']) ? $_POST['search']['value'] : '';
$orderColumnIndex = $_POST['order'][0]['column'] ?? 1;
$orderDir = $_POST['order'][0]['dir'] ?? 'desc';
// Mapping kolom sesuai urutan table DataTable
$columns = [
0 => 'nama_server',
1 => 'start_time',
2 => 'nominal',
3 => 'user_create',
4 => 'status',
5 => 'update_time',
6 => 'id'
];
$orderColumn = $columns[$orderColumnIndex] ?? 'start_time';
// Filter server ID
$id_data_server = isset($_GET['i']) ? $_GET['i'] : 0; // bisa single atau multiple (1,2,3)
$jenis = isset($_GET['s']) ? $_GET['s'] : 0;
// echo $jenis;
$where = "WHERE 1=1 AND jenis = '$jenis'";
if ($id_data_server > 0) {
if ($id_data_server == 1) {
$where .= ""; // semua server
} else {
// pastikan hanya angka dan koma
$safe_ids = implode(',', array_map('intval', explode(',', $id_data_server)));
$where .= " AND id_data_server IN ($safe_ids) ";
}
}
// Query untuk hitung total
try {
$stmt = $pdo->query("SELECT COUNT(*) FROM v_transaksi_withdraw $where");
$recordsTotal = (int) $stmt->fetchColumn();
} catch (Exception $e) {
$recordsTotal = 0;
}
// Query untuk filter pencarian
$searchQuery = '';
if (!empty($search)) {
$searchQuery = " AND (user_create LIKE :search OR status LIKE :search OR nominal LIKE :search) ";
}
// Hitung total setelah filter
try {
$stmt = $pdo->prepare("SELECT COUNT(*) FROM v_transaksi_withdraw $where $searchQuery");
if (!empty($search)) $stmt->bindValue(':search', "%$search%", PDO::PARAM_STR);
$stmt->execute();
$recordsFiltered = (int) $stmt->fetchColumn();
} catch (Exception $e) {
$recordsFiltered = 0;
}
// Ambil data sesuai filter + order + limit
$data = [];
try {
$sql = "SELECT nama_server, start_time, nominal, user_create, status, update_time, id_data_server, id, bukti_success
FROM v_transaksi_withdraw
$where $searchQuery
ORDER BY $orderColumn $orderDir
LIMIT :start, :length";
$stmt = $pdo->prepare($sql);
if (!empty($search)) $stmt->bindValue(':search', "%$search%", PDO::PARAM_STR);
$stmt->bindValue(':start', $start, PDO::PARAM_INT);
$stmt->bindValue(':length', $length, PDO::PARAM_INT);
$stmt->execute();
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC) ?: [];
// foreach ($rows as $row) {
// // Format nominal ke number_format
// $row['nominal'] = number_format((float)$row['nominal'], 0, ',', '.');
// // $row['status'] = ($row['status'] == 'pending') ? '<span class="badge bg-primary p-2">' . strtoupper($row['status']) . '</span>' : '<span class="badge bg-success p-2">' . strtoupper($row['status']) . '</span>';
// $row['id'] = ['id' => '']
// $data[] = array_values($row); // ubah ke numerik index biar sesuai DataTables
// }
foreach ($rows as $row) {
$data[] = [
$row['nama_server'],
$row['start_time'],
number_format((float)$row['nominal'], 0, ',', '.'),
$row['user_create'],
$row['status'],
$row['update_time'],
[ // kolom 6 → objek
"id" => $row['id'],
"bukti_success" => $row['bukti_success']
]
];
}
} catch (Exception $e) {
$data = [];
}
// Response ke DataTables
echo json_encode([
"draw" => $draw,
"recordsTotal" => $recordsTotal,
"recordsFiltered" => $recordsFiltered,
"data" => $data
]);
+158
View File
@@ -0,0 +1,158 @@
<?php
ini_set('display_errors', 1);
error_reporting(E_ALL);
header('Content-Type: text/html; charset=UTF-8');
/**
* Generate form/page HTML berdasarkan data JSON
*/
function formPage(string $dataform): string {
$data = json_decode($dataform, true);
if (json_last_error() !== JSON_ERROR_NONE || !$data || !isset($data['page'])) {
return '<p class="text-danger">Data tidak valid.</p>';
}
$page = $data['page'];
$endpoint = $data['endpoint'] ?? '';
$apikey = $data['apikey'] ?? '';
$tokenkey = $data['tokenkey'] ?? '';
if ($page === 'flip') {
return '
<div class="form-group">
<label>ENDPOINT URL</label>
<input class="form-control" type="text" name="endpoint" value="' . htmlspecialchars($endpoint) . '">
</div>
<div class="form-group">
<label>API SECRET KEY</label>
<div class="input-group">
<input type="password" class="form-control password-input" id="password1" name="apikey" value="' . htmlspecialchars($apikey) . '">
<div class="input-group-append">
<div class="input-group-text password-toggle" data-target="password1">
<span class="fas fa-eye"></span>
</div>
</div>
</div>
</div>
<div class="form-group">
<label>TOKEN VALIDASI</label>
<div class="input-group">
<input type="password" class="form-control password-input" id="password2" name="tokenkey" value="' . htmlspecialchars($tokenkey) . '">
<div class="input-group-append">
<div class="input-group-text password-toggle" data-target="password2">
<span class="fas fa-eye"></span>
</div>
</div>
</div>
</div>
<script>
document.querySelectorAll(".password-toggle").forEach(function(toggle) {
toggle.addEventListener("click", function() {
var targetId = this.getAttribute("data-target");
var input = document.getElementById(targetId);
var icon = this.querySelector("span");
if (!input) return;
if (input.type === "password") {
input.type = "text";
icon.classList.remove("fa-eye");
icon.classList.add("fa-eye-slash");
} else {
input.type = "password";
icon.classList.remove("fa-eye-slash");
icon.classList.add("fa-eye");
}
});
});
</script>
';
}
if ($page === 'paydisini') {
return '
<div class="form-group d-none">
<label>Admin Payment Gateway</label>
<select class="form-control" name="adminpg">
<option value="2">Beban Owner</option>
<option value="1">Beban Customer</option>
</select>
</div>
<div class="text-center mb-4">
<a data-toggle="collapse" href="#collapseExample" role="button" aria-expanded="false" aria-controls="collapseExample">
<h6><b>Aturan dan Kebijakan</b></h6>
</a>
</div>
<div class="collapse" id="collapseExample">
<div class="text-center">
<h6>Setelah mengaktifkan Paymnent Gateway ini kami anggap sudah menyetujui ketentuan di bawah ini</h6>
</div>
<div class="card-body text-justify">
<h6>Umum</h6>
<ul>
<li>ManjaPro didukung oleh Paydisini Payment Gateway Indonesia untuk proses pembayaran.</li>
<li>Semua transaksi harus dilakukan melalui sistem resmi ManjaPro untuk keamanan dan validasi.</li>
<li>Pelanggan bertanggung jawab atas keamanan akun dan informasi pembayaran masing-masing.</li>
</ul>
<h6>Alur Kerja Pembayaran</h6>
<ul>
<li>Pelanggan akan diberikan <strong>link pembayaran unik</strong> untuk setiap transaksi (ONE LINK ONE TRANSACTION).</li>
<li>Pembayaran dapat dilakukan melalui metode yang tersedia: BRI VA, BNI VA, Mandiri VA, atau QRIS.</li>
<li>Setelah pembayaran diterima, dana akan ditahan selama 1x24 jam di rekening ManjaPro untuk proses pengecekan dan penyesuaian (check & balance).</li>
<li>Saldo dapat digunakan atau ditarik (withdraw) setelah status pembayaran berhasil diverifikasi.</li>
<li>Pelanggan wajib memastikan data pembayaran dan nominal yang dikirim sesuai dengan instruksi.</li>
</ul>
<h6>Biaya Admin</h6>
<ul>
<li>Untuk biaya admin Payment Gateway bisa di bebankan ke pelanggan atau ke pemilik</li>
<li>BRI VA : Rp. 2.950</li>
<li>BNI VA : Rp. 4.500</li>
<li>Mandiri VA : Rp. 2.950</li>
<li>QRIS : 1%</li>
</ul>
<h6>Withdraw / Penarikan Saldo</h6>
<ul>
<li>Withdraw hanya dapat dilakukan pada hari kerja. Permintaan pada hari libur akan diproses pada hari kerja berikutnya.</li>
<li>Withdraw hanya dapat dilakukan ke rekening yang telah diverifikasi oleh sistem ManjaPro.</li>
<li>Verifikasi rekening dapat dilakukan melalui menu <strong>Profil</strong> di akun pelanggan.</li>
<li>Minimal saldo untuk melakukan withdraw adalah sesuai ketentuan yang berlaku di akun pelanggan.</li>
<li>ManjaPro berhak menunda atau menolak transaksi withdraw jika ditemukan indikasi penipuan atau kesalahan data.</li>
</ul>
<h6>Pemecahan Masalah / Komplain</h6>
<ul>
<li>Jika terjadi kesalahan pada transaksi atau masalah lainnya, pelanggan wajib menghubungi layanan pelanggan ManjaPro untuk perundingan.</li>
<li>Setiap komplain akan diproses sesuai dengan data transaksi yang tercatat di sistem.</li>
<li>Keputusan akhir akan diambil oleh ManjaPro setelah proses pengecekan dan verifikasi.</li>
</ul>
<h6>Ketentuan Tambahan</h6>
<ul>
<li>ManjaPro berhak mengubah aturan dan kebijakan ini sewaktu-waktu tanpa pemberitahuan terlebih dahulu.</li>
<li>Pelanggan dianggap menyetujui aturan ini saat melakukan transaksi melalui ManjaPro.</li>
<li>Segala tindakan yang melanggar ketentuan dapat menyebabkan akun diblokir atau transaksi dibatalkan.</li>
</ul>
</div>
</div>
';
}
return '<p class="text-danger">Page tidak dikenali.</p>';
}
// Terima JSON dari fetch()
$inputJSON = file_get_contents('php://input');
if (!$inputJSON) {
echo "<p class='text-danger'>Data tidak diterima.</p>";
exit;
}
// Tampilkan hasil formPage
echo formPage($inputJSON);
+48
View File
@@ -0,0 +1,48 @@
<?php
include '../config/connect.php';
require 'payment/client/jwtoken/url_paymnet_encrypt.php';
function createUrlpaydisini($id)
{
if (empty($id) || !is_numeric($id)) {
return ["status" => false];
}
global $pdo;
try {
$stmt = $pdo->prepare("SELECT nama_server, nama FROM v_tagihan WHERE id = :id LIMIT 1");
if (!$stmt->execute(['id' => $id])) {
return ["status" => false];
}
$pelanggan = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$pelanggan) {
return ["status" => false];
}
$namaServer = $pelanggan['nama_server'] ?? '';
$namaPelanggan = $pelanggan['nama'] ?? '';
$server = mb_strtolower(preg_replace('/[^a-zA-Z0-9]+/', '', (string)$namaServer));
$nama = mb_strtolower(preg_replace('/[^a-zA-Z0-9]+/', '', (string)$namaPelanggan));
if ($server === '' || $nama === '') {
return ["status" => false];
}
$encId = jwt_encrypt($id);
if (empty($encId) || !is_string($encId)) {
return ["status" => false];
}
return [
"status" => true,
"url" => "pay.manjapro.net/{$server}/{$nama}/{$encId}"
];
} catch (Throwable $e) {
// kalau mau log error: error_log($e->getMessage());
return ["status" => false];
}
}
+223
View File
@@ -0,0 +1,223 @@
<?php
/** remote_add() // ambil data mikrotik lalu cek address aplikasi, jika address adalah "tunnel.manjapr.net" maka buat port nya di 2 mikrotik dan jika bukan maka buatnya langsung ke mikrotik nya
* buat range port untuk remote ONU.
* buat schedule untuk ubah port ke kosong
*/
class RemoteModem
{
private $pdo;
public function __construct($pdo)
{
$this->pdo = $pdo; // Inject PDO
}
public function remote_add($id_mikrotik, $ip_akses, $nama_user)
{
$mikrotik = new RouterosAPI();
$mikrotik->debug = false;
try {
// 🔥 Ambil data Mikrotik
$stmt = $this->pdo->prepare("SELECT ip_address, username, password, port_api, radius_nas_data
FROM setting_mikrotik
WHERE id = :id");
$stmt->execute([':id' => $id_mikrotik]);
$mikrotikUser = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$mikrotikUser) {
return json_encode([
"status" => "error",
"message" => "Mikrotik dengan ID $id_mikrotik tidak ditemukan."
]);
}
// 🔥 Ambil remote-address jika tunnel
$dataIP = json_decode($mikrotikUser['radius_nas_data']);
$iptunnel = $dataIP->data->{'remote-address'} ?? null;
do {
$freePort = rand(10000, 19999);
$stmt = $this->pdo->prepare("SELECT COUNT(*) FROM log_remote WHERE remote_port = :port");
$stmt->execute([':port' => $freePort]);
$count = $stmt->fetchColumn();
} while ($count > 0);
$Secret = "Remote-User-" . $nama_user;
if ($mikrotikUser['ip_address'] === "tunnel.manjapro.net" && !empty($iptunnel)) {
// 🔥 Koneksi ke Mikrotik pusat
if (!$mikrotik->connect2('manjapro.net', 'apiapkmanjapro', 'apiapkmanjapro123321', 2887)) {
return json_encode([
"status" => "error",
"message" => "Gagal koneksi ke Mikrotik pusat."
]);
}
// Tambah NAT di Mikrotik pusat
$mikrotik->comm('/ip/firewall/nat/add', [
"chain" => "dstnat",
"dst-address-list" => "IP-Public",
"dst-port" => $freePort,
"protocol" => "tcp",
"action" => "dst-nat",
"to-addresses" => $iptunnel,
"to-ports" => $freePort,
"comment" => $Secret
]);
$mikrotik->disconnect();
// 🔥 Koneksi ke Mikrotik remote
if (!$mikrotik->connect2($mikrotikUser['ip_address'], $mikrotikUser['username'], $mikrotikUser['password'], $mikrotikUser['port_api'])) {
return json_encode([
"status" => "error",
"message" => "Gagal koneksi ke Mikrotik remote."
]);
}
// Tambah NAT di Mikrotik remote
$mikrotik->comm('/ip/firewall/nat/add', [
"chain" => "dstnat",
"dst-address" => $iptunnel,
"dst-port" => $freePort,
"protocol" => "tcp",
"action" => "dst-nat",
"to-addresses" => $ip_akses,
"to-ports" => 80,
"comment" => $Secret
]);
$mikrotik->disconnect();
$jenis = "tunnel";
} else {
// 🔥 Koneksi ke Mikrotik langsung
if (!$mikrotik->connect2($mikrotikUser['ip_address'], $mikrotikUser['username'], $mikrotikUser['password'], $mikrotikUser['port_api'])) {
return json_encode([
"status" => "error",
"message" => "Gagal koneksi ke Mikrotik."
]);
}
// Tambah NAT di Mikrotik
$mikrotik->comm('/ip/firewall/nat/add', [
"chain" => "dstnat",
"dst-address" => $mikrotikUser['ip_address'],
"dst-port" => $freePort,
"protocol" => "tcp",
"action" => "dst-nat",
"to-addresses" => $ip_akses,
"to-ports" => 80,
"comment" => $Secret
]);
$mikrotik->disconnect();
$jenis = "public";
}
// 🔥 Simpan log_remote
$stmt = $this->pdo->prepare("INSERT INTO log_remote
(id_setting_mikrotik, nama_user, remote_port, aktif_time, jenis)
VALUES (:id_setting_mikrotik, :nama_user, :remote_port, :aktif_time, :jenis)");
$stmt->execute([
':id_setting_mikrotik' => $id_mikrotik,
':nama_user' => $nama_user,
':remote_port' => $freePort,
':aktif_time' => date('Y-m-d H:i:s'),
':jenis' => $jenis
]);
return json_encode([
"status" => "success",
"message" => "Remote berhasil ditambahkan.",
"remote_port" => $freePort,
"link_remote" => $mikrotikUser['ip_address'] . ":" . $freePort,
"jenis" => $jenis
]);
} catch (Exception $e) {
return json_encode([
"status" => "error",
"message" => $e->getMessage()
]);
}
}
public function remote_close($id_mikrotik, $port)
{
$mikrotik = new RouterosAPI();
$mikrotik->debug = false;
try {
// 🔥 Ambil data Mikrotik
$stmt = $this->pdo->prepare("SELECT ip_address, username, password, port_api, radius_nas_data
FROM setting_mikrotik
WHERE id = :id");
$stmt->execute([':id' => $id_mikrotik]);
$mikrotikUser = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$mikrotikUser) {
return json_encode([
"status" => "error",
"message" => "Mikrotik dengan ID $id_mikrotik tidak ditemukan."
]);
}
$dataIP = json_decode($mikrotikUser['radius_nas_data']);
$iptunnel = $dataIP->data->{'remote-address'} ?? null;
if ($mikrotikUser['ip_address'] === "tunnel.manjapro.net" && !empty($iptunnel)) {
// 🔥 Hapus di Mikrotik pusat
if ($mikrotik->connect2('manjapro.net', 'apiapkmanjapro', 'apiapkmanjapro123321', 2887)) {
$this->removeNatRule($mikrotik, $port);
$mikrotik->disconnect();
}
// 🔥 Hapus di Mikrotik remote
if ($mikrotik->connect2($mikrotikUser['ip_address'], $mikrotikUser['username'], $mikrotikUser['password'], $mikrotikUser['port_api'])) {
$this->removeNatRule($mikrotik, $port);
$mikrotik->disconnect();
}
} else {
// 🔥 Hapus di Mikrotik langsung
if ($mikrotik->connect2($mikrotikUser['ip_address'], $mikrotikUser['username'], $mikrotikUser['password'], $mikrotikUser['port_api'])) {
$this->removeNatRule($mikrotik, $port);
$mikrotik->disconnect();
}
}
// 🔥 Hapus log_remote
$stmt = $this->pdo->prepare("DELETE FROM log_remote
WHERE id_setting_mikrotik = :id AND remote_port = :port");
$stmt->execute([
':id' => $id_mikrotik,
':port' => $port
]);
return json_encode([
"status" => "success",
"message" => "Remote pada port $port berhasil ditutup."
]);
} catch (Exception $e) {
return json_encode([
"status" => "error",
"message" => $e->getMessage()
]);
}
}
private function removeNatRule($mikrotik, $port)
{
// 🔥 Cari dan hapus NAT rule berdasarkan dst-port
$natRules = $mikrotik->comm('/ip/firewall/nat/print');
foreach ($natRules as $rule) {
if (isset($rule['dst-port']) && $rule['dst-port'] == $port) {
$mikrotik->comm('/ip/firewall/nat/remove', ['.id' => $rule['.id']]);
}
}
}
}
+56
View File
@@ -0,0 +1,56 @@
<?php
header("Content-Type: application/json");
$flipKey = "JDJ5JDEzJHlkOFNYckl1a3U3VXJkZERKVnNZL3VTN1BLWmE2U3NMeUJXZC9COFV4LmZlb2VUTmdQaEN5"; // ganti dengan key kamu
$url = "https://bigflip.id/api/v2/disbursement/bank-account-inquiry";
$bank_code = "bri"; // contoh bank
$account_number = "778001005210532"; // contoh no rek
$inquiry_key = uniqid("inq_"); // harus unik setiap request
$data = http_build_query([
"bank_code" => strtolower($bank_code),
"account_number" => $account_number,
"inquiry_key" => $inquiry_key
]);
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Content-Type: application/x-www-form-urlencoded",
"Accept: application/json; charset=UTF-8",
"Authorization: Basic " . base64_encode($flipKey . ":")
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if (curl_errno($ch)) {
echo json_encode([
"status" => false,
"message" => curl_error($ch)
]);
curl_close($ch);
exit;
}
curl_close($ch);
// cek apakah balasan valid JSON
$result = json_decode($response, true);
if (json_last_error() !== JSON_ERROR_NONE) {
echo json_encode([
"status" => false,
"message" => "Respon bukan JSON",
"http" => $httpCode,
"raw" => $response
]);
} else {
echo json_encode([
"status" => true,
"http" => $httpCode,
"response" => $result
]);
}
+78
View File
@@ -0,0 +1,78 @@
<?php
include '../config/connect.php';
$response = ["success" => false, "message" => "Terjadi kesalahan"];
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$id = intval($_POST['id'] ?? 0);
if ($id <= 0) {
echo json_encode(["success" => false, "message" => "ID tidak valid"]);
exit;
}
if (!isset($_FILES['bukti_success']) || $_FILES['bukti_success']['error'] !== UPLOAD_ERR_OK) {
echo json_encode(["success" => false, "message" => "File gambar tidak ditemukan"]);
exit;
}
$uploadDir = __DIR__ . "/../img/bukti_success/";
if (!is_dir($uploadDir)) {
mkdir($uploadDir, 0777, true);
}
$ext = pathinfo($_FILES['bukti_success']['name'], PATHINFO_EXTENSION);
$fileName = "bukti_" . $id . "_" . time() . "." . strtolower($ext);
$filePath = $uploadDir . $fileName;
if (move_uploaded_file($_FILES['bukti_success']['tmp_name'], $filePath)) {
// Update status transaksi withdraw
$sql = "UPDATE transaksi_withdraw
SET status = 'success', bukti_success = :bukti, update_time = :update_time
WHERE id = :id";
$stmt = $pdo->prepare($sql);
$stmt->execute([
":bukti" => "img/bukti_success/" . $fileName,
":update_time" => date('Y-m-d H:i:s'),
":id" => $id
]);
// Ambil data transaksi_withdraw yang baru saja diupdate
$stmt = $pdo->prepare("SELECT * FROM transaksi_withdraw WHERE id = :id");
$stmt->bindParam(':id', $id, PDO::PARAM_INT);
$stmt->execute();
$row = $stmt->fetch(PDO::FETCH_ASSOC); // hanya satu baris
if ($row) {
// Generate nomor unik 10 digit
$numid = date('Y_md').$id;
$keterangan = "Withdraw Pendapatan Voucher Auto Pilot reff_" . $numid;
// Cek apakah transaksi dengan keterangan tsb sudah ada
$stmt = $pdo->prepare("SELECT keterangan FROM transaksi WHERE keterangan = :keterangan");
$stmt->bindParam(':keterangan', $keterangan, PDO::PARAM_STR);
$stmt->execute();
$tagid = $stmt->fetchColumn();
if ($tagid === false) {
$sql = "INSERT INTO transaksi
(id_data_server, keterangan, pemasukan, start_time, metode_pembayaran, status)
VALUES (:idds, :keterangan, :pemasukan, :start_time, :metode, 'Pendapatan Hotspot')";
$stmt = $pdo->prepare($sql);
$stmt->bindParam(':idds', $row['id_data_server'], PDO::PARAM_INT);
$stmt->bindParam(':keterangan', $keterangan, PDO::PARAM_STR);
$stmt->bindParam(':pemasukan', $row['nominal'], PDO::PARAM_STR);
$stmt->bindValue(':start_time', date('Y-m-d H:i:s'));
$stmt->bindValue(':metode', 'API Payment');
$stmt->execute();
}
}
$response = ["success" => true, "message" => "Update berhasil"];
} else {
$response = ["success" => false, "message" => "Gagal upload file"];
}
}
echo json_encode($response);
+29 -12
View File
@@ -14,6 +14,7 @@ try {
$length = intval($_GET['length'] ?? 10);
$searchValue = $_GET['search']['value'] ?? '';
$svid = $_GET['i'] ?? '';
$statusFilter = $_GET['s'] ?? '';
// Kolom yang bisa diurutkan
$columns = ['nama_server', 'voucher', 'harga', 'status', 'create_time', 'active_time', 'expaired_time'];
@@ -22,14 +23,14 @@ try {
$orderColumn = $columns[$orderColumnIndex] ?? 'create_time';
// Kondisi dasar (statis)
$baseCondition = "id_data_server IN (".$svid.")";
$baseCondition = "id_data_server IN (".$svid.") AND status = '" . $statusFilter . "'";
// Hitung total data
$totalQuery = $pdo->query("SELECT COUNT(*) FROM v_generate_voucher_manual WHERE $baseCondition");
$totalRecords = $totalQuery->fetchColumn();
// Query data + search
$sql = "SELECT nama_server, nama_mikrotik, create_time, voucher, harga, jenis, active_time, expaired_time
$sql = "SELECT *
FROM v_generate_voucher_manual
WHERE $baseCondition";
$params = [];
@@ -49,7 +50,7 @@ try {
// Hitung total setelah filter
$filteredSql = str_replace(
"SELECT nama_server, nama_mikrotik, create_time, voucher, harga, jenis, active_time, expaired_time",
"SELECT *",
"SELECT COUNT(*)",
$sql
);
@@ -75,23 +76,39 @@ try {
$data = [];
foreach ($rows as $row) {
$harga = floatval($row['harga']);
if ($row['jenis'] === 'api-pw') {
if (($row['jenis'] === 'api-pw' || $row['jenis'] === 'rad-api-pw') && $row['status'] == 'LUNAS') {
$biaya = $harga * $potongan;
$active = $row['active_time'];
$expired = $row['expaired_time'];
$saldo = $harga - $biaya;
} else {
$biaya = 0; // Tidak ada biaya jika bukan sv-radius
if (($row['jenis'] != 'api-pw' || $row['jenis'] != 'rad-api-pw') && $row['status'] == NULL) {
$biaya = 0; // Tidak ada biaya jika bukan sv-radius
$active = $row['active_time'];
$expired = $row['expaired_time'];
$saldo = 0;
} else {
$biaya = 0; // Tidak ada biaya jika bukan sv-radius
$active = "";
$expired = "";
$saldo = 0;
}
}
$saldo = $harga - $biaya;
$data[] = [
$row['nama_server'] . '<br>' . $row['nama_mikrotik'],
$row['voucher'],
number_format($harga), // harga
number_format($biaya), // biaya
number_format($saldo), // saldo
$row['jenis'],
number_format((float)$harga, 0, ',', '.'),
number_format((float)$biaya, 0, ',', '.'),
number_format((float)$saldo, 0, ',', '.'),
// number_format($harga), // harga
// number_format($biaya), // biaya
// number_format($saldo), // saldo
$row['jenis'] . '<br>' . $row['status'],
$row['create_time'],
$row['active_time'],
$row['expaired_time'],
$active,
$expired,
];
}