Add remaining project files (exclude ignored folders)
This commit is contained in:
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
ini_set('display_errors', 1);
|
||||
ini_set('display_startup_errors', 1);
|
||||
error_reporting(E_ALL);
|
||||
|
||||
header('Content-Type: application/json');
|
||||
|
||||
include "/www/wwwroot/bilspro/config/connect.php";
|
||||
|
||||
// Validasi metode
|
||||
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
||||
echo json_encode(['success' => false, 'message' => 'Metode tidak diperbolehkan']);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Validasi input
|
||||
$order_id = $_POST['order_id'] ?? '';
|
||||
if (empty($order_id)) {
|
||||
echo json_encode(['success' => false, 'message' => 'Order ID tidak ditemukan']);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Cek status dari database
|
||||
$stmt = $pdo->prepare("SELECT status FROM apk_payment WHERE order_id = :order_id");
|
||||
$stmt->bindParam(':order_id', $order_id);
|
||||
$stmt->execute();
|
||||
$data = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if (!$data) {
|
||||
echo json_encode(['success' => false, 'message' => 'Transaksi tidak ditemukan']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$status = strtoupper($data['status']);
|
||||
|
||||
if (in_array($status, ['SUCCESS', 'PENDING', 'CANCELED', 'LUNAS'])) {
|
||||
echo json_encode([
|
||||
'success' => true,
|
||||
'status' => ucfirst(strtolower($status)) // Output: Success, Pending, etc.
|
||||
]);
|
||||
} else {
|
||||
echo json_encode([
|
||||
'success' => false,
|
||||
'message' => 'Status tidak dikenali: ' . $status
|
||||
]);
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
(function () {
|
||||
// Ambil router_id dari <script src="?router_id=...">
|
||||
function getRouterIdFromScriptSrc() {
|
||||
const script = document.currentScript;
|
||||
if (script && script.src) {
|
||||
const url = new URL(script.src);
|
||||
return url.searchParams.get("router_id");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
const routerId = getRouterIdFromScriptSrc() || "unknown";
|
||||
console.log("Halaman login diakses dari MikroTik:", routerId);
|
||||
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
const container = document.getElementById("voucher-container");
|
||||
|
||||
if (container) {
|
||||
const iframe = document.createElement("iframe");
|
||||
iframe.id = "voucherFrame";
|
||||
iframe.src = "https://manjapro.net/voucherpay/?id=" + encodeURIComponent(routerId);
|
||||
iframe.style.width = "100%";
|
||||
iframe.style.border = "none";
|
||||
iframe.style.display = "block";
|
||||
iframe.setAttribute("scrolling", "no");
|
||||
container.appendChild(iframe);
|
||||
}
|
||||
|
||||
// Cek jika status sudah "Lunas", isi otomatis input login
|
||||
const status = localStorage.getItem("status");
|
||||
const voucher = localStorage.getItem("voucher");
|
||||
|
||||
if (status === "Lunas" && voucher) {
|
||||
console.log("Mendeteksi status Lunas, mengisi otomatis input dengan voucher:", voucher);
|
||||
const inputs = [
|
||||
document.querySelector('#voucher'),
|
||||
document.querySelector('input[name="username"]'),
|
||||
document.querySelector('input[name="password"]')
|
||||
];
|
||||
|
||||
inputs.forEach((input, i) => {
|
||||
if (input) {
|
||||
input.value = voucher;
|
||||
console.log(`Input otomatis (${input.name || input.id}): ${voucher}`);
|
||||
}
|
||||
});
|
||||
|
||||
// Cegah reload berulang dengan flag khusus
|
||||
if (!sessionStorage.getItem("voucher_reloaded")) {
|
||||
sessionStorage.setItem("voucher_reloaded", "1");
|
||||
console.log("Melakukan reload sekali untuk mengaktifkan form login");
|
||||
location.reload();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Terima pesan tinggi dari iframe dan isi otomatis voucher jika lunas
|
||||
window.addEventListener("message", function (event) {
|
||||
const data = event.data;
|
||||
|
||||
// Atur tinggi iframe jika ada
|
||||
if (typeof data === "object" && data.frameHeight) {
|
||||
const iframe = document.getElementById("voucherFrame");
|
||||
if (iframe) {
|
||||
iframe.style.height = data.frameHeight + "px";
|
||||
console.log("Iframe height disesuaikan:", data.frameHeight);
|
||||
}
|
||||
}
|
||||
|
||||
// Isi voucher otomatis dan reload
|
||||
if (data.type === "voucher_paid" && data.voucher) {
|
||||
console.log("Menerima voucher_paid dari iframe:", data.voucher);
|
||||
|
||||
// localStorage.setItem("status", "Lunas");
|
||||
// localStorage.setItem("voucher", data.voucher);
|
||||
|
||||
const inputs = [
|
||||
document.querySelector('#voucher'),
|
||||
document.querySelector('input[name="username"]'),
|
||||
document.querySelector('input[name="password"]')
|
||||
];
|
||||
|
||||
inputs.forEach((input, i) => {
|
||||
if (input) {
|
||||
input.value = data.voucher;
|
||||
console.log(`Input dari iframe (${input.name || input.id}): ${data.voucher}`);
|
||||
}
|
||||
});
|
||||
|
||||
// Reload supaya auto-fill login aktif
|
||||
if (!sessionStorage.getItem("voucher_reloaded")) {
|
||||
sessionStorage.setItem("voucher_reloaded", "1");
|
||||
console.log("Melakukan reload sekali untuk auto login");
|
||||
location.reload();
|
||||
}
|
||||
}
|
||||
});
|
||||
})();
|
||||
@@ -0,0 +1,281 @@
|
||||
<?php
|
||||
include "/www/wwwroot/bilspro/config/connect.php";
|
||||
include "/www/wwwroot/bilspro/payment/paydisini/api_control.php";
|
||||
|
||||
if (!isset($_GET['id']) || empty($_GET['id'])) {
|
||||
die("ID tidak valid");
|
||||
}
|
||||
|
||||
$board_id = $_GET['id'];
|
||||
|
||||
$stmt = $pdo->prepare("SELECT * FROM setting_mikrotik WHERE board_id = :board_id");
|
||||
$stmt->bindParam(':board_id', $board_id, PDO::PARAM_STR);
|
||||
$stmt->execute();
|
||||
$servers = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="id">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title>Daftar Voucher</title>
|
||||
<link rel="stylesheet" href="style.css">
|
||||
</head>
|
||||
<body>
|
||||
<div class="voucher-container" id="voucher-container">
|
||||
<!-- Konten akan diisi melalui JavaScript berdasarkan localStorage -->
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function tampilkanKonfirmasi(nama, harga, ids, idm, idv) {
|
||||
const container = document.getElementById('voucher-container');
|
||||
container.innerHTML = `
|
||||
<div class="confirm-wrapper">
|
||||
<div class="confirm-box">
|
||||
<h3 class="confirm-title">Konfirmasi Pembelian</h3>
|
||||
<p class="confirm-nama">${nama}</p>
|
||||
<p class="confirm-harga">Rp ${harga.toLocaleString()}</p>
|
||||
<div class="confirm">
|
||||
<input type="text" id="waInput" placeholder="0812xxxxxxx" />
|
||||
<p class="confirm-info">Masukkan nomor WhatsApp untuk menerima kode voucher</p>
|
||||
</div>
|
||||
<div class="button-group">
|
||||
<button class="btn-submit" onclick="kirimPembayaran(${ids}, ${idm}, ${idv})">Bayar</button>
|
||||
<button class="btn-cancel" onclick="resetPembayaran()">Kembali</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
localStorage.setItem("harga", harga);
|
||||
localStorage.setItem("nama", nama);
|
||||
kirimHeight();
|
||||
}
|
||||
|
||||
function resetPembayaran() {
|
||||
localStorage.clear();
|
||||
window.location.reload();
|
||||
}
|
||||
|
||||
function countDown(expiredTimeString) {
|
||||
const targetDate = new Date(expiredTimeString.replace(" ", "T"));
|
||||
const countdownElement = document.getElementById("countdown");
|
||||
if (!countdownElement) return;
|
||||
const countdownFunction = setInterval(() => {
|
||||
const now = new Date().getTime();
|
||||
const distance = targetDate.getTime() - now;
|
||||
if (distance <= 0) {
|
||||
clearInterval(countdownFunction);
|
||||
countdownElement.textContent = "Waktu habis, memeriksa status pembayaran...";
|
||||
cekstatusPembayaran();
|
||||
return;
|
||||
}
|
||||
const hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
|
||||
const minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
|
||||
const seconds = Math.floor((distance % (1000 * 60)) / 1000);
|
||||
let countdownText = "";
|
||||
if (hours > 0) countdownText += hours + " jam ";
|
||||
if (minutes > 0 || hours > 0) countdownText += minutes + " menit ";
|
||||
countdownText += seconds + " detik";
|
||||
countdownElement.textContent = countdownText;
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
function kirimPembayaran(ids, idm, idv) {
|
||||
const wa = document.getElementById('waInput').value.trim();
|
||||
if (!wa.match(/^[0-9]{10,15}$/)) {
|
||||
alert("Nomor WhatsApp tidak valid");
|
||||
return;
|
||||
}
|
||||
const box = document.querySelector(".confirm-box");
|
||||
box.innerHTML = `
|
||||
<p style="margin-bottom:10px;">Memproses pembayaran...</p>
|
||||
<p>Mohon tunggu sebentar.</p>
|
||||
`;
|
||||
fetch("payment.php", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/x-www-form-urlencoded"
|
||||
},
|
||||
body: `ids=${encodeURIComponent(ids)}&idm=${encodeURIComponent(idm)}&idv=${encodeURIComponent(idv)}&wa=${encodeURIComponent(wa)}`
|
||||
})
|
||||
.then(response => response.text())
|
||||
.then(text => {
|
||||
try {
|
||||
const data = JSON.parse(text);
|
||||
if (data.success) {
|
||||
localStorage.setItem("status", "Pending");
|
||||
localStorage.setItem("voucher", data.voucher);
|
||||
localStorage.setItem("exppay", data.exppay);
|
||||
localStorage.setItem("order_id", data.order_id);
|
||||
localStorage.setItem("qr", data.qr);
|
||||
tampilkanQR(data.qr, data.exppay);
|
||||
} else {
|
||||
box.innerHTML = `<p style="color:red;">${data.message}</p>`;
|
||||
}
|
||||
} catch (e) {
|
||||
box.innerHTML = `<p style="color:red;">Respon tidak valid:<br>${text}</p>`;
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
box.innerHTML = `<p style="color:red;">Terjadi kesalahan: ${error}</p>`;
|
||||
});
|
||||
}
|
||||
|
||||
function cekstatusPembayaran() {
|
||||
const order_id = localStorage.getItem("order_id");
|
||||
if (!order_id) {
|
||||
console.log("ID pembayaran tidak ditemukan.");
|
||||
return;
|
||||
}
|
||||
|
||||
fetch("cek_status.php", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/x-www-form-urlencoded"
|
||||
},
|
||||
body: `order_id=${encodeURIComponent(order_id)}`
|
||||
})
|
||||
.then(response => response.text()) // Tangkap sebagai teks dulu untuk debug
|
||||
.then(text => {
|
||||
try {
|
||||
const data = JSON.parse(text);
|
||||
console.log("Response dari cek_status.php:", data);
|
||||
|
||||
if (!data.success) {
|
||||
console.log("Cek status gagal:", data.message || "Tidak diketahui");
|
||||
if (data.raw_response) console.log("Raw Response:", data.raw_response);
|
||||
return;
|
||||
}
|
||||
|
||||
const status = data.status;
|
||||
|
||||
if (status === "Lunas") {
|
||||
localStorage.setItem("status", "Lunas");
|
||||
tampilkanSukses(localStorage.getItem("nama"), "Rp " + localStorage.getItem("harga"), localStorage.getItem("voucher"));
|
||||
} else if (status === "Pending") {
|
||||
alert("Pembayaran masih diproses.");
|
||||
} else if (status === "Canceled" || status === "Failed") {
|
||||
alert("Pembayaran dibatalkan atau gagal.");
|
||||
resetPembayaran();
|
||||
} else {
|
||||
console.log("Status tidak dikenali:", status);
|
||||
}
|
||||
} catch (err) {
|
||||
console.log("Gagal parse JSON:", err);
|
||||
console.log("Respon mentah:", text);
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
console.log("Gagal melakukan request cek status:", err);
|
||||
});
|
||||
}
|
||||
|
||||
function tampilkanQR(qrUrl, expPay) {
|
||||
const container = document.getElementById("voucher-container");
|
||||
container.innerHTML = `
|
||||
<div class="confirm-wrapper">
|
||||
<div class="confirm-box">
|
||||
<p style="font-size: 12px;">Silakan melakukan pembayaran dengan QRIS di bawah ini</p>
|
||||
<img src="${qrUrl}" alt="QR Code" style="max-width: 180px;">
|
||||
<p style="font-size: 14px;" id="countdown"></p>
|
||||
<p style="font-size: 12px;">Kode voucher akan dikirim ke WhatsApp setelah pembayaran berhasil.</p>
|
||||
<div class="button-group">
|
||||
<button class="btn-cancel" onclick="resetPembayaran()">Batal</button>
|
||||
<button class="btn-submit" onclick="cekstatusPembayaran()">Cek Status</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
countDown(expPay);
|
||||
kirimHeight();
|
||||
}
|
||||
|
||||
function tampilkanSukses(nama, harga, kodeVoucher) {
|
||||
const container = document.getElementById("voucher-container");
|
||||
container.innerHTML = `
|
||||
<div class="confirm-wrapper">
|
||||
<div class="confirm-box">
|
||||
<div class="confirm-title">Pembayaran ${nama} ${harga}</div>
|
||||
<div class="confirm-harga">BERHASIL</div>
|
||||
<div class="confirm-info">Kode Voucher</div>
|
||||
<h3>${kodeVoucher}</h3>
|
||||
<div class="confirm-info">Silakan masukan kode voucher di atas</div>
|
||||
<div class="button-group">
|
||||
<button class="btn-cancel" onclick="resetPembayaran()">Tutup</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
kirimHeight();
|
||||
}
|
||||
|
||||
function tampilkanListVoucher() {
|
||||
const data = <?php
|
||||
$output = [];
|
||||
if (!empty($servers)) {
|
||||
$id_data_server = $servers[0]['id_data_server'];
|
||||
$stmt = $pdo->prepare("SELECT * FROM profile_paket WHERE jenis_profile = 'Hotspot' AND status = '1' AND id_data_server = :id_data_server");
|
||||
$stmt->bindParam(':id_data_server', $id_data_server, PDO::PARAM_INT);
|
||||
$stmt->execute();
|
||||
$paket = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
foreach ($paket as $p) {
|
||||
$output[] = [
|
||||
'nama' => htmlspecialchars($p['nama']),
|
||||
'harga' => (int)$p['harga_paket'],
|
||||
'ids' => (int)$p['id_data_server'],
|
||||
'idm' => (int)$servers[0]['id'],
|
||||
'idv' => (int)$p['id']
|
||||
];
|
||||
}
|
||||
}
|
||||
echo json_encode($output);
|
||||
?>;
|
||||
|
||||
const container = document.getElementById("voucher-container");
|
||||
container.innerHTML = "";
|
||||
if (data.length === 0) {
|
||||
container.innerHTML = "<p>Data Mikrotik tidak ditemukan.</p>";
|
||||
return;
|
||||
}
|
||||
data.forEach(p => {
|
||||
const html = `
|
||||
<div class="voucher-box">
|
||||
<div class="voucher-info">
|
||||
<div class="voucher-desc">${p.nama}</div>
|
||||
<div class="voucher-title">Rp. ${p.harga.toLocaleString()}</div>
|
||||
</div>
|
||||
<button class="btn-bayar" onclick="tampilkanKonfirmasi('${p.nama}', ${p.harga}, ${p.ids}, ${p.idm}, ${p.idv})">Beli</button>
|
||||
</div>
|
||||
`;
|
||||
container.innerHTML += html;
|
||||
});
|
||||
kirimHeight();
|
||||
}
|
||||
|
||||
function kirimHeight() {
|
||||
const tinggi = document.body.scrollHeight;
|
||||
window.parent.postMessage({ frameHeight: tinggi }, "*");
|
||||
}
|
||||
|
||||
window.addEventListener("load", () => {
|
||||
const status = localStorage.getItem("status");
|
||||
const kodeVoucher = localStorage.getItem("voucher");
|
||||
const expPay = localStorage.getItem("exppay");
|
||||
const qr = localStorage.getItem("qr");
|
||||
if (status === "Pending" && qr && expPay) {
|
||||
tampilkanQR(qr, expPay);
|
||||
} else if (status === "Lunas") {
|
||||
tampilkanSukses(localStorage.getItem("nama"), "Rp " + localStorage.getItem("harga"), localStorage.getItem("voucher"));
|
||||
parent.postMessage({
|
||||
type: "voucher_paid",
|
||||
voucher: localStorage.getItem("voucher")
|
||||
}, "*");
|
||||
} else {
|
||||
tampilkanListVoucher();
|
||||
}
|
||||
});
|
||||
|
||||
window.addEventListener("resize", kirimHeight);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,123 @@
|
||||
<?php
|
||||
|
||||
ini_set('display_errors', 1);
|
||||
ini_set('display_startup_errors', 1);
|
||||
error_reporting(E_ALL);
|
||||
|
||||
|
||||
include "/www/wwwroot/bilspro/config/connect.php";
|
||||
include "/www/wwwroot/bilspro/payment/paydisini/api_control.php";
|
||||
|
||||
header('Content-Type: application/json');
|
||||
|
||||
function generateOrderId($pdo) {
|
||||
do {
|
||||
$order_id = sprintf('%013d', mt_rand(0, 9999999999999));
|
||||
$stmt = $pdo->prepare("SELECT COUNT(*) FROM apk_payment WHERE order_id = :order_id");
|
||||
$stmt->bindParam(':order_id', $order_id);
|
||||
$stmt->execute();
|
||||
$exists = $stmt->fetchColumn();
|
||||
} while ($exists > 0);
|
||||
return $order_id;
|
||||
}
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
||||
echo json_encode(['success' => false, 'message' => 'Metode tidak diperbolehkan']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$ids = $_POST['ids'] ?? '';
|
||||
$idm = $_POST['idm'] ?? '';
|
||||
$idv = $_POST['idv'] ?? '';
|
||||
$wa = $_POST['wa'] ?? '';
|
||||
|
||||
if (!preg_match('/^[0-9]{10,15}$/', $wa)) {
|
||||
echo json_encode(['success' => false, 'message' => 'Nomor WhatsApp tidak valid']);
|
||||
exit;
|
||||
}
|
||||
if (empty($ids) || empty($idm) || empty($idv)) {
|
||||
echo json_encode(['success' => false, 'message' => 'Data tidak lengkap']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$stmt = $pdo->prepare("SELECT * FROM profile_paket WHERE id = :idv");
|
||||
$stmt->execute([':idv' => $idv]);
|
||||
$data1 = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if (!$data1) {
|
||||
echo json_encode(['success' => false, 'message' => 'Data paket tidak ditemukan']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$harga = $data1['harga_paket'];
|
||||
$kodeprofile = $data1['nama_profile'];
|
||||
$durasi = $data1['durasi'];
|
||||
|
||||
$karakter = "QWERTYUIOPASDFGHJKLZXCV12345098760987612345BNMQWERTYUIOPASGHJKLZXCVBNM";
|
||||
$kodevoucher = $durasi . substr(str_shuffle($karakter), 0, 7) . 'VPG';
|
||||
$create_time = date('Y-m-d H:i:s');
|
||||
|
||||
$stmt = $pdo->prepare("INSERT INTO ganerate_voucher
|
||||
(id_data_server, id_agen_voucher, id_setting_mikrotik, id_profile_paket, voucher, harga, create_time, jenis, nomor_whatsapp)
|
||||
VALUES (:ids, NULL, :idm, :idv, :voucher, :harga, :create_time, 'api-pw', :nomor_whatsapp)");
|
||||
$stmt->execute([
|
||||
':ids' => $ids,
|
||||
':idm' => $idm,
|
||||
':idv' => $idv,
|
||||
':voucher' => $kodevoucher,
|
||||
':harga' => $harga,
|
||||
':create_time' => $create_time,
|
||||
':nomor_whatsapp' => $wa
|
||||
]);
|
||||
$last_id = $pdo->lastInsertId();
|
||||
|
||||
$order_id = generateOrderId($pdo);
|
||||
$keterangan = "Pembelian voucher " . $kodevoucher;
|
||||
$waktu_transaksi = date("Y-m-d H:i:s");
|
||||
|
||||
$stmt = $pdo->prepare("INSERT INTO apk_payment
|
||||
(id_data_server, order_id, keterangan, waktu_transaksi, nominal, id_generate, status, jenis)
|
||||
VALUES
|
||||
(:ids, :order_id, :keterangan, :waktu_transaksi, :nominal, :id_generate, 'BELUM DIBAYAR', 'Hotspot')");
|
||||
$stmt->execute([
|
||||
':ids' => $ids,
|
||||
':order_id' => $order_id,
|
||||
':keterangan' => $keterangan,
|
||||
':waktu_transaksi' => $waktu_transaksi,
|
||||
':nominal' => $harga,
|
||||
':id_generate' => $last_id
|
||||
]);
|
||||
|
||||
$trxData = [
|
||||
'unique_code' => $order_id,
|
||||
'service' => 'qris',
|
||||
'amount' => $harga,
|
||||
'note' => $keterangan,
|
||||
'valid_time' => 300
|
||||
];
|
||||
|
||||
$response = CreateTransaction($trxData);
|
||||
$trxResult = json_decode($response);
|
||||
|
||||
if ($trxResult && $trxResult->success === true && isset($trxResult->data->qrcode_url)) {
|
||||
$qrImage = $trxResult->data->qrcode_url;
|
||||
$expired = $trxResult->data->expired;
|
||||
|
||||
$stmt = $pdo->prepare("UPDATE apk_payment SET data_get = :data_get, status = 'PENDING' WHERE order_id = :order_id");
|
||||
$stmt->execute([
|
||||
':data_get' => $response,
|
||||
':order_id' => $order_id
|
||||
]);
|
||||
|
||||
echo json_encode([
|
||||
'success' => true,
|
||||
'voucher' => $kodevoucher,
|
||||
'exppay' => $expired,
|
||||
'order_id' => $order_id,
|
||||
'qr' => $qrImage
|
||||
]);
|
||||
exit;
|
||||
} else {
|
||||
echo json_encode(['success' => false, 'message' => 'Gagal membuat transaksi QR']);
|
||||
exit;
|
||||
}
|
||||
@@ -0,0 +1,180 @@
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 20px;
|
||||
font-family: 'Segoe UI', sans-serif;
|
||||
background: #ffffff;
|
||||
}
|
||||
|
||||
.voucher-container {
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
/* Voucher Box */
|
||||
.voucher-box {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
background: linear-gradient(135deg, #ffffff, #fef5e6);
|
||||
border: 1px solid #f2e8d8;
|
||||
border-radius: 16px;
|
||||
padding: 18px 20px;
|
||||
margin-bottom: 16px;
|
||||
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.03);
|
||||
transition: all 0.25s ease-in-out;
|
||||
}
|
||||
|
||||
.voucher-box:hover {
|
||||
box-shadow: 0 6px 14px rgba(0, 0, 0, 0.08);
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
.voucher-info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.voucher-desc {
|
||||
font-size: 13px;
|
||||
color: #888;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.voucher-title {
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
color: #2c2c2c;
|
||||
}
|
||||
|
||||
.btn-bayar {
|
||||
background: linear-gradient(to right, #ff7e29, #ff5300);
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 50px;
|
||||
padding: 6px 14px;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
transition: background 0.3s ease, transform 0.2s ease;
|
||||
}
|
||||
|
||||
.btn-bayar:hover {
|
||||
background: linear-gradient(to right, #ff5300, #e44d00);
|
||||
transform: scale(1.05);
|
||||
box-shadow: 0 2px 8px rgba(255, 83, 0, 0.25);
|
||||
}
|
||||
|
||||
|
||||
/* Konfirmasi Pembelian */
|
||||
.confirm-wrapper {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
padding: 10px 15px;
|
||||
box-sizing: border-box;
|
||||
/* Hapus min-height agar tinggi dinamis mengikuti isi */
|
||||
min-height: 400px;
|
||||
}
|
||||
|
||||
.confirm-box {
|
||||
background: #fffaf4;
|
||||
border: 1px solid #ffd9b8;
|
||||
border-radius: 16px;
|
||||
padding: 22px 20px;
|
||||
max-width: 400px;
|
||||
width: 100%;
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.06);
|
||||
text-align: center;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.confirm-title {
|
||||
font-size: 16px;
|
||||
color: #333;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.confirm-nama {
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
margin: 4px 0;
|
||||
}
|
||||
|
||||
.confirm-harga {
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
color: #d35400;
|
||||
margin: 6px 0 12px;
|
||||
}
|
||||
|
||||
.confirm-info {
|
||||
font-size: 11px;
|
||||
color: #666;
|
||||
margin-top: 5px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.confirm-box input {
|
||||
width: 100%;
|
||||
padding: 5px;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 8px;
|
||||
font-size: 13px;
|
||||
box-sizing: border-box;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.button-group {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 10px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.btn-submit,
|
||||
.btn-cancel {
|
||||
padding: 8px 16px;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
border-radius: 50px;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.btn-submit {
|
||||
background: linear-gradient(to right, #ff7e29, #ff5300);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.btn-submit:hover {
|
||||
background: linear-gradient(to right, #ff5300, #e44d00);
|
||||
}
|
||||
|
||||
.btn-cancel {
|
||||
background-color: #ddd;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.btn-cancel:hover {
|
||||
background-color: #bbb;
|
||||
}
|
||||
|
||||
@media (max-width: 500px) {
|
||||
.voucher-box {
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.voucher-info {
|
||||
width: calc(100% - 100px);
|
||||
}
|
||||
|
||||
.btn-bayar {
|
||||
width: 80px;
|
||||
margin-top: 4px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.confirm-box {
|
||||
padding: 20px 15px;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user