72) { throw new RuntimeException('密码需为 8-72 位。'); } if ($password !== $confirm) { throw new RuntimeException('两次输入的密码不一致。'); } if ($phone !== '' && !preg_match('/^[0-9+ -]{6,20}$/', $phone)) { throw new RuntimeException('手机号格式不正确。'); } $created = create_user_account($username,$password,$phone,$inviteCode); $userId = (int)$created['user_id']; session_regenerate_id(true); $_SESSION['user_id'] = $userId; flash('success', '注册成功,欢迎加入。'); redirect('/index.php'); case 'login': $username = trim((string) ($_POST['username'] ?? '')); $password = (string) ($_POST['password'] ?? ''); assert_auth_not_limited('user_login', $username, 5, 900); $stmt = db()->prepare('SELECT * FROM users WHERE username = ?'); $stmt->execute([$username]); $user = $stmt->fetch(); if (!$user || !password_verify($password, $user['password_hash'])) { record_auth_attempt('user_login', $username, false); throw new RuntimeException('账号或密码错误。'); } if ((int) $user['status'] !== 1) { throw new RuntimeException('账号已停用,请联系客服。'); } session_regenerate_id(true); $_SESSION['user_id'] = (int) $user['id']; record_auth_attempt('user_login', $username, true); db()->prepare('UPDATE users SET last_login_at = ?, last_login_ip = ? WHERE id = ?')->execute([now(), client_ip(), $user['id']]); flash('success', '登录成功。'); redirect('/index.php'); case 'logout': unset($_SESSION['user_id']); session_regenerate_id(true); flash('success', '已安全退出。'); redirect('/index.php?view=login'); case 'recharge': $user = require_user(); $amount = round((float) ($_POST['amount'] ?? 0), 2); $method = (string) ($_POST['method'] ?? 'wechat'); $note = trim((string) ($_POST['payer_note'] ?? '')); if ($amount < 10 || $amount > 100000) { throw new RuntimeException('充值金额需在 10-100000 之间。'); } if (!in_array($method, ['wechat', 'alipay', 'bank'], true)) { throw new RuntimeException('不支持的充值方式。'); } if ($note === '') { throw new RuntimeException('请填写付款备注。'); } $no = order_no(); $stmt = db()->prepare('INSERT INTO recharge_orders (order_no, user_id, amount, method, payer_note, status, created_at) VALUES (?, ?, ?, ?, ?, ?, ?)'); $stmt->execute([$no, $user['id'], $amount, $method, mb_substr($note, 0, 200), 'pending', now()]); flash('success', '充值申请已提交,订单号:' . $no); redirect('/index.php?view=recharge'); case 'redeem_card': $user = require_user(); $code = strtoupper(trim((string) ($_POST['card_code'] ?? ''))); redeem_recharge_card((int)$user['id'], $code); flash('success', '充值卡兑换成功。'); redirect('/index.php?view=recharge'); case 'profile': $user = require_user(); $phone = trim((string) ($_POST['phone'] ?? '')); if ($phone !== '' && !preg_match('/^[0-9+ -]{6,20}$/', $phone)) { throw new RuntimeException('手机号格式不正确。'); } db()->prepare('UPDATE users SET phone = ?, updated_at = ? WHERE id = ?')->execute([$phone, now(), $user['id']]); flash('success', '资料已保存。'); redirect('/index.php?view=security'); case 'password': $user = require_user(); $old = (string) ($_POST['old_password'] ?? ''); $new = (string) ($_POST['new_password'] ?? ''); $confirm = (string) ($_POST['new_password_confirm'] ?? ''); if (!password_verify($old, $user['password_hash'])) throw new RuntimeException('原密码不正确。'); if (strlen($new) < 8 || strlen($new) > 72) throw new RuntimeException('新密码需为 8-72 位。'); if ($new !== $confirm) throw new RuntimeException('两次输入的新密码不一致。'); db()->prepare('UPDATE users SET password_hash = ?, updated_at = ? WHERE id = ?')->execute([password_hash($new, PASSWORD_DEFAULT), now(), $user['id']]); session_regenerate_id(true); flash('success', '密码修改成功。'); redirect('/index.php?view=security'); default: throw new RuntimeException('无效的操作。'); } } catch (Throwable $e) { flash('error', $e instanceof RuntimeException ? $e->getMessage() : '系统暂时无法处理,请稍后重试。'); redirect($return); }