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>
Выполнить команду
Для локальной разработки. Не используйте в интернете!