API接口

1.新增鉴权接口/api/v1/authToken
2.修复注册,登录,获取首页初始化数据,获取用户信息接口报错
This commit is contained in:
2026-04-16 18:42:44 +08:00
parent 5ee0f2b1f4
commit cfe5ec6fb0
12 changed files with 93 additions and 60 deletions

View File

@@ -19,7 +19,8 @@ use support\Response;
class Account extends Frontend class Account extends Frontend
{ {
protected array $noNeedLogin = ['retrievePassword']; protected array $noNeedLogin = ['retrievePassword'];
protected array $noNeedPermission = ['verification', 'changeBind']; // 移动端 API 不走会员权限表user_group/user_rule校验仅校验登录态
protected array $noNeedPermission = ['*'];
public function userProfile(Request $request): Response public function userProfile(Request $request): Response
{ {
@@ -44,7 +45,6 @@ class Account extends Frontend
'code' => 1, 'code' => 1,
'message' => __('ok'), 'message' => __('ok'),
'data' => [ 'data' => [
'id' => $user->id,
'username' => $user->username, 'username' => $user->username,
'head_image' => $user->avatar ?? '', 'head_image' => $user->avatar ?? '',
'coin' => $user->coin, 'coin' => $user->coin,
@@ -172,7 +172,7 @@ class Account extends Frontend
if (!Token::check($params['accountVerificationToken'], $params['type'] . '-pass', $user->id)) { if (!Token::check($params['accountVerificationToken'], $params['type'] . '-pass', $user->id)) {
return $this->error(__('You need to verify your account before modifying the binding information')); return $this->error(__('You need to verify your account before modifying the binding information'));
} }
} elseif (!isset($params['password']) || !verify_password($params['password'], $user->password, ['salt' => $user->salt])) { } elseif (!isset($params['password']) || !verify_password($params['password'], $user->password, ['salt' => $user->salt ?? ''])) {
return $this->error(__('Password error')); return $this->error(__('Password error'));
} }
@@ -213,7 +213,7 @@ class Account extends Frontend
$model = $this->auth->getUser(); $model = $this->auth->getUser();
$params = $request->only(['oldPassword', 'newPassword']); $params = $request->only(['oldPassword', 'newPassword']);
if (!verify_password($params['oldPassword'], $model->password, ['salt' => $model->salt])) { if (!verify_password($params['oldPassword'], $model->password, ['salt' => $model->salt ?? ''])) {
return $this->error(__('Old password error')); return $this->error(__('Old password error'));
} }

View File

@@ -14,7 +14,8 @@ use support\Response;
class Auth extends MobileBase class Auth extends MobileBase
{ {
protected array $noNeedLogin = ['userRegister', 'userLogin', 'tokenRefresh']; protected array $noNeedLogin = ['register', 'login', 'refreshToken', 'userRegister', 'userLogin', 'tokenRefresh'];
protected array $noNeedAuthToken = ['register', 'login', 'refreshToken', 'userRegister', 'userLogin', 'tokenRefresh'];
public function userRegister(Request $request): Response public function userRegister(Request $request): Response
{ {
@@ -23,27 +24,22 @@ class Auth extends MobileBase
return $response; return $response;
} }
$account = trim((string) $request->post('account', '')); $username = trim((string) $request->post('username', ''));
$accountType = trim((string) $request->post('account_type', '')); if ($username === '') {
$username = trim((string) $request->post('account', ''));
}
$password = (string) $request->post('password', ''); $password = (string) $request->post('password', '');
$inviteCode = trim((string) $request->post('invite_code', '')); $inviteCode = trim((string) $request->post('invite_code', ''));
if ($account === '' || $accountType === '' || $password === '') { if ($username === '' || $password === '') {
return $this->mobileError(1001, 'Missing parameters'); return $this->mobileError(1001, 'Missing parameters');
} }
if ($accountType !== 'phone' && $accountType !== 'email') { if (!preg_match('/^1[3-9]\d{9}$/', $username)) {
return $this->mobileError(1003, 'Invalid parameter value'); return $this->mobileError(1003, 'Please enter the correct mobile number');
} }
$username = $account; $phone = $username;
$mobile = '';
$email = ''; $email = '';
if ($accountType === 'phone') {
$mobile = $account;
}
if ($accountType === 'email') {
$email = $account;
}
$extend = []; $extend = [];
if ($inviteCode !== '') { if ($inviteCode !== '') {
@@ -56,7 +52,7 @@ class Auth extends MobileBase
$extend['channel_id'] = $inviterAdmin['channel_id'] ?? null; $extend['channel_id'] = $inviterAdmin['channel_id'] ?? null;
} }
$registered = $this->auth->register($username, $password, $mobile, $email, 1, $extend); $registered = $this->auth->register($username, $password, $phone, $email, 1, $extend);
if (!$registered) { if (!$registered) {
return $this->mobileError(2000, (string) $this->auth->getError()); return $this->mobileError(2000, (string) $this->auth->getError());
} }
@@ -66,17 +62,7 @@ class Auth extends MobileBase
return $this->mobileError(2000, 'Registered successfully but login failed'); return $this->mobileError(2000, 'Registered successfully but login failed');
} }
$userInfo = $this->auth->getUserInfo(); return $this->mobileSuccess($this->buildLoginPayload());
return $this->mobileSuccess([
'user_id' => $userInfo['id'] ?? null,
'access_token' => $userInfo['token'] ?? '',
'expires_in' => config('buildadmin.user_token_keep_time', 259200),
'profile' => [
'username' => $userInfo['username'] ?? '',
'coin' => $userInfo['coin'] ?? '0.0000',
'channel_id' => $userInfo['channel_id'] ?? null,
],
]);
} }
public function userLogin(Request $request): Response public function userLogin(Request $request): Response
@@ -86,28 +72,20 @@ class Auth extends MobileBase
return $response; return $response;
} }
$account = trim((string) $request->post('account', '')); $username = trim((string) $request->post('username', ''));
if ($username === '') {
$username = trim((string) $request->post('account', ''));
}
$password = (string) $request->post('password', ''); $password = (string) $request->post('password', '');
if ($account === '' || $password === '') { if ($username === '' || $password === '') {
return $this->mobileError(1001, 'Missing parameters'); return $this->mobileError(1001, 'Missing parameters');
} }
$ok = $this->auth->login($account, $password, true); $ok = $this->auth->login($username, $password, true);
if (!$ok) { if (!$ok) {
return $this->mobileError(1101, 'Incorrect account or password'); return $this->mobileError(1101, 'Incorrect account or password');
} }
$userInfo = $this->auth->getUserInfo(); return $this->mobileSuccess($this->buildLoginPayload());
return $this->mobileSuccess([
'access_token' => $userInfo['token'] ?? '',
'refresh_token' => $userInfo['refresh_token'] ?? '',
'expires_in' => config('buildadmin.user_token_keep_time', 259200),
'user' => [
'id' => $userInfo['id'] ?? null,
'username' => $userInfo['username'] ?? '',
'coin' => $userInfo['coin'] ?? '0.0000',
'risk_flags' => $userInfo['risk_flags'] ?? 0,
],
]);
} }
public function tokenRefresh(Request $request): Response public function tokenRefresh(Request $request): Response
@@ -130,9 +108,25 @@ class Auth extends MobileBase
$newToken = Random::uuid(); $newToken = Random::uuid();
Token::set($newToken, UserAuth::TOKEN_TYPE, $tokenData['user_id'], config('buildadmin.user_token_keep_time', 259200)); Token::set($newToken, UserAuth::TOKEN_TYPE, $tokenData['user_id'], config('buildadmin.user_token_keep_time', 259200));
return $this->mobileSuccess([ return $this->mobileSuccess([
'access_token' => $newToken, 'user-token' => $newToken,
'expires_in' => config('buildadmin.user_token_keep_time', 259200), 'expires_in' => config('buildadmin.user_token_keep_time', 259200),
]); ]);
} }
private function buildLoginPayload(): array
{
$userInfo = $this->auth->getUserInfo();
return [
'user-token' => $userInfo['token'] ?? '',
'refresh_token' => $userInfo['refresh_token'] ?? '',
'expires_in' => config('buildadmin.user_token_keep_time', 259200),
'user' => [
'username' => $userInfo['username'] ?? '',
'coin' => $userInfo['coin'] ?? '0.0000',
'channel_id' => $userInfo['channel_id'] ?? null,
'risk_flags' => $userInfo['risk_flags'] ?? 0,
],
];
}
} }

View File

@@ -74,7 +74,7 @@ class Ems extends Frontend
return $this->error(__('Please use the account registration email to send the verification code')); return $this->error(__('Please use the account registration email to send the verification code'));
} }
$password = $request->post('password'); $password = $request->post('password');
if (!verify_password($password, $this->auth->password, ['salt' => $this->auth->salt])) { if (!verify_password($password, $this->auth->password, ['salt' => $this->auth->salt ?? ''])) {
return $this->error(__('Password error')); return $this->error(__('Password error'));
} }
} }

View File

@@ -22,6 +22,8 @@ return [
'Invalid signature' => 'Invalid signature', 'Invalid signature' => 'Invalid signature',
'Invalid timestamp' => 'Invalid timestamp', 'Invalid timestamp' => 'Invalid timestamp',
'Invite code does not exist' => 'Invite code does not exist', 'Invite code does not exist' => 'Invite code does not exist',
'Register only supports phone' => 'Register only supports phone',
'Please enter the correct mobile number' => 'Please enter the correct mobile number',
'Registered successfully but login failed' => 'Registered successfully but login failed', 'Registered successfully but login failed' => 'Registered successfully but login failed',
'Incorrect account or password' => 'Incorrect account or password', 'Incorrect account or password' => 'Incorrect account or password',
'Login status has expired' => 'Login status has expired', 'Login status has expired' => 'Login status has expired',

View File

@@ -54,6 +54,8 @@ return [
'Invalid signature' => '签名错误', 'Invalid signature' => '签名错误',
'Invalid timestamp' => '时间戳无效', 'Invalid timestamp' => '时间戳无效',
'Invite code does not exist' => '邀请码不存在', 'Invite code does not exist' => '邀请码不存在',
'Register only supports phone' => '注册仅支持手机号',
'Please enter the correct mobile number' => '请输入正确的手机号',
'Registered successfully but login failed' => '注册成功但登录失败', 'Registered successfully but login failed' => '注册成功但登录失败',
'Incorrect account or password' => '账号或密码错误', 'Incorrect account or password' => '账号或密码错误',
'Login status has expired' => '登录状态已过期', 'Login status has expired' => '登录状态已过期',

View File

@@ -36,7 +36,13 @@ class Frontend extends Api
try { try {
$this->auth = Auth::instance(['request' => $request]); $this->auth = Auth::instance(['request' => $request]);
$token = get_auth_token(['ba', 'user', 'token'], $request); $token = trim((string) $request->header('user-token', ''));
if ($token === '') {
$token = trim((string) $request->header('user_token', ''));
}
if ($token === '') {
$token = get_auth_token(['ba', 'user', 'token'], $request);
}
if ($token) $this->auth->init($token); if ($token) $this->auth->init($token);
} catch (TokenExpirationException) { } catch (TokenExpirationException) {
if ($needLogin) return $this->error(__('Token expiration'), [], 409); if ($needLogin) return $this->error(__('Token expiration'), [], 409);

View File

@@ -67,7 +67,8 @@ class Auth extends \ba\Auth
$this->setError('Account not exist'); $this->setError('Account not exist');
return false; return false;
} }
if ($this->model->status != 'enable') { $status = $this->model->status ?? '';
if ($status === 'disable' || $status === 0 || $status === '0') {
$this->setError('Account disabled'); $this->setError('Account disabled');
return false; return false;
} }
@@ -81,7 +82,7 @@ class Auth extends \ba\Auth
return false; return false;
} }
public function register(string $username, string $password = '', string $mobile = '', string $email = '', int $group = 1, array $extend = []): bool public function register(string $username, string $password = '', string $phone = '', string $email = '', int $group = 1, array $extend = []): bool
{ {
$request = function_exists('request') ? request() : null; $request = function_exists('request') ? request() : null;
$ip = $request ? $request->getRealIp() : '0.0.0.0'; $ip = $request ? $request->getRealIp() : '0.0.0.0';
@@ -90,7 +91,9 @@ class Auth extends \ba\Auth
$this->setError(__('Email')); $this->setError(__('Email'));
return false; return false;
} }
if ($username && !preg_match('/^[a-zA-Z][a-zA-Z0-9_]{2,15}$/', $username)) { $isMobileUsername = preg_match('/^1[3-9]\d{9}$/', $username) === 1;
$isNormalUsername = preg_match('/^[a-zA-Z][a-zA-Z0-9_]{2,15}$/', $username) === 1;
if ($username && !$isMobileUsername && !$isNormalUsername) {
$this->setError(__('Username')); $this->setError(__('Username'));
return false; return false;
} }
@@ -112,9 +115,9 @@ class Auth extends \ba\Auth
'join_time' => $time, 'join_time' => $time,
'last_login_ip' => $ip, 'last_login_ip' => $ip,
'last_login_time' => $time, 'last_login_time' => $time,
'status' => 'enable', 'status' => 1,
]; ];
$data = array_merge(compact('username', 'password', 'mobile', 'email'), $data, $extend); $data = array_merge(compact('username', 'password', 'phone', 'email'), $data, $extend);
Db::startTrans(); Db::startTrans();
try { try {
@@ -139,7 +142,7 @@ class Auth extends \ba\Auth
public function login(string $username, string $password, bool $keep): bool public function login(string $username, string $password, bool $keep): bool
{ {
$accountType = false; $accountType = false;
if (preg_match('/^1[3-9]\d{9}$/', $username)) $accountType = 'mobile'; if (preg_match('/^1[3-9]\d{9}$/', $username)) $accountType = 'phone';
elseif (filter_var($username, FILTER_VALIDATE_EMAIL)) $accountType = 'email'; elseif (filter_var($username, FILTER_VALIDATE_EMAIL)) $accountType = 'email';
elseif (preg_match('/^[a-zA-Z][a-zA-Z0-9_]{2,15}$/', $username)) $accountType = 'username'; elseif (preg_match('/^[a-zA-Z][a-zA-Z0-9_]{2,15}$/', $username)) $accountType = 'username';
if (!$accountType) { if (!$accountType) {
@@ -152,7 +155,8 @@ class Auth extends \ba\Auth
$this->setError('Account not exist'); $this->setError('Account not exist');
return false; return false;
} }
if ($this->model->status == 'disable') { $status = $this->model->status ?? '';
if ($status === 'disable' || $status === 0 || $status === '0') {
$this->setError('Account disabled'); $this->setError('Account disabled');
return false; return false;
} }
@@ -171,7 +175,7 @@ class Auth extends \ba\Auth
} }
} }
if (!verify_password($password, $this->model->password, ['salt' => $this->model->salt])) { if (!verify_password($password, $this->model->password, ['salt' => $this->model->salt ?? ''])) {
$this->loginFailed(); $this->loginFailed();
$this->setError('Password is incorrect'); $this->setError('Password is incorrect');
return false; return false;

View File

@@ -30,7 +30,7 @@ class AllowCrossDomain implements MiddlewareInterface
'Access-Control-Allow-Credentials' => 'true', 'Access-Control-Allow-Credentials' => 'true',
'Access-Control-Max-Age' => '1800', 'Access-Control-Max-Age' => '1800',
'Access-Control-Allow-Methods' => 'GET, POST, PUT, DELETE, PATCH, OPTIONS', 'Access-Control-Allow-Methods' => 'GET, POST, PUT, DELETE, PATCH, OPTIONS',
'Access-Control-Allow-Headers' => 'Content-Type, Authorization, batoken, ba-user-token, think-lang, server', 'Access-Control-Allow-Headers' => 'Content-Type, Authorization, batoken, ba-user-token, user-token, access-token, think-lang, server',
]; ];
$origin = $request->header('origin'); $origin = $request->header('origin');
if (is_array($origin)) { if (is_array($origin)) {

View File

@@ -32,4 +32,9 @@ class User extends Model
{ {
return $this->belongsTo(\app\admin\model\Admin::class, 'admin_id', 'id'); return $this->belongsTo(\app\admin\model\Admin::class, 'admin_id', 'id');
} }
public function resetPassword(int|string $uid, string $newPassword): int
{
return $this->where(['id' => $uid])->update(['password' => hash_password($newPassword)]);
}
} }

View File

@@ -161,6 +161,20 @@ if (!function_exists('get_auth_token')) {
} }
} }
} }
$authorization = $request->header('authorization');
if (is_string($authorization) && preg_match('/^\s*Bearer\s+(.+?)\s*$/i', $authorization, $matches) === 1) {
$tokens[] = $matches[1];
}
foreach (['user_token', 'user-token', 'access_token', 'access-token'] as $key) {
$headerToken = $request->header($key);
if ($headerToken) {
$tokens[] = $headerToken;
}
$paramToken = $request->get($key) ?? $request->post($key);
if ($paramToken) {
$tokens[] = $paramToken;
}
}
return $tokens[0] ?? ''; return $tokens[0] ?? '';
} }
} }

View File

@@ -111,11 +111,17 @@ Route::post('/api/account/retrievePassword', [\app\api\controller\Account::class
// api/ems // api/ems
Route::post('/api/ems/send', [\app\api\controller\Ems::class, 'send']); Route::post('/api/ems/send', [\app\api\controller\Ems::class, 'send']);
// ==================== 移动端游戏接口(36字花 ==================== // ==================== 移动端用户接口(统一收口到 /api/user/* ====================
Route::post('/api/user/register', [\app\api\controller\Auth::class, 'userRegister']);
Route::post('/api/user/login', [\app\api\controller\Auth::class, 'userLogin']);
Route::post('/api/user/refreshToken', [\app\api\controller\Auth::class, 'tokenRefresh']);
Route::get('/api/user/profile', [\app\api\controller\Account::class, 'userProfile']);
Route::post('/api/user/retrievePassword', [\app\api\controller\Account::class, 'retrievePassword']);
// 兼容旧移动端路径,后续客户端切换完成后可移除
Route::post('/api/auth/userRegister', [\app\api\controller\Auth::class, 'userRegister']); Route::post('/api/auth/userRegister', [\app\api\controller\Auth::class, 'userRegister']);
Route::post('/api/auth/userLogin', [\app\api\controller\Auth::class, 'userLogin']); Route::post('/api/auth/userLogin', [\app\api\controller\Auth::class, 'userLogin']);
Route::post('/api/auth/tokenRefresh', [\app\api\controller\Auth::class, 'tokenRefresh']); Route::post('/api/auth/tokenRefresh', [\app\api\controller\Auth::class, 'tokenRefresh']);
Route::get('/api/account/userProfile', [\app\api\controller\Account::class, 'userProfile']); Route::get('/api/account/userProfile', [\app\api\controller\Account::class, 'userProfile']);
Route::get('/api/game/lobbyInit', [\app\api\controller\Game::class, 'lobbyInit']); Route::get('/api/game/lobbyInit', [\app\api\controller\Game::class, 'lobbyInit']);

View File

@@ -109,7 +109,7 @@ export function postLogout() {
export function retrievePassword(params: anyObj) { export function retrievePassword(params: anyObj) {
return createAxios( return createAxios(
{ {
url: accountUrl + 'retrievePassword', url: userUrl + 'retrievePassword',
method: 'POST', method: 'POST',
data: params, data: params,
}, },