PHP WebShell

Текущая директория: /var/www/bitcardoApp/user/data

Просмотр файла: detect.php

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Crypto/Bank Account Wizard</title>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css">
    <link href="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/css/select2.min.css" rel="stylesheet" />
    <style>
        body { background: #f8f9fa; }
        .step { display: none; }
        .step.active { display: block; }
        .form-label { font-weight: 500; }
        .select2-container--bootstrap5 .select2-selection {
            min-height: 38px;
            padding-top: 4px;
        }
    </style>
</head>
<body>
<div class="container py-5">
    <h3 class="mb-4">Wallet or Bank Account Wizard</h3>
    <form id="wizardForm" autocomplete="off">
        <!-- Step 1: Enter Address or Account -->
        <div class="step active" id="step1">
            <label for="inputValue" class="form-label">Enter Wallet Address or 10-digit Bank Account</label>
            <input type="text" id="inputValue" class="form-control mb-3" placeholder="e.g. 0x... or 1234567890">
            <div id="detectFeedback" class="form-text mb-3"></div>
            <button type="button" class="btn btn-primary" id="toStep2" disabled>Next</button>
        </div>
        <!-- Step 2: Bank or Crypto Details -->
        <div class="step" id="step2">
            <!-- For Bank -->
            <div id="bankSection" style="display:none;">
                <label for="bankSelect" class="form-label">Bank</label>
                <select class="form-select mb-2" id="bankSelect" style="width: 100%"></select>
                <label for="accountNumber" class="form-label">Account Number</label>
                <input type="text" id="accountNumber" class="form-control mb-2" maxlength="10" readonly>
                <div class="row g-2">
                    <div class="col">
                        <label for="fname" class="form-label">First Name</label>
                        <input type="text" id="fname" class="form-control" readonly>
                    </div>
                    <div class="col">
                        <label for="lname" class="form-label">Last Name</label>
                        <input type="text" id="lname" class="form-control" readonly>
                    </div>
                </div>
                <div id="bankError" class="form-text text-danger"></div>
            </div>
            <!-- For Crypto -->
            <div id="cryptoSection" style="display:none;">
                <label for="walletTypeSelect" class="form-label">Coin/Token Type <span class="text-danger">*</span></label>
                <select id="walletTypeSelect" class="form-select mb-2" required></select>
                <label for="walletName" class="form-label">Wallet Label (optional)</label>
                <input type="text" id="walletName" class="form-control mb-2" placeholder="Label this wallet (optional)">
                <div class="row g-2">
                    <div class="col">
                        <label for="cryptoFname" class="form-label">First Name (optional)</label>
                        <input type="text" id="cryptoFname" class="form-control">
                    </div>
                    <div class="col">
                        <label for="cryptoLname" class="form-label">Last Name (optional)</label>
                        <input type="text" id="cryptoLname" class="form-control">
                    </div>
                </div>
                <div id="cryptoTypeError" class="form-text text-danger"></div>
            </div>
            <button type="button" class="btn btn-secondary me-2" id="backStep1">Back</button>
            <button type="submit" class="btn btn-success" id="submitBtn">Finish</button>
        </div>
    </form>
    <div id="wizardResult" class="mt-4"></div>
</div>

<script src="https://cdn.jsdelivr.net/npm/jquery@3.7.1/dist/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/js/select2.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
<script>
// ----------- Coin Detection -------------
function detectCoin(address) {
    address = address.trim();
    // Returns array of possible types
    if (/^(1|3)[A-HJ-NP-Za-km-z1-9]{25,34}$/.test(address) ||
        /^(bc1)[0-9ac-hj-np-z]{25,39}$/.test(address.toLowerCase()))
        return ['BTC'];
    if (/^0x[a-fA-F0-9]{40}$/.test(address))
        return ['ETH', 'USDT-ERC20', 'BNB (BEP20)', 'ERC20 Token'];
    if (/^T[a-zA-Z0-9]{33}$/.test(address))
        return ['TRX', 'USDT-TRC20'];
    if (/^[LM3][a-km-zA-HJ-NP-Z1-9]{26,33}$/.test(address) ||
        /^(ltc1)[0-9ac-hj-np-z]{39,59}$/.test(address.toLowerCase()))
        return ['LTC'];
    if (/^D{1}[5-9A-HJ-NP-Ua-km-z]{33}$/.test(address))
        return ['DOGE'];
    if (/^r[1-9A-HJ-NP-Za-km-z]{25,34}$/.test(address))
        return ['XRP'];
    if (/^[1-9A-HJ-NP-Za-km-z]{32,44}$/.test(address))
        return ['SOL'];
    return null;
}

// ---------- Bank Detection -------------
function looksLikeNigerianBankAccount(input) {
    return /^\d{10}$/.test(input);
}

function splitName(name) {
    if (!name) return { fname: '', lname: '' };
    let parts = name.trim().split(/\s+/);
    let fname = parts[0] || '';
    let lname = parts.length > 1 ? parts.slice(1).join(' ') : '';
    return { fname, lname };
}

// ---- Call backend to get all banks ----
function fetchAllBanks(cb) {
    fetch('bank-api.php?action=get_banks', {method: 'GET'})
    .then(res => res.json())
    .then(cb)
    .catch(() => cb({ status: false, message: 'Could not load banks', data: [] }));
}

// ---- Call backend to verify account via Paystack ----
function verifyBankAccount(account_number, bank_code, cb) {
    fetch('bank-api.php', {
        method: 'POST',
        headers: {'Content-Type': 'application/json'},
        body: JSON.stringify({ action: 'resolve_account', account_number, bank_code })
    })
    .then(res => res.json())
    .then(cb)
    .catch(() => cb({status: false, message: 'Network error'}));
}

document.addEventListener('DOMContentLoaded', function () {
    const bankSelect = document.getElementById('bankSelect');
    fetchAllBanks(function (resp) {
        if (resp.status !== false && Array.isArray(resp.data)) {
            bankSelect.innerHTML = resp.data.map(
                b => `<option value="${b.code}">${b.name}</option>`
            ).join('');
        } else {
            bankSelect.innerHTML = `<option value="058">GTBank</option><option value="033">UBA</option>`;
        }
        $(bankSelect).select2({ theme: "bootstrap5", width: '100%' });
    });

    // Elements
    const inputValue = document.getElementById('inputValue');
    const detectFeedback = document.getElementById('detectFeedback');
    const toStep2 = document.getElementById('toStep2');
    const step1 = document.getElementById('step1');
    const step2 = document.getElementById('step2');
    const bankSection = document.getElementById('bankSection');
    const cryptoSection = document.getElementById('cryptoSection');
    const accountNumber = document.getElementById('accountNumber');
    const bankError = document.getElementById('bankError');
    const walletTypeSelect = document.getElementById('walletTypeSelect');
    const walletName = document.getElementById('walletName');
    const backStep1 = document.getElementById('backStep1');
    const form = document.getElementById('wizardForm');
    const resultDiv = document.getElementById('wizardResult');
    const fname = document.getElementById('fname');
    const lname = document.getElementById('lname');
    const cryptoFname = document.getElementById('cryptoFname');
    const cryptoLname = document.getElementById('cryptoLname');
    const cryptoTypeError = document.getElementById('cryptoTypeError');
    const submitBtn = document.getElementById('submitBtn');

    let detectedType = null; // 'bank' or 'crypto'
    let detectedCoin = null;

    inputValue.addEventListener('input', function () {
        let val = inputValue.value.trim();
        detectedType = null;
        detectedCoin = null;
        toStep2.disabled = true;
        detectFeedback.textContent = '';

        if (looksLikeNigerianBankAccount(val)) {
            detectedType = 'bank';
            detectFeedback.textContent = "Detected: Nigerian bank account number. Click Next to continue.";
            toStep2.disabled = false;
        } else {
            let coins = detectCoin(val);
            if (coins) {
                detectedType = 'crypto';
                detectedCoin = coins;
                if (coins.length > 1) {
                    detectFeedback.textContent = `Detected: This address can be used for multiple networks/tokens. Please select the actual coin/token you use.`;
                } else {
                    detectFeedback.textContent = `Detected: ${coins[0]} wallet address. Click Next to continue.`;
                }
                toStep2.disabled = false;
            } else if (val.length > 0) {
                detectFeedback.textContent = "Input not recognized as wallet or bank account.";
            }
        }
    });

    toStep2.addEventListener('click', function () {
        step1.classList.remove('active');
        step2.classList.add('active');
        bankError.textContent = '';
        cryptoTypeError.textContent = '';
        if (detectedType === 'bank') {
            bankSection.style.display = 'block';
            cryptoSection.style.display = 'none';
            accountNumber.value = inputValue.value.trim();
            fname.value = '';
            lname.value = '';
            fname.readOnly = true;
            lname.readOnly = true;
            setTimeout(() => {
                verifyBankAccount(accountNumber.value, bankSelect.value, function (resp) {
                    if (resp.status && resp.data && resp.data.account_name) {
                        let split = splitName(resp.data.account_name);
                        fname.value = split.fname;
                        lname.value = split.lname;
                        bankError.textContent = '';
                        submitBtn.disabled = false;
                    } else {
                        fname.value = '';
                        lname.value = '';
                        bankError.textContent = 'Could not resolve account name.';
                        submitBtn.disabled = true;
                    }
                });
            }, 100);
        } else if (detectedType === 'crypto') {
            cryptoSection.style.display = 'block';
            bankSection.style.display = 'none';
            walletTypeSelect.innerHTML = '';
            walletName.value = '';
            cryptoFname.value = '';
            cryptoLname.value = '';
            // Populate select with possible types
            let placeholderOption = '';
            if (detectedCoin.length > 1) {
                placeholderOption = `<option value="" selected disabled>-- Select Coin/Token Type --</option>`;
            }
            walletTypeSelect.innerHTML = placeholderOption + detectedCoin.map(function (coin, idx) {
                if (detectedCoin.length === 1) {
                    return `<option value="${coin}" selected>${coin}</option>`;
                } else {
                    return `<option value="${coin}">${coin}</option>`;
                }
            }).join('');
            // Required attribute always set
            walletTypeSelect.setAttribute('required', 'required');
        }
    });

    backStep1.addEventListener('click', function () {
        step2.classList.remove('active');
        step1.classList.add('active');
        form.reset();
        detectFeedback.textContent = '';
        toStep2.disabled = true;
        bankError.textContent = '';
        cryptoTypeError.textContent = '';
        resultDiv.innerHTML = '';
        fname.value = '';
        lname.value = '';
        cryptoFname.value = '';
        cryptoLname.value = '';
        walletTypeSelect.innerHTML = '';
    });

    // For Select2, use jQuery event for bankSelect
    $(bankSelect).on('change', function () {
        const selectedBankCode = $(this).val();
        accountNumber.value = inputValue.value.trim();
        fname.value = '';
        lname.value = '';
        bankError.textContent = 'Verifying...';
        submitBtn.disabled = true;
        verifyBankAccount(accountNumber.value, selectedBankCode, function (resp) {
            if (resp.status && resp.data && resp.data.account_name) {
                let split = splitName(resp.data.account_name);
                fname.value = split.fname;
                lname.value = split.lname;
                bankError.textContent = '';
                submitBtn.disabled = false;
            } else {
                fname.value = '';
                lname.value = '';
                bankError.textContent = 'Could not resolve account name.';
                submitBtn.disabled = true;
            }
        });
    });

    form.addEventListener('submit', function (e) {
        e.preventDefault();
        cryptoTypeError.textContent = '';
        // Show result
        if (detectedType === 'bank') {
            resultDiv.innerHTML = `
                <div class="alert alert-success">
                    <b>Bank Account Saved!</b><br>
                    Bank: ${bankSelect.options[bankSelect.selectedIndex].text}<br>
                    Account: ${accountNumber.value}<br>
                    First Name: ${fname.value}<br>
                    Last Name: ${lname.value}
                </div>
            `;
        } else if (detectedType === 'crypto') {
            const selectedToken = walletTypeSelect.value;
            if (!selectedToken) {
                cryptoTypeError.textContent = "Please select the coin/token type.";
                walletTypeSelect.focus();
                return false;
            }
            resultDiv.innerHTML = `
                <div class="alert alert-primary">
                    <b>Wallet Saved!</b><br>
                    Type: ${selectedToken}<br>
                    Address: ${inputValue.value.trim()}<br>
                    Wallet Label: ${walletName.value || '(not set)'}<br>
                    First Name: ${cryptoFname.value || ''}<br>
                    Last Name: ${cryptoLname.value || ''}
                </div>
            `;
        }
        setTimeout(() => {
            backStep1.click();
        }, 2000);
    });
});
</script>
</body>
</html>

Выполнить команду


Для локальной разработки. Не используйте в интернете!