login.php cho wifi marketing Ruckus

 <?php
function h($s) {
    return htmlspecialchars((string)$s, ENT_QUOTES, 'UTF-8');
}

function cleanParams(array $input): array {
    $clean = [];

    foreach ($input as $key => $value) {
        $key = preg_replace('/^amp;/', '', (string)$key);
        $clean[$key] = $value;
    }

    return $clean;
}

$params = cleanParams($_POST);

// =======================
// CONFIG
// =======================

$defaultNbiHost = 'thay IP controller vào đây';

$nbiUser = 'nbi-acc';
$nbiPass = 'pass của nbi-acc';

// AAA Always Accept nên user/pass này chỉ là dummy
$ueUsername = 'ok';
$uePassword = 'ok';

// Chỉ cho phép gọi đúng vSZ NBI này
$allowedNbiHosts = [
    'thay IP controller vào đây',
];

// =======================
// INPUT FROM vSZ
// =======================

$nbiHost = $params['nbiIP'] ?? $defaultNbiHost;

if (!in_array($nbiHost, $allowedNbiHosts, true)) {
    $nbiHost = $defaultNbiHost;
}

$nbiUrl = 'https://' . $nbiHost . ':9443/portalintf';

$ueIp    = $params['uip'] ?? '';
$ueMac   = $params['client_mac'] ?? '';
$ueProxy = $params['proxy'] ?? '0';

if ($ueIp === '' || $ueMac === '') {
    http_response_code(400);
    echo 'Missing uip or client_mac';
    exit;
}

// =======================
// BUILD PAYLOAD
// =======================

$payload = [
    'Vendor'          => 'ruckus',
    'APIVersion'      => '1.0',
    'RequestCategory' => 'UserOnlineControl',
    'RequestType'     => 'Login',

    'RequestUserName' => $nbiUser,
    'RequestPassword' => $nbiPass,

    'UE-IP'       => $ueIp,
    'UE-MAC'      => $ueMac,
    'UE-Proxy'    => $ueProxy,
    'UE-Username' => $ueUsername,
    'UE-Password' => $uePassword,
];

// =======================
// CALL vSZ NBI
// =======================

$ch = curl_init($nbiUrl);

curl_setopt_array($ch, [
    CURLOPT_POST           => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER     => [
        'Content-Type: application/json',
        'Accept: application/json',
    ],
    CURLOPT_POSTFIELDS     => json_encode($payload, JSON_UNESCAPED_SLASHES),

    // vSZ cert đang expired/self-signed thì để false.
    // Khi thay cert chuẩn có thể bật verify lại.
    CURLOPT_SSL_VERIFYPEER => false,
    CURLOPT_SSL_VERIFYHOST => false,

    CURLOPT_CONNECTTIMEOUT => 5,
    CURLOPT_TIMEOUT        => 10,
]);

$response = curl_exec($ch);

$curlNo   = curl_errno($ch);
$curlErr  = curl_error($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$info     = curl_getinfo($ch);

curl_close($ch);

// =======================
// LOG DEBUG
// =======================

$logPayload = $payload;
$logPayload['RequestPassword'] = '***';

/*
file_put_contents(
    __DIR__ . '/nbi-login.log',
    date('c') .
    ' URL=' . $nbiUrl .
    ' HTTP=' . $httpCode .
    ' CURL_NO=' . $curlNo .
    ' CURL_ERR=' . $curlErr .
    ' INFO=' . json_encode($info, JSON_UNESCAPED_SLASHES) .
    ' PAYLOAD=' . json_encode($logPayload, JSON_UNESCAPED_SLASHES) .
    ' RESPONSE=' . $response .
    PHP_EOL,
    FILE_APPEND
);
*/

// =======================
// CHECK CURL RESULT
// =======================

if ($response === false || $curlNo !== 0 || $curlErr !== '' || $httpCode < 200 || $httpCode >= 300) {
    http_response_code(500);

    echo '<pre>';
    echo "NBI request failed\n";
    echo "HTTP: " . h($httpCode) . "\n";
    echo "CURL_NO: " . h($curlNo) . "\n";
    echo "CURL_ERR: " . h($curlErr) . "\n";
    echo "Response:\n" . h($response) . "\n";
    echo '</pre>';

    exit;
}

$data = json_decode($response, true);

$responseCode = isset($data['ResponseCode']) ? (int)$data['ResponseCode'] : 0;
$replyMessage = $data['ReplyMessage'] ?? '';

// vSZ có thể trả:
// 201 = Login succeeded
// 101 = Client authorized
$successCodes = [101, 201];

if (!in_array($responseCode, $successCodes, true)) {
    http_response_code(500);

    echo '<pre>';
    echo "NBI login not successful\n";
    echo "ResponseCode: " . h($responseCode) . "\n";
    echo "ReplyMessage: " . h($replyMessage) . "\n";
    echo "Full response:\n" . h($response) . "\n";
    echo '</pre>';

    exit;
}

// =======================
// SUCCESS PAGE
// =======================

header('Content-Type: text/html; charset=utf-8');
header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
header('Pragma: no-cache');
?>
<!doctype html>
<html lang="vi">
<head>
    <meta charset="utf-8">
    <title>Connected</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <style>
        * { box-sizing: border-box; }
        body {
            margin: 0;
            min-height: 100vh;
            font-family: Arial, sans-serif;
            background: #111827;
            color: white;
            display: flex;
            align-items: center;
            justify-content: center;
            text-align: center;
        }
        .box {
            width: 90%;
            max-width: 360px;
            background: #ffffff;
            color: #111827;
            padding: 28px;
            border-radius: 16px;
            box-shadow: 0 20px 50px rgba(0,0,0,.35);
        }
        .check {
            width: 64px;
            height: 64px;
            margin: 0 auto 16px;
            border-radius: 50%;
            background: #16a34a;
            color: #ffffff;
            display: flex;
            align-items: center;
            justify-content: center;
            font-size: 36px;
            font-weight: bold;
        }
        h2 { margin: 0 0 10px; font-size: 24px; }
        p { margin: 0; color: #4b5563; line-height: 1.5; }
        .small { margin-top: 12px; font-size: 12px; color: #6b7280; }
        .dots span {
            animation: bounce 1.2s infinite ease-in-out;
            display: inline-block;
        }
        .dots span:nth-child(2) { animation-delay: 0.2s; }
        .dots span:nth-child(3) { animation-delay: 0.4s; }
        @keyframes bounce {
            0%, 80%, 100% { transform: translateY(0); opacity: 0.4; }
            40% { transform: translateY(-5px); opacity: 1; }
        }
        #preload-frame {
            position: absolute;
            width: 1px;
            height: 1px;
            opacity: 0;
            pointer-events: none;
            border: none;
        }
    </style>
</head>
<body>
    <div class="box">
        <div class="check">✓</div>
        <h2>Connected</h2>
        <p>Bạn đã kết nối Internet.</p>
        <div class="small dots">Đang chuyển hướng<span>.</span><span>.</span><span>.</span></div>
    </div>

    <iframe id="preload-frame"></iframe>

<script>
    const TARGET = 'https://tamanhhospital.vn/vu-tru-robot/?utm_campaign=bvta_longbien_wifi-sitelongbien_vutrurobot2026_he-thong-may-moc_traffic&utm_source=wifi-sitelongbien&utm_medium=wifi-marketing&utm_content=robot-traffic&utm_term=mass';
    const MIN_DISPLAY_MS = 4000; // minimum time to show this screen

    const start = Date.now();
    let iframeReady = false;
    let timerDone = false;

    function tryRedirect() {
        if (iframeReady || timerDone) {
            window.location.replace(TARGET);
        }
    }

    // Start preloading in hidden iframe
    const frame = document.getElementById('preload-frame');
    frame.src = TARGET;
    frame.onload = function () {
        iframeReady = true;
        tryRedirect();
    };
    frame.onerror = function () {
        // If iframe fails (e.g. X-Frame-Options blocks it), redirect anyway
        iframeReady = true;
        tryRedirect();
    };

    // Minimum display timer
    setTimeout(function () {
        timerDone = true;
        tryRedirect();
    }, MIN_DISPLAY_MS);
</script>
</body>
</html>
<?php
exit;

index.php cho wifi marketing Ruckus

<?php
function h($s) {
    return htmlspecialchars((string)$s, ENT_QUOTES, 'UTF-8');
}

function getCleanParams(): array {
    $query = parse_url($_SERVER['REQUEST_URI'] ?? '', PHP_URL_QUERY) ?? '';
    $query = html_entity_decode($query, ENT_QUOTES | ENT_HTML5, 'UTF-8');

    $params = [];
    parse_str($query, $params);

    $clean = [];
    foreach ($params as $key => $value) {
        $key = preg_replace('/^amp;/', '', (string)$key);
        $clean[$key] = $value;
    }

    return $clean;
}

$params = getCleanParams();
?>
<!doctype html>
<html lang="vi">
<head>
    <meta charset="utf-8">
    <title>Guest Wi-Fi</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <style>
        * {
            box-sizing: border-box;
        }

        body {
            margin: 0;
            height: 100vh;
            font-family: Arial, sans-serif;
            background: #111827;
            display: flex;
            align-items: center;
            justify-content: center;
        }

        .box {
            width: 90%;
            max-width: 420px;
            background: #ffffff;
            padding: 0;
            border-radius: 16px;
            text-align: center;
            box-shadow: 0 20px 50px rgba(0, 0, 0, .35);
            overflow: hidden;
        }

        .slider {
            position: relative;
            width: 100%;
            aspect-ratio: 9 / 16;
            overflow: hidden;
            background: #e5e7eb;
        }

        .slide {
            position: absolute;
            inset: 0;
            width: 100%;
            height: 100%;
            object-fit: contain;
            opacity: 0;
            transition: opacity 600ms ease-in-out;
        }

        .slide.active {
            opacity: 1;
        }

        .dots {
            position: absolute;
            left: 0;
            right: 0;
            bottom: 10px;
            display: flex;
            justify-content: center;
            gap: 6px;
        }

        .dot {
            width: 8px;
            height: 8px;
            border-radius: 50%;
            background: rgba(255, 255, 255, .55);
        }

        .dot.active {
            background: #ffffff;
        }

        .content {
            padding: 24px;
            background: #111111;
        }

        button {
            width: 100%;
            padding: 14px;
            border: 0;
            border-radius: 10px;
            background: #2563eb;
            color: #ffffff;
            font-size: 17px;
            font-weight: bold;
            cursor: pointer;
        }

        button:hover {
            background: #1d4ed8;
        }

        button:disabled {
            background: #9ca3af;
            cursor: not-allowed;
        }
    </style>
</head>
<body>
    <div class="box">
        <div class="slider">
            <img class="slide active" src="images/1.jpg" alt="Slide 1">
            <img class="slide" src="images/2.jpg" alt="Slide 2">

            <div class="dots">
                <span class="dot active"></span>
                <span class="dot"></span>
            </div>
        </div>

        <div class="content">
            <form method="post" action="login.php" id="connectForm">
                <?php foreach ($params as $key => $value): ?>
                    <input type="hidden" name="<?= h($key) ?>" value="<?= h($value) ?>">
                <?php endforeach; ?>

                <button type="submit" id="connectBtn">Kết nối Internet</button>
            </form>
        </div>
    </div>

    <script>
        const slides = document.querySelectorAll('.slide');
        const dots = document.querySelectorAll('.dot');
        let currentSlide = 0;

        function showSlide(index) {
            slides.forEach(function (slide, i) {
                slide.classList.toggle('active', i === index);
            });
            dots.forEach(function (dot, i) {
                dot.classList.toggle('active', i === index);
            });
        }

        if (slides.length > 1) {
            setInterval(function () {
                currentSlide = (currentSlide + 1) % slides.length;
                showSlide(currentSlide);
            }, 2000);
        }

        document.getElementById('connectForm').addEventListener('submit', function () {
            const btn = document.getElementById('connectBtn');
            btn.innerText = 'Đang kết nối...';
            btn.disabled = true;
        });
    </script>
</body>
</html>

Backup file local sang shard folder

Tạo VBscript: 

Set WshShell = CreateObject("WScript.Shell")

cmd = "robocopy ""Source-path"" ""Target=path"" /E /XO /Z /FFT /R:2 /W:5 /MT:16"

WshShell.Run cmd, 0, True 

Tạo task schdule chạy mỗi 60 phút:

schtasks /Create /TN "ZaloData Robocopy" /SC MINUTE /MO 60 /TR "wscript.exe \"Script-path\DataBackup.vbs\"" /F

login.php cho wifi marketing Ruckus

 <?php function h($s) {     return htmlspecialchars((string)$s, ENT_QUOTES, 'UTF-8'); } function cleanParams(array $input): array...