feat: 初始提交 Web 管理后台源码 (PHP)
This commit is contained in:
@@ -0,0 +1,213 @@
|
||||
<?php
|
||||
/**
|
||||
* 注册API
|
||||
* POST ?action=check - 检查用户名是否已注册
|
||||
* POST ?action=register - 注册新账号(需token)
|
||||
* GET ?action=query - 查询账号信息(需token)
|
||||
*/
|
||||
// 防止任何输出污染JSON响应
|
||||
ob_start();
|
||||
require_once __DIR__ . '/../core.php';
|
||||
ob_end_clean();
|
||||
|
||||
$action = getParam('action', 'check');
|
||||
$token = getParam('token');
|
||||
|
||||
switch ($action) {
|
||||
case 'check':
|
||||
registerCheck();
|
||||
break;
|
||||
case 'register':
|
||||
registerAccount($token);
|
||||
break;
|
||||
case 'web_register':
|
||||
webRegister();
|
||||
break;
|
||||
case 'query':
|
||||
registerQuery($token);
|
||||
break;
|
||||
default:
|
||||
error('未知操作: ' . $action);
|
||||
}
|
||||
|
||||
// ===== 检查用户名 =====
|
||||
function registerCheck() {
|
||||
$player = getParam('player');
|
||||
if (!$player) error('缺少player参数');
|
||||
|
||||
$db = getDB();
|
||||
// 只查询users表实际存在的列
|
||||
$stmt = $db->prepare("SELECT player_name, register_time, email FROM users WHERE player_name = :name");
|
||||
$stmt->bindValue(':name', $player, SQLITE3_TEXT);
|
||||
$result = $stmt->execute();
|
||||
$row = $result->fetchArray(SQLITE3_ASSOC);
|
||||
|
||||
success([
|
||||
'exists' => !!$row,
|
||||
'player' => $player,
|
||||
'info' => $row ?: null
|
||||
]);
|
||||
}
|
||||
|
||||
// ===== 注册账号 =====
|
||||
function registerAccount($token) {
|
||||
$player = getParam('player');
|
||||
$passwordHash = getParam('password_hash');
|
||||
$salt = getParam('salt');
|
||||
$email = getParam('email', '');
|
||||
$ip = getParam('ip', '');
|
||||
|
||||
if (!$player) error('缺少player');
|
||||
if (!$passwordHash) error('缺少password_hash');
|
||||
if (!$salt) error('缺少salt');
|
||||
|
||||
// 验证token(注册需要token)
|
||||
$isPreview = true;
|
||||
if ($token) {
|
||||
$tokenInfo = validateToken($token);
|
||||
if ($tokenInfo) {
|
||||
$isPreview = false;
|
||||
validateAndUseToken($token);
|
||||
}
|
||||
}
|
||||
|
||||
$db = getDB();
|
||||
|
||||
// 检查是否已注册
|
||||
$stmt = $db->prepare("SELECT 1 FROM users WHERE player_name = :name");
|
||||
$stmt->bindValue(':name', $player, SQLITE3_TEXT);
|
||||
$result = $stmt->execute();
|
||||
if ($result->fetchArray()) {
|
||||
error('账号已存在: ' . $player);
|
||||
}
|
||||
|
||||
if ($isPreview) {
|
||||
preview([
|
||||
'player' => $player,
|
||||
'email' => $email,
|
||||
'would_register' => true
|
||||
], '预览模式 - 注册不会生效');
|
||||
}
|
||||
|
||||
// 执行注册
|
||||
$now = time();
|
||||
$stmt = $db->prepare("INSERT INTO users (player_name, register_time, email) VALUES (:name, :time, :email)");
|
||||
$stmt->bindValue(':name', $player, SQLITE3_TEXT);
|
||||
$stmt->bindValue(':time', $now, SQLITE3_INTEGER);
|
||||
$stmt->bindValue(':email', $email, SQLITE3_TEXT);
|
||||
$stmt->execute();
|
||||
|
||||
// 记录
|
||||
$stmt = $db->prepare("INSERT INTO web_transactions (player_name, type, amount, reason, created_at) VALUES (:player, 'register', 0, 'Web端注册', :time)");
|
||||
$stmt->bindValue(':player', $player, SQLITE3_TEXT);
|
||||
$stmt->bindValue(':time', $now, SQLITE3_INTEGER);
|
||||
$stmt->execute();
|
||||
|
||||
success(['player' => $player], '注册成功');
|
||||
}
|
||||
|
||||
// ===== Web注册请求(由Web端提交,等待插件同步)=====
|
||||
function webRegister() {
|
||||
$webToken = getParam('web_token');
|
||||
$password = getParam('password');
|
||||
$email = getParam('email', '');
|
||||
$ipAddress = $_SERVER['REMOTE_ADDR'] ?? '0.0.0.0';
|
||||
|
||||
if (!$webToken) error('缺少web_token');
|
||||
if (!$password) error('缺少password');
|
||||
if (strlen($password) < 6) error('密码长度至少6位');
|
||||
|
||||
// 验证web_token
|
||||
$db = getDB();
|
||||
$stmt = $db->prepare("SELECT * FROM weblogin_tokens WHERE web_token = :token");
|
||||
$stmt->bindValue(':token', $webToken, SQLITE3_TEXT);
|
||||
$result = $stmt->execute();
|
||||
$tokenRow = $result->fetchArray(SQLITE3_ASSOC);
|
||||
|
||||
if (!$tokenRow) error('无效的Web登录Token');
|
||||
|
||||
$createdAt = (int)($tokenRow['created_at'] ?? 0);
|
||||
$expireSeconds = (int)($tokenRow['expire_seconds'] ?? 600);
|
||||
if (time() - $createdAt > $expireSeconds) error('Web登录Token已过期');
|
||||
|
||||
$playerName = $tokenRow['player_name'];
|
||||
|
||||
// 检查是否已注册
|
||||
if (isPlayerRegistered($playerName)) {
|
||||
error('玩家已注册: ' . $playerName);
|
||||
}
|
||||
|
||||
// 生成密码凭证(与插件相同的SHA-256算法)
|
||||
$saltBytes = random_bytes(16);
|
||||
$salt = base64_encode($saltBytes);
|
||||
$passwordHash = base64_encode(hash('sha256', $saltBytes . $password, true));
|
||||
|
||||
// ★ 创建web_register_requests表记录(等待插件同步)
|
||||
$db->exec("CREATE TABLE IF NOT EXISTS web_register_requests (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
player_name TEXT NOT NULL,
|
||||
password_hash TEXT NOT NULL,
|
||||
salt TEXT NOT NULL,
|
||||
email TEXT DEFAULT '',
|
||||
ip_address TEXT DEFAULT '',
|
||||
created_at INTEGER NOT NULL,
|
||||
status TEXT DEFAULT 'pending',
|
||||
processed_at INTEGER DEFAULT 0
|
||||
)");
|
||||
|
||||
// 插入注册请求
|
||||
$stmt = $db->prepare("INSERT INTO web_register_requests (player_name, password_hash, salt, email, ip_address, created_at) VALUES (:player, :hash, :salt, :email, :ip, :time)");
|
||||
$stmt->bindValue(':player', $playerName, SQLITE3_TEXT);
|
||||
$stmt->bindValue(':hash', $passwordHash, SQLITE3_TEXT);
|
||||
$stmt->bindValue(':salt', $salt, SQLITE3_TEXT);
|
||||
$stmt->bindValue(':email', $email, SQLITE3_TEXT);
|
||||
$stmt->bindValue(':ip', $ipAddress, SQLITE3_TEXT);
|
||||
$stmt->bindValue(':time', time(), SQLITE3_INTEGER);
|
||||
$stmt->execute();
|
||||
|
||||
$requestId = $db->lastInsertRowID();
|
||||
|
||||
success([
|
||||
'player' => $playerName,
|
||||
'request_id' => $requestId,
|
||||
'email' => $email
|
||||
], '注册请求已提交,等待游戏同步');
|
||||
}
|
||||
|
||||
// ===== 查询账号信息 =====
|
||||
function registerQuery($token) {
|
||||
$player = getParam('player');
|
||||
if (!$player) error('缺少player');
|
||||
|
||||
$db = getDB();
|
||||
// 只查询users表实际存在的列
|
||||
$stmt = $db->prepare("SELECT player_name, register_time, last_login_time, email, points, gift_stage, total_online_time FROM users WHERE player_name = :name");
|
||||
$stmt->bindValue(':name', $player, SQLITE3_TEXT);
|
||||
$result = $stmt->execute();
|
||||
$row = $result->fetchArray(SQLITE3_ASSOC);
|
||||
|
||||
if (!$row) {
|
||||
error('账号不存在: ' . $player);
|
||||
}
|
||||
|
||||
// 处理Java插件推送的毫秒级时间戳,转换为秒级
|
||||
if ($row['register_time'] && $row['register_time'] > 1000000000000) {
|
||||
$row['register_time'] = (int)($row['register_time'] / 1000);
|
||||
}
|
||||
if ($row['last_login_time'] && $row['last_login_time'] > 1000000000000) {
|
||||
$row['last_login_time'] = (int)($row['last_login_time'] / 1000);
|
||||
}
|
||||
|
||||
// 有token才返回完整信息
|
||||
$tokenInfo = null;
|
||||
if ($token) {
|
||||
$tokenInfo = validateToken($token);
|
||||
}
|
||||
|
||||
if ($tokenInfo) {
|
||||
success($row);
|
||||
} else {
|
||||
// 无token:隐藏敏感信息
|
||||
preview($row, '预览模式 - 部分信息已隐藏');
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user