Files
shuiguoji/actions.php
T
2026-07-23 08:58:13 +08:00

129 lines
6.1 KiB
PHP

<?php
declare(strict_types=1);
require __DIR__ . '/includes/bootstrap.php';
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
redirect('/index.php');
}
$action = (string) ($_POST['action'] ?? '');
$return = (string) ($_POST['return'] ?? '/index.php');
if (!str_starts_with($return, '/') || str_starts_with($return, '//')) {
$return = '/index.php';
}
try {
verify_csrf();
switch ($action) {
case 'register':
$username = trim((string) ($_POST['username'] ?? ''));
assert_auth_not_limited('register', $username, 5, 3600);
record_auth_attempt('register', $username, false);
$password = (string) ($_POST['password'] ?? '');
$confirm = (string) ($_POST['password_confirm'] ?? '');
$phone = trim((string) ($_POST['phone'] ?? ''));
$inviteCode = trim((string) ($_POST['invite_code'] ?? ''));
if (!preg_match('/^[a-zA-Z0-9_]{6,20}$/', $username)) {
throw new RuntimeException('账号需为 6-20 位字母、数字或下划线。');
}
if (strlen($password) < 8 || strlen($password) > 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);
}