provider->exchange(Fields::text($input, 'code', 512)); return $this->issue($identity); } /** Internal only. The HTTP controller never accepts provider identity from clients. */ public function issue(array $identity): array { return (new MiniUser())->getConnection()->transaction(function () use ($identity) { $now = date('Y-m-d H:i:s'); MiniUser::query()->insertOrIgnore($identity + [ 'nickname' => '', 'status' => 1, 'created_at' => $now, 'updated_at' => $now, ]); $user = MiniUser::query()->where($identity)->lockForUpdate()->firstOrFail(); if ((int) $user->status !== 1) { throw new ApiException(40302, '账号已停用', 403); } $token = bin2hex(random_bytes(32)); $expires = date('Y-m-d H:i:s', time() + (int) config('mini_api.session_ttl', 604800)); MiniSession::query()->insert([ 'user_id' => $user->id, 'token_hash' => hash('sha256', $token), 'expires_at' => $expires, 'created_at' => $now, ]); return [ 'access_token' => $token, 'token_type' => 'Bearer', 'expires_at' => $expires, 'user_id' => (string) $user->id, 'identities' => (new Access(new Principal((string) $user->id)))->identities(), ]; }); } public function logout(string $token): array { MiniSession::query()->where('token_hash', hash('sha256', $token))->whereNull('revoked_at')->update(['revoked_at' => date('Y-m-d H:i:s')]); return ['logged_out' => true]; } }