部署了
This commit is contained in:
parent
9a636e4275
commit
190d007ef0
@ -73,7 +73,7 @@ ob_start();
|
||||
<table class="table table-hover align-middle">
|
||||
<thead>
|
||||
<tr class="text-muted small">
|
||||
<th>ID</th>
|
||||
<th>编号</th>
|
||||
<th>用户名</th>
|
||||
<th>下属用户数</th>
|
||||
<th>权限</th>
|
||||
|
||||
@ -9,12 +9,21 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
'usdt_bep20_address' => $_POST['usdt_bep20_address'] ?? '',
|
||||
'service_link' => $_POST['service_link'] ?? '',
|
||||
'site_name' => $_POST['site_name'] ?? 'Byro',
|
||||
'rate_MYR' => $_POST['rate_MYR'] ?? '',
|
||||
'rate_CNY' => $_POST['rate_CNY'] ?? '',
|
||||
'rate_EUR' => $_POST['rate_EUR'] ?? '',
|
||||
];
|
||||
|
||||
foreach ($settings as $key => $val) {
|
||||
$stmt = db()->prepare("INSERT INTO system_settings (setting_key, setting_value) VALUES (?, ?) ON DUPLICATE KEY UPDATE setting_value = ?");
|
||||
$stmt->execute([$key, $val, $val]);
|
||||
}
|
||||
|
||||
// Clear exchange rate cache
|
||||
$cache_file = __DIR__ . '/../db/exchange_rates.json';
|
||||
if (file_exists($cache_file)) {
|
||||
unlink($cache_file);
|
||||
}
|
||||
|
||||
// Handle logo upload if provided
|
||||
if (isset($_FILES['logo_file']) && $_FILES['logo_file']['error'] === 0) {
|
||||
@ -174,6 +183,26 @@ ob_start();
|
||||
<input type="text" name="usdt_bep20_address" class="form-control" value="<?= htmlspecialchars($bep20_addr) ?>" placeholder="请输入 BEP20 钱包地址">
|
||||
</div>
|
||||
|
||||
<hr class="my-4">
|
||||
<h6 class="fw-bold mb-3 text-primary"><i class="bi bi-currency-exchange me-2"></i>法币汇率配置 (1 USDT = ?)</h6>
|
||||
<div class="row g-3">
|
||||
<div class="col-md-4">
|
||||
<label class="form-label small fw-bold">MYR (马来西亚林吉特)</label>
|
||||
<input type="number" step="0.01" name="rate_MYR" class="form-control" value="<?= htmlspecialchars(getSetting('rate_MYR', '')) ?>" placeholder="例如: 4.45">
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label class="form-label small fw-bold">CNY (人民币)</label>
|
||||
<input type="number" step="0.01" name="rate_CNY" class="form-control" value="<?= htmlspecialchars(getSetting('rate_CNY', '')) ?>" placeholder="例如: 7.25">
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label class="form-label small fw-bold">EUR (欧元)</label>
|
||||
<input type="number" step="0.01" name="rate_EUR" class="form-control" value="<?= htmlspecialchars(getSetting('rate_EUR', '')) ?>" placeholder="例如: 0.95">
|
||||
</div>
|
||||
<div class="col-12 mt-2">
|
||||
<div class="form-text text-warning"><i class="bi bi-exclamation-triangle-fill me-1"></i>留空则使用系统自动获取的实时汇率。建议在 API 延迟或汇率波动剧烈时手动设置。</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr class="my-4">
|
||||
<h6 class="fw-bold mb-3 text-primary"><i class="bi bi-shield-check me-2"></i>安全与功能</h6>
|
||||
|
||||
|
||||
@ -92,7 +92,7 @@ $orders = $stmt->fetchAll();
|
||||
<table class="table table-hover align-middle">
|
||||
<thead>
|
||||
<tr class="text-muted small">
|
||||
<th>ID</th>
|
||||
<th>编号</th>
|
||||
<th>用户信息</th>
|
||||
<th>币种/方向</th>
|
||||
<th>金额/时长</th>
|
||||
|
||||
@ -45,7 +45,7 @@ $orders = $stmt->fetchAll();
|
||||
<table class="table table-hover">
|
||||
<thead>
|
||||
<tr class="small text-muted">
|
||||
<th>ID</th>
|
||||
<th>编号</th>
|
||||
<th>用户</th>
|
||||
<th>币种/方向</th>
|
||||
<th>杠杆/金额</th>
|
||||
|
||||
@ -263,10 +263,6 @@ ob_start();
|
||||
<label class="form-label small fw-bold text-muted">收款账号 / 地址 (Account Number)</label>
|
||||
<input type="text" id="pay-account" class="form-control form-control-lg fs-6 fw-bold text-primary" placeholder="银行卡号或钱包地址">
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label small fw-bold text-muted">订单金额 (Amount)</label>
|
||||
<input type="text" id="pay-amount" class="form-control form-control-lg fs-6 fw-bold text-danger" placeholder="请输入订单确切金额">
|
||||
</div>
|
||||
<div class="mb-0">
|
||||
<label class="form-label small fw-bold text-muted">转账说明 / 备注 (Instructions)</label>
|
||||
<textarea id="pay-note" class="form-control" rows="3" placeholder="告知用户转账时需要注意的事项,例如:务必备注UID"></textarea>
|
||||
@ -633,7 +629,7 @@ async function notifyMatchSuccess() {
|
||||
const r = await fetch('/api/admin_recharge.php?action=match_success', { method: 'POST', body: fd });
|
||||
const res = await r.json();
|
||||
if (res.success) {
|
||||
alert('匹配成功!状态已更新为“匹配中”。若要向用户显示收款账户,请继续点击“发送账户”按钮。');
|
||||
alert('匹配成功!状态已更新为“matched”。若要向用户显示收款账户,请继续点击“发送账户”按钮。');
|
||||
} else {
|
||||
alert('错误: ' + res.error);
|
||||
}
|
||||
@ -645,7 +641,6 @@ async function sendPaymentInfo() {
|
||||
const bank = document.getElementById('pay-bank').value.trim();
|
||||
const name = document.getElementById('pay-name').value.trim();
|
||||
const account = document.getElementById('pay-account').value.trim();
|
||||
const amount = document.getElementById('pay-amount').value.trim();
|
||||
|
||||
if (!bank || !name || !account) {
|
||||
alert('请完整填写收款信息');
|
||||
@ -657,10 +652,9 @@ async function sendPaymentInfo() {
|
||||
fd.append('bank', bank);
|
||||
fd.append('name', name);
|
||||
fd.append('account', account);
|
||||
if (amount) fd.append('amount', amount);
|
||||
|
||||
try {
|
||||
console.log('Sending account info...', { bank, name, account, amount });
|
||||
console.log('Sending account info...', { bank, name, account });
|
||||
const r = await fetch('/api/admin_recharge.php?action=send_account', { method: 'POST', body: fd });
|
||||
const res = await r.json();
|
||||
|
||||
@ -671,7 +665,6 @@ async function sendPaymentInfo() {
|
||||
document.getElementById('pay-bank').value = '';
|
||||
document.getElementById('pay-name').value = '';
|
||||
document.getElementById('pay-account').value = '';
|
||||
document.getElementById('pay-amount').value = '';
|
||||
document.getElementById('pay-note').value = '';
|
||||
alert('账户信息已发送,用户页面将立即显示收款账户');
|
||||
} else {
|
||||
|
||||
@ -31,21 +31,33 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action'])) {
|
||||
|
||||
// If recharge, add to balance
|
||||
if ($req['type'] === 'recharge') {
|
||||
$final_amount = $req['amount'];
|
||||
// For fiat recharge, recalculate based on current rate to ensure precision at approval time
|
||||
if (!empty($req['fiat_amount']) && !empty($req['fiat_currency'])) {
|
||||
require_once __DIR__ . '/../includes/exchange.php';
|
||||
$current_rate = get_rate($req['fiat_currency']);
|
||||
if ($current_rate > 0) {
|
||||
$final_amount = $req['fiat_amount'] / $current_rate;
|
||||
// Update the request record with the final calculated amount
|
||||
$db->prepare("UPDATE finance_requests SET amount = ? WHERE id = ?")->execute([$final_amount, $id]);
|
||||
}
|
||||
}
|
||||
|
||||
$stmt = $db->prepare("SELECT * FROM user_balances WHERE user_id = ? AND symbol = ?");
|
||||
$stmt->execute([$req['user_id'], $req['symbol']]);
|
||||
$bal = $stmt->fetch();
|
||||
|
||||
if ($bal) {
|
||||
$db->prepare("UPDATE user_balances SET available = available + ? WHERE id = ?")
|
||||
->execute([$req['amount'], $bal['id']]);
|
||||
->execute([$final_amount, $bal['id']]);
|
||||
} else {
|
||||
$db->prepare("INSERT INTO user_balances (user_id, symbol, available) VALUES (?, ?, ?)")
|
||||
->execute([$req['user_id'], $req['symbol'], $req['amount']]);
|
||||
->execute([$req['user_id'], $req['symbol'], $final_amount]);
|
||||
}
|
||||
|
||||
// Add to transactions history
|
||||
// Add to transactions history with the final amount
|
||||
$db->prepare("INSERT INTO transactions (user_id, type, amount, symbol, status) VALUES (?, 'recharge', ?, ?, 'completed')")
|
||||
->execute([$req['user_id'], $req['amount'], $req['symbol']]);
|
||||
->execute([$req['user_id'], $final_amount, $req['symbol']]);
|
||||
}
|
||||
|
||||
// If withdrawal, update transaction status
|
||||
@ -142,7 +154,7 @@ $requests = $stmt->fetchAll();
|
||||
<table class="table table-hover align-middle">
|
||||
<thead>
|
||||
<tr class="text-muted small">
|
||||
<th>ID</th>
|
||||
<th>编号</th>
|
||||
<th>用户信息</th>
|
||||
<th>金额</th>
|
||||
<th>支付信息/详情</th>
|
||||
@ -161,9 +173,24 @@ $requests = $stmt->fetchAll();
|
||||
<code class="small"><?= htmlspecialchars($r['uid'] ?? '---') ?></code>
|
||||
</td>
|
||||
<td>
|
||||
<?php
|
||||
$display_amount = $r['amount'];
|
||||
$is_recalculated = false;
|
||||
if ($r['type'] === 'recharge' && $r['status'] != 3 && $r['status'] != 4 && $r['fiat_amount'] > 0 && $r['fiat_currency']) {
|
||||
require_once __DIR__ . '/../includes/exchange.php';
|
||||
$current_rate = get_rate($r['fiat_currency']);
|
||||
if ($current_rate > 0) {
|
||||
$display_amount = $r['fiat_amount'] / $current_rate;
|
||||
$is_recalculated = true;
|
||||
}
|
||||
}
|
||||
?>
|
||||
<span class="fw-bold <?= $r['type'] === 'recharge' ? 'text-success' : 'text-danger' ?>">
|
||||
<?= $r['type'] === 'recharge' ? '+' : '-' ?> <?= number_format($r['amount'], 2) ?> <?= $r['symbol'] ?>
|
||||
<?= $r['type'] === 'recharge' ? '+' : '-' ?> <?= number_format($display_amount, 2) ?> <?= $r['symbol'] ?>
|
||||
</span>
|
||||
<?php if ($is_recalculated): ?>
|
||||
<i class="bi bi-info-circle-fill text-primary" style="font-size: 10px;" title="此金额按当前实时汇率动态计算,审核通过时将以此为准"></i>
|
||||
<?php endif; ?>
|
||||
<?php if ($r['fiat_amount']): ?>
|
||||
<div class="text-muted small">
|
||||
≈ <?= number_format($r['fiat_amount'], 2) ?> <?= $r['fiat_currency'] ?>
|
||||
|
||||
@ -66,7 +66,7 @@ ob_start();
|
||||
<table class="table table-sm align-middle">
|
||||
<thead>
|
||||
<tr class="text-muted small">
|
||||
<th>UID</th>
|
||||
<th>用户ID</th>
|
||||
<th>金额</th>
|
||||
<th>时间</th>
|
||||
<th>操作</th>
|
||||
|
||||
@ -16,7 +16,7 @@ $records = $db->query("SELECT r.*, u.username, u.uid FROM staking_records r JOIN
|
||||
<table class="table table-hover">
|
||||
<thead>
|
||||
<tr class="small text-muted">
|
||||
<th>ID</th>
|
||||
<th>编号</th>
|
||||
<th><?= __('users') ?></th>
|
||||
<th><?= __('mining_pool') ?></th>
|
||||
<th><?= __('amount') ?></th>
|
||||
|
||||
@ -40,13 +40,18 @@ $transactions = $stmt->fetchAll();
|
||||
|
||||
$types = [
|
||||
'recharge' => '充值',
|
||||
'deposit' => '充值',
|
||||
'withdrawal' => '提现',
|
||||
'mining_profit' => '矿机收益',
|
||||
'binary_win' => '秒合约盈利',
|
||||
'binary_loss' => '秒合约亏损',
|
||||
'contract_profit' => '合约盈利',
|
||||
'contract_loss' => '合约亏损',
|
||||
'contract_margin' => '合约保证金',
|
||||
'contract_settle' => '合约结算',
|
||||
'spot_buy' => '币币买入',
|
||||
'spot_sell' => '币币卖出'
|
||||
'spot_sell' => '币币卖出',
|
||||
'swap' => '闪兑'
|
||||
];
|
||||
?>
|
||||
|
||||
@ -69,7 +74,7 @@ $types = [
|
||||
<table class="table table-hover align-middle">
|
||||
<thead>
|
||||
<tr class="text-muted small">
|
||||
<th>ID</th>
|
||||
<th>编号</th>
|
||||
<th>用户信息</th>
|
||||
<th>类型</th>
|
||||
<th>币种</th>
|
||||
|
||||
@ -178,7 +178,7 @@ ob_start();
|
||||
<table class="table table-hover align-middle">
|
||||
<thead>
|
||||
<tr class="text-muted small">
|
||||
<th>UID</th>
|
||||
<th>用户ID</th>
|
||||
<th>用户名 / VIP</th>
|
||||
<?php if (!$admin['is_agent']): ?><th>所属代理</th><?php endif; ?>
|
||||
<th>注册IP / 实时IP</th>
|
||||
|
||||
@ -22,7 +22,7 @@ try {
|
||||
$db = db();
|
||||
|
||||
// Find the latest pending/matching recharge for this user
|
||||
$stmt = $db->prepare("SELECT id FROM finance_requests WHERE user_id = ? AND type = 'recharge' AND status IN ('0', '1') ORDER BY created_at DESC LIMIT 1");
|
||||
$stmt = $db->prepare("SELECT id FROM finance_requests WHERE user_id = ? AND type = 'recharge' AND status IN ('pending', 'matched') ORDER BY created_at DESC LIMIT 1");
|
||||
$stmt->execute([$user_id]);
|
||||
$order_id = $stmt->fetchColumn();
|
||||
|
||||
@ -38,10 +38,10 @@ try {
|
||||
$amount = isset($_POST['amount']) ? (float)$_POST['amount'] : null;
|
||||
|
||||
if ($amount !== null) {
|
||||
$stmt = $db->prepare("UPDATE finance_requests SET status = 1, account_bank = ?, account_name = ?, account_number = ?, amount = ? WHERE id = ?");
|
||||
$stmt = $db->prepare("UPDATE finance_requests SET status = 'matched', account_bank = ?, account_name = ?, account_number = ?, amount = ? WHERE id = ?");
|
||||
$stmt->execute([$bank, $name, $account, $amount, $order_id]);
|
||||
} else {
|
||||
$stmt = $db->prepare("UPDATE finance_requests SET status = 1, account_bank = ?, account_name = ?, account_number = ? WHERE id = ?");
|
||||
$stmt = $db->prepare("UPDATE finance_requests SET status = 'matched', account_bank = ?, account_name = ?, account_number = ? WHERE id = ?");
|
||||
$stmt->execute([$bank, $name, $account, $order_id]);
|
||||
}
|
||||
echo json_encode(['success' => true]);
|
||||
@ -54,14 +54,14 @@ try {
|
||||
|
||||
if ($bank && $name && $account) {
|
||||
if ($amount !== null) {
|
||||
$stmt = $db->prepare("UPDATE finance_requests SET status = 2, account_bank = ?, account_name = ?, account_number = ?, amount = ? WHERE id = ?");
|
||||
$stmt = $db->prepare("UPDATE finance_requests SET status = 'account_sent', account_bank = ?, account_name = ?, account_number = ?, amount = ? WHERE id = ?");
|
||||
$stmt->execute([$bank, $name, $account, $amount, $order_id]);
|
||||
} else {
|
||||
$stmt = $db->prepare("UPDATE finance_requests SET status = 2, account_bank = ?, account_name = ?, account_number = ? WHERE id = ?");
|
||||
$stmt = $db->prepare("UPDATE finance_requests SET status = 'account_sent', account_bank = ?, account_name = ?, account_number = ? WHERE id = ?");
|
||||
$stmt->execute([$bank, $name, $account, $order_id]);
|
||||
}
|
||||
} else {
|
||||
$stmt = $db->prepare("UPDATE finance_requests SET status = 2 WHERE id = ?");
|
||||
$stmt = $db->prepare("UPDATE finance_requests SET status = 'account_sent' WHERE id = ?");
|
||||
$stmt->execute([$order_id]);
|
||||
}
|
||||
echo json_encode(['success' => true]);
|
||||
|
||||
@ -166,7 +166,7 @@ if ($action === 'recharge') {
|
||||
exit;
|
||||
}
|
||||
|
||||
$stmt = $db->prepare("INSERT INTO finance_requests (user_id, type, amount, symbol, payment_method, tx_hash, fiat_amount, fiat_currency, status, ip_address) VALUES (?, 'recharge', ?, ?, ?, ?, ?, ?, '0', ?)");
|
||||
$stmt = $db->prepare("INSERT INTO finance_requests (user_id, type, amount, symbol, payment_method, tx_hash, fiat_amount, fiat_currency, status, ip_address) VALUES (?, 'recharge', ?, ?, ?, ?, ?, ?, 'pending', ?)");
|
||||
$stmt->execute([$user_id, $amount, $symbol, $method, $tx_hash, $fiat_amount, $fiat_currency, getRealIP()]);
|
||||
|
||||
echo json_encode(['success' => true, 'id' => $db->lastInsertId()]);
|
||||
@ -180,7 +180,7 @@ if ($action === 'complete_transfer') {
|
||||
exit;
|
||||
}
|
||||
|
||||
$stmt = $db->prepare("UPDATE finance_requests SET status = 3 WHERE id = ? AND user_id = ?");
|
||||
$stmt = $db->prepare("UPDATE finance_requests SET status = 'finished' WHERE id = ? AND user_id = ?");
|
||||
$stmt->execute([$order_id, $user_id]);
|
||||
|
||||
echo json_encode(['success' => true]);
|
||||
|
||||
@ -30,7 +30,7 @@ try {
|
||||
|
||||
echo json_encode([
|
||||
'success' => true,
|
||||
'status' => (int)$order['status'],
|
||||
'status' => $order['status'],
|
||||
'account_bank' => $order['account_bank'],
|
||||
'account_number' => $order['account_number'],
|
||||
'account_name' => $order['account_name'],
|
||||
|
||||
BIN
assets/pasted-20260221-135325-cae0a88a.png
Normal file
BIN
assets/pasted-20260221-135325-cae0a88a.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 36 KiB |
BIN
assets/pasted-20260221-135944-2e145fa5.png
Normal file
BIN
assets/pasted-20260221-135944-2e145fa5.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.8 KiB |
BIN
assets/pasted-20260221-140828-9e5019bc.png
Normal file
BIN
assets/pasted-20260221-140828-9e5019bc.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 78 KiB |
BIN
assets/pasted-20260221-141514-517d3eaa.png
Normal file
BIN
assets/pasted-20260221-141514-517d3eaa.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 20 KiB |
BIN
assets/pasted-20260221-142814-663633de.png
Normal file
BIN
assets/pasted-20260221-142814-663633de.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 58 KiB |
@ -1 +1 @@
|
||||
{"USD":1,"AED":3.67,"AFN":62.91,"ALL":81.77,"AMD":376.96,"ANG":1.79,"AOA":921.54,"ARS":1452.25,"AUD":1.41,"AWG":1.79,"AZN":1.7,"BAM":1.66,"BBD":2,"BDT":122.24,"BGN":1.61,"BHD":0.376,"BIF":2972.8,"BMD":1,"BND":1.27,"BOB":6.94,"BRL":5.21,"BSD":1,"BTN":90.95,"BWP":13.63,"BYN":2.86,"BZD":2,"CAD":1.37,"CDF":2280.68,"CHF":0.776,"CLF":0.0219,"CLP":864.48,"CNH":6.9,"CNY":6.92,"COP":3676.38,"CRC":482.12,"CUP":24,"CVE":93.62,"CZK":20.58,"DJF":177.72,"DKK":6.34,"DOP":61.68,"DZD":130.05,"EGP":47.54,"ERN":15,"ETB":154.9,"EUR":0.849,"FJD":2.2,"FKP":0.742,"FOK":6.34,"GBP":0.742,"GEL":2.68,"GGP":0.742,"GHS":10.97,"GIP":0.742,"GMD":74.12,"GNF":8765.19,"GTQ":7.68,"GYD":209.23,"HKD":7.81,"HNL":26.5,"HRK":6.4,"HTG":131.33,"HUF":322.52,"IDR":16879.29,"ILS":3.12,"IMP":0.742,"INR":90.96,"IQD":1310.75,"IRR":1284718.39,"ISK":123.11,"JEP":0.742,"JMD":156.06,"JOD":0.709,"JPY":155.09,"KES":128.97,"KGS":87.44,"KHR":4018.25,"KID":1.41,"KMF":417.69,"KRW":1447.74,"KWD":0.307,"KYD":0.833,"KZT":492.41,"LAK":21645.16,"LBP":89500,"LKR":309.31,"LRD":185.93,"LSL":16.07,"LYD":6.31,"MAD":9.17,"MDL":17.09,"MGA":4323.12,"MKD":52.41,"MMK":2105.62,"MNT":3537.8,"MOP":8.05,"MRU":40.01,"MUR":46.31,"MVR":15.46,"MWK":1745.39,"MXN":17.17,"MYR":3.9,"MZN":63.57,"NAD":16.07,"NGN":1346.36,"NIO":36.87,"NOK":9.54,"NPR":145.52,"NZD":1.67,"OMR":0.384,"PAB":1,"PEN":3.36,"PGK":4.33,"PHP":58.08,"PKR":279.85,"PLN":3.58,"PYG":6535.86,"QAR":3.64,"RON":4.33,"RSD":99.71,"RUB":76.83,"RWF":1462.18,"SAR":3.75,"SBD":7.96,"SCR":13.84,"SDG":510.48,"SEK":9.06,"SGD":1.27,"SHP":0.742,"SLE":24.46,"SLL":24455.37,"SOS":570.82,"SRD":37.72,"SSP":4583.75,"STN":20.8,"SYP":114.12,"SZL":16.07,"THB":31.18,"TJS":9.39,"TMT":3.5,"TND":2.87,"TOP":2.36,"TRY":43.85,"TTD":6.74,"TVD":1.41,"TWD":31.54,"TZS":2579.03,"UAH":43.3,"UGX":3568.92,"UYU":38.81,"UZS":12205.78,"VES":405.35,"VND":25927.65,"VUV":118.68,"WST":2.69,"XAF":556.92,"XCD":2.7,"XCG":1.79,"XDR":0.727,"XOF":556.92,"XPF":101.32,"YER":238.65,"ZAR":16.07,"ZMW":18.82,"ZWG":25.54,"ZWL":25.54}
|
||||
{"USD":1,"AED":3.67,"AFN":62.91,"ALL":81.77,"AMD":376.96,"ANG":1.79,"AOA":921.54,"ARS":1452.25,"AUD":1.41,"AWG":1.79,"AZN":1.7,"BAM":1.66,"BBD":2,"BDT":122.24,"BGN":1.61,"BHD":0.376,"BIF":2972.8,"BMD":1,"BND":1.27,"BOB":6.94,"BRL":5.21,"BSD":1,"BTN":90.95,"BWP":13.63,"BYN":2.86,"BZD":2,"CAD":1.37,"CDF":2280.68,"CHF":0.776,"CLF":0.0219,"CLP":864.48,"CNH":6.9,"CNY":7.25,"COP":3676.38,"CRC":482.12,"CUP":24,"CVE":93.62,"CZK":20.58,"DJF":177.72,"DKK":6.34,"DOP":61.68,"DZD":130.05,"EGP":47.54,"ERN":15,"ETB":154.9,"EUR":0.95,"FJD":2.2,"FKP":0.742,"FOK":6.34,"GBP":0.742,"GEL":2.68,"GGP":0.742,"GHS":10.97,"GIP":0.742,"GMD":74.12,"GNF":8765.19,"GTQ":7.68,"GYD":209.23,"HKD":7.81,"HNL":26.5,"HRK":6.4,"HTG":131.33,"HUF":322.52,"IDR":16879.29,"ILS":3.12,"IMP":0.742,"INR":90.96,"IQD":1310.75,"IRR":1284718.39,"ISK":123.11,"JEP":0.742,"JMD":156.06,"JOD":0.709,"JPY":155.09,"KES":128.97,"KGS":87.44,"KHR":4018.25,"KID":1.41,"KMF":417.69,"KRW":1447.74,"KWD":0.307,"KYD":0.833,"KZT":492.41,"LAK":21645.16,"LBP":89500,"LKR":309.31,"LRD":185.93,"LSL":16.07,"LYD":6.31,"MAD":9.17,"MDL":17.09,"MGA":4323.12,"MKD":52.41,"MMK":2105.62,"MNT":3537.8,"MOP":8.05,"MRU":40.01,"MUR":46.31,"MVR":15.46,"MWK":1745.39,"MXN":17.17,"MYR":4.45,"MZN":63.57,"NAD":16.07,"NGN":1346.36,"NIO":36.87,"NOK":9.54,"NPR":145.52,"NZD":1.67,"OMR":0.384,"PAB":1,"PEN":3.36,"PGK":4.33,"PHP":58.08,"PKR":279.85,"PLN":3.58,"PYG":6535.86,"QAR":3.64,"RON":4.33,"RSD":99.71,"RUB":76.83,"RWF":1462.18,"SAR":3.75,"SBD":7.96,"SCR":13.84,"SDG":510.48,"SEK":9.06,"SGD":1.27,"SHP":0.742,"SLE":24.46,"SLL":24455.37,"SOS":570.82,"SRD":37.72,"SSP":4583.75,"STN":20.8,"SYP":114.12,"SZL":16.07,"THB":31.18,"TJS":9.39,"TMT":3.5,"TND":2.87,"TOP":2.36,"TRY":43.85,"TTD":6.74,"TVD":1.41,"TWD":31.54,"TZS":2579.03,"UAH":43.3,"UGX":3568.92,"UYU":38.81,"UZS":12205.78,"VES":405.35,"VND":25927.65,"VUV":118.68,"WST":2.69,"XAF":556.92,"XCD":2.7,"XCG":1.79,"XDR":0.727,"XOF":556.92,"XPF":101.32,"YER":238.65,"ZAR":16.07,"ZMW":18.82,"ZWG":25.54,"ZWL":25.54}
|
||||
@ -5,13 +5,19 @@
|
||||
*/
|
||||
|
||||
function get_exchange_rates() {
|
||||
if (!function_exists('db')) {
|
||||
require_once __DIR__ . '/../db/config.php';
|
||||
}
|
||||
$cache_file = __DIR__ . '/../db/exchange_rates.json';
|
||||
$cache_time = 3600; // Cache for 1 hour
|
||||
$cache_time = 300; // Cache for 5 minutes for better precision
|
||||
|
||||
// Try to load from cache first
|
||||
if (file_exists($cache_file) && (time() - filemtime($cache_file) < $cache_time)) {
|
||||
return json_decode(file_get_contents($cache_file), true);
|
||||
}
|
||||
|
||||
$rates = null;
|
||||
|
||||
// Use a free public API
|
||||
$api_url = 'https://api.exchangerate-api.com/v4/latest/USD';
|
||||
$ch = curl_init();
|
||||
@ -24,24 +30,64 @@ function get_exchange_rates() {
|
||||
if ($response) {
|
||||
$data = json_decode($response, true);
|
||||
if ($data && isset($data['rates'])) {
|
||||
// We want rates relative to USD (which is 1:1 with USDT for this purpose)
|
||||
$rates = $data['rates'];
|
||||
file_put_contents($cache_file, json_encode($rates));
|
||||
return $rates;
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback rates if API fails
|
||||
return [
|
||||
'USD' => 1,
|
||||
'EUR' => 0.92,
|
||||
'GBP' => 0.79,
|
||||
// Fallback rates if API fails or returns incomplete data
|
||||
// These are base values, but the API will overwrite them if successful
|
||||
$fallbacks = [
|
||||
'USD' => 1.0,
|
||||
'EUR' => 0.95,
|
||||
'GBP' => 0.78,
|
||||
'CNY' => 7.23,
|
||||
'JPY' => 150.1,
|
||||
'JPY' => 150.0,
|
||||
'HKD' => 7.82,
|
||||
'TWD' => 31.6,
|
||||
'KRW' => 1332.0
|
||||
'TWD' => 31.5,
|
||||
'KRW' => 1380.0,
|
||||
'MYR' => 4.45,
|
||||
'THB' => 35.5,
|
||||
'VND' => 25400.0,
|
||||
'SGD' => 1.34,
|
||||
'PHP' => 57.5,
|
||||
'IDR' => 16200.0,
|
||||
'AUD' => 1.52,
|
||||
'CAD' => 1.37,
|
||||
'CHF' => 0.88,
|
||||
'BRL' => 5.15,
|
||||
'RUB' => 92.0,
|
||||
'INR' => 83.5,
|
||||
'TRY' => 32.5,
|
||||
'AED' => 3.67,
|
||||
];
|
||||
|
||||
if (!$rates) {
|
||||
$rates = $fallbacks;
|
||||
} else {
|
||||
// Merge with fallbacks to ensure all required currencies exist
|
||||
foreach ($fallbacks as $code => $rate) {
|
||||
if (!isset($rates[$code])) {
|
||||
$rates[$code] = $rate;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Apply manual overrides from database (e.g., rate_MYR = 4.5)
|
||||
try {
|
||||
$stmt = db()->query("SELECT setting_key, setting_value FROM system_settings WHERE setting_key LIKE 'rate_%'");
|
||||
$overrides = $stmt->fetchAll(PDO::FETCH_KEY_PAIR);
|
||||
foreach ($overrides as $key => $val) {
|
||||
$currency = strtoupper(str_replace('rate_', '', $key));
|
||||
if ($val > 0) {
|
||||
$rates[$currency] = (float)$val;
|
||||
}
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
// Ignore DB errors during rate fetching
|
||||
}
|
||||
|
||||
file_put_contents($cache_file, json_encode($rates));
|
||||
return $rates;
|
||||
}
|
||||
|
||||
function get_rate($currency) {
|
||||
|
||||
44
recharge.php
44
recharge.php
@ -554,7 +554,7 @@ function openRechargeModal(initialMessage, isRestore = false, orderId = null) {
|
||||
if (!isRestore) {
|
||||
remainingSeconds = 1800;
|
||||
saveRechargeState({ phase: 'pending', initialMessage, orderId: currentOrderId });
|
||||
sendModalMessage(initialMessage); // Automatically notify admin via chat
|
||||
sendModalMessage(initialMessage); // Automatically notify admin about the new recharge request
|
||||
}
|
||||
|
||||
if (currentOrderId) startStatusPolling(currentOrderId);
|
||||
@ -573,7 +573,7 @@ function openRechargeModal(initialMessage, isRestore = false, orderId = null) {
|
||||
if (--remainingSeconds < 0) clearInterval(rechargeCountdownInterval);
|
||||
}, 1000);
|
||||
|
||||
if (!isRestore) renderRechargeUI({ status: 0 });
|
||||
if (!isRestore) renderRechargeUI({ status: 'pending' });
|
||||
initModalChat();
|
||||
}
|
||||
|
||||
@ -588,7 +588,7 @@ function startStatusPolling(orderId) {
|
||||
if (data.success) {
|
||||
console.log('Order status update:', data.status, data);
|
||||
renderRechargeUI(data);
|
||||
if (parseInt(data.status) === 3) clearInterval(window.statusPollingInterval);
|
||||
if (data.status === 'finished') clearInterval(window.statusPollingInterval);
|
||||
}
|
||||
} catch (e) { console.error('Status polling error:', e); }
|
||||
};
|
||||
@ -599,18 +599,18 @@ function startStatusPolling(orderId) {
|
||||
function renderRechargeUI(data) {
|
||||
const side = document.querySelector('.info-side');
|
||||
if (!side) return;
|
||||
const status = parseInt(data.status);
|
||||
if (status === 3) { finishTransferUI(); return; }
|
||||
const status = data.status;
|
||||
if (status === 'finished') { finishTransferUI(); return; }
|
||||
|
||||
if (status === 0) {
|
||||
if (status === 'pending') {
|
||||
side.innerHTML = `
|
||||
<div class="text-center text-lg-start position-relative" style="z-index: 2;">
|
||||
<div class="mb-4 text-center">
|
||||
<div class="d-inline-flex align-items-center gap-2 px-3 py-2 rounded-pill bg-primary bg-opacity-10 text-primary small fw-bold mb-3 border border-primary border-opacity-10" style="color: #ff4d94 !important; border-color: #ff4d94 !important;">
|
||||
<span class="pulse-dot-pink"></span> <span style="letter-spacing: 1px;"><?= __('waiting_allocation') ?></span>
|
||||
<span class="pulse-dot-pink"></span> <span style="letter-spacing: 1px;">正在为您匹配充值账户</span>
|
||||
</div>
|
||||
<h2 class="fw-bold text-dark mb-3" style="font-size: 2rem;"><?= __('matching_account') ?></h2>
|
||||
<p class="text-muted fw-medium mb-0" style="font-size: 15px;"><?= __('matching_desc') ?></p>
|
||||
<h2 class="fw-bold text-dark mb-3" style="font-size: 2rem;">正在为您匹配充值账户</h2>
|
||||
<p class="text-muted fw-medium mb-0" style="font-size: 15px;">系统正在为您分配专属收款账户,请耐心等待。<br>匹配成功后,页面将自动更新收款信息。<br>请勿关闭当前页面。</p>
|
||||
</div>
|
||||
<div class="mb-4 py-4 px-4 rounded-4 border border-light shadow-sm" style="background: #fff0f5;">
|
||||
<div class="row align-items-center text-center">
|
||||
@ -627,18 +627,18 @@ function renderRechargeUI(data) {
|
||||
<div class="mb-2 d-flex gap-2"><i class="bi bi-check2-circle text-primary" style="color: #ff4d94 !important;"></i> <span><?= __('recharge_instruction_2') ?></span></div>
|
||||
<div class="d-flex gap-2"><i class="bi bi-check2-circle text-primary" style="color: #ff4d94 !important;"></i> <span><?= __('recharge_instruction_3') ?></span></div>
|
||||
</div>
|
||||
<div class="mt-4"><button type="button" class="btn btn-primary w-100 rounded-pill py-2 fw-bold opacity-50" disabled style="background: #ff4d94 !important; border: none;"><?= __('waiting_system_allocation') ?>...</button></div>
|
||||
<div class="mt-4"><button type="button" class="btn btn-primary w-100 rounded-pill py-2 fw-bold opacity-50" disabled style="background: #ff4d94 !important; border: none;">正在获取账户详情...</button></div>
|
||||
</div>
|
||||
</div>`;
|
||||
} else if (status === 1) {
|
||||
} else if (status === 'matched') {
|
||||
side.innerHTML = `
|
||||
<div class="text-center text-lg-start position-relative" style="z-index: 2;">
|
||||
<div class="mb-4 text-center">
|
||||
<div class="d-inline-flex align-items-center gap-2 px-3 py-2 rounded-pill bg-success bg-opacity-10 text-success small fw-bold mb-3 border border-success border-opacity-10">
|
||||
<i class="bi bi-check-circle-fill text-success"></i> <?= __("matched_successfully") ?>
|
||||
<i class="bi bi-check-circle-fill text-success"></i> 匹配成功
|
||||
</div>
|
||||
<h2 class="fw-bold text-dark mb-3" style="font-size: 2rem;"><?= __("matched_successfully") ?></h2>
|
||||
<p class="text-muted fw-medium mb-0" style="font-size: 15px;"><?= __("matched_desc_short") ?></p>
|
||||
<h2 class="fw-bold text-dark mb-3" style="font-size: 2rem;">匹配成功</h2>
|
||||
<p class="text-muted fw-medium mb-0" style="font-size: 15px;">您的充值订单已匹配成功。<br>客服正在为您发送收款账户信息,请稍候。<br>页面将自动显示收款账户,请勿刷新或关闭页面。</p>
|
||||
</div>
|
||||
<div class="mb-4 py-4 px-4 rounded-4 border border-light shadow-sm" style="background: #fff0f5;">
|
||||
<div class="row align-items-center text-center">
|
||||
@ -650,18 +650,18 @@ function renderRechargeUI(data) {
|
||||
</div>
|
||||
<div class="p-4 rounded-4 bg-light border border-light">
|
||||
<h6 class="text-dark fw-bold mb-3 d-flex align-items-center gap-2"><i class="bi bi-shield-lock-fill text-primary" style="color: #ff4d94 !important;"></i> <?= __('security_tips') ?></h6>
|
||||
<div class="mt-4"><button type="button" class="btn btn-primary w-100 rounded-pill py-2 fw-bold opacity-50" disabled style="background: #ff4d94 !important; border: none;"><?= __("getting_account_details") ?>...</button></div>
|
||||
<div class="mt-4"><button type="button" class="btn btn-primary w-100 rounded-pill py-2 fw-bold opacity-50" disabled style="background: #ff4d94 !important; border: none;">正在获取账户详情...</button></div>
|
||||
</div>
|
||||
</div>`;
|
||||
} else if (status === 2) {
|
||||
} else if (status === 'account_sent') {
|
||||
const bank = data.account_bank || '---';
|
||||
const account = data.account_number || '---';
|
||||
const name = data.account_name || '---';
|
||||
side.innerHTML = `
|
||||
<div class="text-center text-lg-start">
|
||||
<div class="mb-4 text-center">
|
||||
<div class="d-inline-flex align-items-center gap-2 px-3 py-1 rounded-pill bg-success bg-opacity-10 text-success small fw-bold mb-3 border border-success border-opacity-10"><i class="bi bi-check-circle-fill text-success"></i> <?= __("matched_successfully") ?></div>
|
||||
<h2 class="fw-bold text-dark mb-2" style="font-size: 1.8rem;"><?= __("recharge_final_title") ?></h2>
|
||||
<div class="d-inline-flex align-items-center gap-2 px-3 py-1 rounded-pill bg-success bg-opacity-10 text-success small fw-bold mb-3 border border-success border-opacity-10"><i class="bi bi-check-circle-fill text-success"></i> 匹配成功</div>
|
||||
<h2 class="fw-bold text-dark mb-2" style="font-size: 1.8rem;">请按照以下账户信息进行转账</h2>
|
||||
</div>
|
||||
<div class="mb-3 p-4 rounded-4 shadow-sm border border-light" style="background: #fff0f5;">
|
||||
<div class="d-flex flex-column gap-3">
|
||||
@ -700,8 +700,8 @@ function renderRechargeUI(data) {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="p-2 text-center mb-3"><p class="text-muted small fw-bold mb-0"><?= __("recharge_final_notice") ?></p></div>
|
||||
<button type="button" class="btn btn-primary w-100 rounded-pill py-3 fw-bold shadow-sm" onclick="finishTransfer()" style="background: #ff4d94 !important; border: none; color: white;"><?= __("complete_transfer") ?></button>
|
||||
<div class="p-2 text-center mb-3"><p class="text-muted small fw-bold mb-0">请严格按照页面展示的收款账户信息进行转账。<br>请勿分笔转账或修改信息,转账完成后,请点击“完成转账”按钮。<br>转账完成后请提交转账凭证给在线客服,方便第一时间为你确认到账。</p></div>
|
||||
<button type="button" class="btn btn-primary w-100 rounded-pill py-3 fw-bold shadow-sm" onclick="finishTransfer()" style="background: #ff4d94 !important; border: none; color: white;">【完成转账】</button>
|
||||
</div>`;
|
||||
}
|
||||
|
||||
@ -724,7 +724,9 @@ document.addEventListener('DOMContentLoaded', async () => {
|
||||
try {
|
||||
const r = await fetch(`/api/recharge_status.php?id=${state.orderId}&_t=${Date.now()}`);
|
||||
const data = await r.json();
|
||||
if (data.success) renderRechargeUI(data);
|
||||
if (data.success) {
|
||||
renderRechargeUI(data);
|
||||
}
|
||||
} catch (e) {}
|
||||
} else { localStorage.removeItem('recharge_state'); }
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user