38320-vm/ajax_handler.php
Flatlogic Bot 48b78f8a22 加码
2026-02-10 12:06:31 +00:00

356 lines
15 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();
// Ensure apikey is loaded
$stmt = $pdo->prepare("SELECT setting_value FROM settings WHERE setting_key = 'lubansms_apikey'");
$stmt->execute();
$db_apikey = $stmt->fetchColumn();
$api = new LubanSMS($db_apikey);
$action = $_GET['action'] ?? '';
header('Content-Type: application/json; charset=utf-8');
// Basic Auth check
if (!isset($_SESSION['user_id']) && $action !== 'login') {
echo json_encode(['code' => 401, 'msg' => '未登录或登录已过期']);
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, 15);
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36');
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
$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);
if (abs($amount - $target_amount) < 0.01 && $tx_time > $order_ts) {
return $tx['transaction_id'];
}
}
return false;
}
try {
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((float)$balance, 2)]);
break;
case 'get_countries':
if (!$db_apikey) {
echo json_encode(['code' => 500, 'msg' => 'API Key not configured in DB'], JSON_UNESCAPED_UNICODE);
break;
}
$res = $api->getCountries();
if ($res && (int)($res['code'] ?? -1) === 0) {
$data = $res['msg'] ?? $res['data'] ?? [];
echo json_encode(['code' => 0, 'data' => $data], JSON_UNESCAPED_UNICODE);
} else {
echo json_encode($res ?: ['code' => 500, 'msg' => 'API接口响应异常'], JSON_UNESCAPED_UNICODE);
}
break;
case 'get_services':
if (!$db_apikey) {
echo json_encode(['code' => 500, 'msg' => 'API Key not configured in DB'], JSON_UNESCAPED_UNICODE);
break;
}
$country = $_GET['country'] ?? '';
$service = $_GET['service'] ?? '';
$res = $api->getServices($country, $service);
if ($res && (int)($res['code'] ?? -1) === 0) {
$data = $res['msg'] ?? $res['data'] ?? [];
if (!is_array($data)) $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], JSON_UNESCAPED_UNICODE);
} else {
echo json_encode($res ?: ['code' => 500, 'msg' => '获取项目列表失败'], JSON_UNESCAPED_UNICODE);
}
break;
case 'get_number':
if (!$db_apikey) {
echo json_encode(['code' => 500, 'msg' => 'API Key not configured in DB'], JSON_UNESCAPED_UNICODE);
break;
}
$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 = (float)$stmt->fetchColumn();
if ($balance < $price) {
echo json_encode(['code' => 400, 'msg' => '余额不足,请先充值']);
break;
}
$res = $api->getNumber($service_id);
if ($res && (int)($res['code'] ?? -1) === 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, JSON_UNESCAPED_UNICODE);
} catch (Exception $e) {
$pdo->rollBack();
echo json_encode(['code' => 500, 'msg' => '数据库事务错误'], JSON_UNESCAPED_UNICODE);
}
} else {
echo json_encode($res ?: ['code' => 500, 'msg' => 'API获取号码失败'], JSON_UNESCAPED_UNICODE);
}
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'] ?? -1) === 0 && (string)($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'], JSON_UNESCAPED_UNICODE);
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' => '未找到该订单']);
break;
}
if ($order['status'] !== 'pending') {
echo json_encode(['code' => 400, 'msg' => '订单状态不符合释放条件']);
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'] ?? -1) === 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释放失败'], JSON_UNESCAPED_UNICODE);
break;
case 'get_active_orders':
// Auto expire old 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()], JSON_UNESCAPED_UNICODE);
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], JSON_UNESCAPED_UNICODE);
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' => '未找到充值订单']);
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' => '自动入账失败'], JSON_UNESCAPED_UNICODE);
}
} else {
echo json_encode(['code' => 0, 'status' => 'pending']);
}
break;
case 'send_message':
$message = trim($_POST['message'] ?? '');
$target_user_id = $_POST['user_id'] ?? $_SESSION['user_id'];
if (!$message) {
echo json_encode(['code' => 400, 'msg' => '消息内容不能为空']);
break;
}
// Check sender role
$stmt = $pdo->prepare("SELECT role FROM users WHERE id = ?");
$stmt->execute([$_SESSION['user_id']]);
$role = $stmt->fetchColumn();
$sender = ($role === 'admin') ? 'admin' : 'user';
$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' => '已发送'], JSON_UNESCAPED_UNICODE);
break;
case 'get_messages':
$target_user_id = $_GET['user_id'] ?? $_SESSION['user_id'];
$stmt = $pdo->prepare("SELECT role FROM users WHERE id = ?");
$stmt->execute([$_SESSION['user_id']]);
$currentUserRole = $stmt->fetchColumn();
$isAdmin = ($currentUserRole === 'admin');
if (!$isAdmin && (int)$target_user_id !== (int)$_SESSION['user_id']) {
echo json_encode(['code' => 403, 'msg' => '无权查看他人消息']);
break;
}
// Mark as read
if ($isAdmin && (int)$target_user_id !== (int)$_SESSION['user_id']) {
$stmt = $pdo->prepare("UPDATE support_messages SET is_read = 1 WHERE user_id = ? AND sender = 'user'");
$stmt->execute([$target_user_id]);
} else if (!$isAdmin) {
$stmt = $pdo->prepare("UPDATE support_messages SET is_read = 1 WHERE user_id = ? AND sender = 'admin'");
$stmt->execute([$_SESSION['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()], JSON_UNESCAPED_UNICODE);
break;
case 'get_chat_users':
$stmt = $pdo->prepare("SELECT role FROM users WHERE id = ?");
$stmt->execute([$_SESSION['user_id']]);
if ($stmt->fetchColumn() !== '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()], JSON_UNESCAPED_UNICODE);
break;
case 'check_new_messages':
$stmt = $pdo->prepare("SELECT role FROM users WHERE id = ?");
$stmt->execute([$_SESSION['user_id']]);
if ($stmt->fetchColumn() !== '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' => '未知请求']);
break;
}
} catch (Exception $e) {
echo json_encode(['code' => 500, 'msg' => '系统处理异常: ' . $e->getMessage()], JSON_UNESCAPED_UNICODE);
}