38320-vm/ajax_handler.php
Flatlogic Bot f09a03c89c 最新
2026-02-10 11:39:11 +00:00

344 lines
13 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
session_start();
require_once __DIR__ . '/db/config.php';
require_once __DIR__ . '/api/LocalLubanApi.php';
// Price multiplier to earn profit (User requested 1.5 - 2x)
const PRICE_MULTIPLIER = 1.8;
$pdo = db();
$api = new LubanSMS();
$action = $_GET['action'] ?? '';
header('Content-Type: application/json');
if (!isset($_SESSION['user_id']) && $action !== 'login') {
echo json_encode(['code' => 401, 'msg' => 'Unauthorized']);
exit;
}
function check_trc20_payment($address, $target_amount, $order_time) {
if (!$address || $address == 'TEm1B...TRC20_ADDRESS_HERE') return false;
// TronScan API to check transactions
$url = "https://apilist.tronscan.org/api/token_trc20/transfers?limit=20&start=0&direction=1&address=" . urlencode($address);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0');
$response = curl_exec($ch);
curl_close($ch);
if (!$response) return false;
$data = json_decode($response, true);
if (!isset($data['token_transfers'])) return false;
foreach ($data['token_transfers'] as $tx) {
if ($tx['symbol'] !== 'USDT') continue;
$amount = (float)$tx['quant'] / pow(10, $tx['tokenInfo']['tokenDecimal']);
$tx_time = (int)($tx['block_ts'] / 1000);
$order_ts = strtotime($order_time);
// Match amount (with small tolerance for floating point) and time (must be after order)
if (abs($amount - $target_amount) < 0.001 && $tx_time > $order_ts) {
return $tx['transaction_id'];
}
}
return false;
}
switch ($action) {
case 'get_balance':
$stmt = $pdo->prepare("SELECT balance FROM users WHERE id = ?");
$stmt->execute([$_SESSION['user_id']]);
$balance = $stmt->fetchColumn();
echo json_encode(['code' => 0, 'balance' => number_format($balance, 2)]);
break;
case 'get_countries':
$res = $api->getCountries();
if ($res && (int)$res['code'] === 0) {
$data = $res['msg'] ?? $res['data'] ?? [];
echo json_encode(['code' => 0, 'data' => $data]);
} else {
echo json_encode($res ?: ['code' => 500, 'msg' => 'Unknown API error']);
}
break;
case 'get_services':
$country = $_GET['country'] ?? '';
$service = $_GET['service'] ?? '';
$res = $api->getServices($country, $service);
if ($res && (int)$res['code'] === 0) {
$data = $res['msg'] ?? $res['data'] ?? [];
foreach ($data as &$item) {
if (isset($item['cost'])) {
$item['cost'] = round((float)$item['cost'] * PRICE_MULTIPLIER, 2);
}
}
echo json_encode(['code' => 0, 'data' => $data]);
} else {
echo json_encode($res ?: ['code' => 500, 'msg' => 'Unknown API error']);
}
break;
case 'get_number':
$service_id = $_GET['service_id'] ?? '';
$country_name = $_GET['country_name'] ?? '未知国家';
$service_name = $_GET['service_name'] ?? '未知项目';
$price = (float)($_GET['price'] ?? 0);
if (!$service_id) {
echo json_encode(['code' => 400, 'msg' => 'Service ID is required']);
break;
}
$stmt = $pdo->prepare("SELECT balance FROM users WHERE id = ?");
$stmt->execute([$_SESSION['user_id']]);
$balance = $stmt->fetchColumn();
if ($balance < $price) {
echo json_encode(['code' => 400, 'msg' => '余额不足,请先充值']);
break;
}
$res = $api->getNumber($service_id);
if ($res && (int)$res['code'] === 0) {
$pdo->beginTransaction();
try {
$stmt = $pdo->prepare("UPDATE users SET balance = balance - ? WHERE id = ?");
$stmt->execute([$price, $_SESSION['user_id']]);
$stmt = $pdo->prepare("INSERT INTO sms_orders (user_id, request_id, number, service_name, country_name, cost, status, expire_at) VALUES (?, ?, ?, ?, ?, ?, 'pending', DATE_ADD(NOW(), INTERVAL 10 MINUTE))");
$stmt->execute([$_SESSION['user_id'], $res['request_id'], $res['number'], $service_name, $country_name, $price]);
$pdo->commit();
echo json_encode($res);
} catch (Exception $e) {
$pdo->rollBack();
echo json_encode(['code' => 500, 'msg' => 'Database error: ' . $e->getMessage()]);
}
} else {
echo json_encode($res ?: ['code' => 500, 'msg' => 'API Error']);
}
break;
case 'check_sms':
$request_id = $_GET['request_id'] ?? '';
if (!$request_id) {
echo json_encode(['code' => 400, 'msg' => 'Request ID is required']);
break;
}
$res = $api->getSms($request_id);
if ($res && (int)$res['code'] === 0 && ($res['msg'] ?? '') == 'success') {
$stmt = $pdo->prepare("UPDATE sms_orders SET sms_content = ?, status = 'received' WHERE request_id = ?");
$stmt->execute([$res['sms_code'], $request_id]);
}
echo json_encode($res ?: ['code' => 500, 'msg' => 'API Error']);
break;
case 'release_number':
$request_id = $_GET['request_id'] ?? '';
$stmt = $pdo->prepare("SELECT created_at, status FROM sms_orders WHERE request_id = ? AND user_id = ?");
$stmt->execute([$request_id, $_SESSION['user_id']]);
$order = $stmt->fetch();
if (!$order) {
echo json_encode(['code' => 404, 'msg' => 'Order not found']);
break;
}
if ($order['status'] !== 'pending') {
echo json_encode(['code' => 400, 'msg' => 'Invalid order status']);
break;
}
$createdAt = strtotime($order['created_at']);
if (time() - $createdAt < 120) {
echo json_encode(['code' => 400, 'msg' => '获取号码不足2分钟暂时无法手动释放。']);
break;
}
$res = $api->setStatus($request_id, 'reject');
if ($res && (int)$res['code'] === 0) {
$stmt = $pdo->prepare("UPDATE sms_orders SET status = 'canceled' WHERE request_id = ?");
$stmt->execute([$request_id]);
}
echo json_encode($res ?: ['code' => 500, 'msg' => 'API Error']);
break;
case 'get_active_orders':
$stmt = $pdo->prepare("UPDATE sms_orders SET status = 'expired' WHERE status = 'pending' AND expire_at < NOW()");
$stmt->execute();
$stmt = $pdo->prepare("SELECT * FROM sms_orders WHERE user_id = ? AND status = 'pending' ORDER BY created_at DESC");
$stmt->execute([$_SESSION['user_id']]);
echo json_encode(['code' => 0, 'data' => $stmt->fetchAll()]);
break;
case 'create_recharge':
$amount = (float)($_POST['amount'] ?? 0);
if ($amount < 10) {
echo json_encode(['code' => 400, 'msg' => '最低充值金额为 10 USDT']);
break;
}
$base = floor($amount);
$random_decimal = rand(1, 99) / 100;
$final_amount = $base + $random_decimal;
$stmt = $pdo->prepare("INSERT INTO recharges (user_id, amount, txid, status) VALUES (?, ?, 'Auto-Detect', 'pending')");
$stmt->execute([$_SESSION['user_id'], $final_amount]);
echo json_encode(['code' => 0, 'recharge_id' => $pdo->lastInsertId(), 'amount' => $final_amount]);
break;
case 'check_recharge_status':
$recharge_id = $_GET['recharge_id'] ?? '';
if (!$recharge_id) {
echo json_encode(['code' => 400, 'msg' => 'Recharge ID is required']);
break;
}
$stmt = $pdo->prepare("SELECT * FROM recharges WHERE id = ? AND user_id = ?");
$stmt->execute([$recharge_id, $_SESSION['user_id']]);
$recharge = $stmt->fetch();
if (!$recharge) {
echo json_encode(['code' => 404, 'msg' => 'Order not found']);
break;
}
if ($recharge['status'] === 'completed') {
echo json_encode(['code' => 0, 'status' => 'completed']);
exit;
}
// Try Auto-Detection
$settings = $pdo->query("SELECT setting_key, setting_value FROM settings")->fetchAll(PDO::FETCH_KEY_PAIR);
$trc20_address = $settings['usdt_trc20_address'] ?? '';
$txid = check_trc20_payment($trc20_address, $recharge['amount'], $recharge['created_at']);
if ($txid) {
$pdo->beginTransaction();
try {
$stmt = $pdo->prepare("UPDATE recharges SET status = 'completed', txid = ? WHERE id = ?");
$stmt->execute([$txid, $recharge_id]);
$stmt = $pdo->prepare("UPDATE users SET balance = balance + ? WHERE id = ?");
$stmt->execute([$recharge['amount'], $recharge['user_id']]);
$pdo->commit();
echo json_encode(['code' => 0, 'status' => 'completed']);
} catch (Exception $e) {
$pdo->rollBack();
echo json_encode(['code' => 500, 'msg' => 'Detection error']);
}
} else {
echo json_encode(['code' => 0, 'status' => 'pending']);
}
break;
// --- Chat Actions ---
case 'send_message':
$message = trim($_POST['message'] ?? '');
$target_user_id = $_POST['user_id'] ?? $_SESSION['user_id'];
if (!$message) {
echo json_encode(['code' => 400, 'msg' => 'Message is empty']);
break;
}
$sender = 'user';
// Check if current user is admin
$stmt = $pdo->prepare("SELECT role FROM users WHERE id = ?");
$stmt->execute([$_SESSION['user_id']]);
$currentUser = $stmt->fetch();
if ($currentUser['role'] === 'admin') {
$sender = 'admin';
}
$stmt = $pdo->prepare("INSERT INTO support_messages (user_id, sender, message, is_read) VALUES (?, ?, ?, 0)");
$stmt->execute([$target_user_id, $sender, $message]);
echo json_encode(['code' => 0, 'msg' => 'Sent']);
break;
case 'get_messages':
$target_user_id = $_GET['user_id'] ?? $_SESSION['user_id'];
// Security: non-admins can only see their own messages
$stmt = $pdo->prepare("SELECT role FROM users WHERE id = ?");
$stmt->execute([$_SESSION['user_id']]);
$currentUser = $stmt->fetch();
$isAdmin = ($currentUser['role'] === 'admin');
if (!$isAdmin && $target_user_id != $_SESSION['user_id']) {
echo json_encode(['code' => 403, 'msg' => 'Forbidden']);
break;
}
// Mark as read logic
if ($isAdmin && $target_user_id != $_SESSION['user_id']) {
// Admin is reading user messages
$stmt = $pdo->prepare("UPDATE support_messages SET is_read = 1 WHERE user_id = ? AND sender = 'user'");
$stmt->execute([$target_user_id]);
} else if (!$isAdmin && $target_user_id == $_SESSION['user_id']) {
// User is reading admin messages
$stmt = $pdo->prepare("UPDATE support_messages SET is_read = 1 WHERE user_id = ? AND sender = 'admin'");
$stmt->execute([$target_user_id]);
}
$stmt = $pdo->prepare("SELECT * FROM support_messages WHERE user_id = ? ORDER BY created_at ASC");
$stmt->execute([$target_user_id]);
echo json_encode(['code' => 0, 'data' => $stmt->fetchAll()]);
break;
case 'get_chat_users':
// Admin only
$stmt = $pdo->prepare("SELECT role FROM users WHERE id = ?");
$stmt->execute([$_SESSION['user_id']]);
$currentUser = $stmt->fetch();
if ($currentUser['role'] !== 'admin') {
echo json_encode(['code' => 403, 'msg' => 'Forbidden']);
break;
}
$stmt = $pdo->query("
SELECT u.id, u.username, m.message as last_message, m.created_at as last_time,
(SELECT COUNT(*) FROM support_messages WHERE user_id = u.id AND sender = 'user' AND is_read = 0) as unread_count
FROM users u
JOIN (
SELECT user_id, MAX(created_at) as max_time
FROM support_messages
GROUP BY user_id
) last_msg ON u.id = last_msg.user_id
JOIN support_messages m ON m.user_id = u.id AND m.created_at = last_msg.max_time
ORDER BY m.created_at DESC
");
echo json_encode(['code' => 0, 'data' => $stmt->fetchAll()]);
break;
case 'check_new_messages':
// Admin only
$stmt = $pdo->prepare("SELECT role FROM users WHERE id = ?");
$stmt->execute([$_SESSION['user_id']]);
$currentUser = $stmt->fetch();
if ($currentUser['role'] !== 'admin') {
echo json_encode(['code' => 403, 'msg' => 'Forbidden']);
break;
}
$stmt = $pdo->query("SELECT COUNT(*) FROM support_messages WHERE sender = 'user' AND is_read = 0");
$count = $stmt->fetchColumn();
echo json_encode(['code' => 0, 'unread_total' => $count]);
break;
default:
echo json_encode(['code' => 404, 'msg' => 'Action not found']);
break;
}