validateRequiredFields($data); // 生成应用ID和密钥 $data['app_id'] = OpenApiApp::generateAppId(); $data['app_secret'] = OpenApiApp::generateAppSecret(); // 设置默认值 $data['status'] = $data['status'] ?? config('openapi.app.default_status', APP_STATUS::PENDING->value); $data['auth_type'] = $data['auth_type'] ?? config('openapi.auth.default_type', AUTH_TYPE::API_KEY->value); $data['scopes'] = $data['scopes'] ?? config('openapi.scopes.default', []); // 设置过期时间 if (!isset($data['expires_at'])) { $expireDays = config('openapi.app.expire_days', 365); $data['expires_at'] = now()->addDays($expireDays); } // 加密应用密钥 if (config('openapi.security.encrypt_secrets', true)) { $data['app_secret'] = encrypt($data['app_secret']); } // 创建应用 $app = OpenApiApp::create($data); // 触发应用创建事件 Event::dispatch(new AppCreatedEvent($app)); return $app; } /** * 验证必填字段 * * @param array $data * @throws \InvalidArgumentException */ protected function validateRequiredFields(array $data): void { $requiredFields = config('openapi.app.required_fields', ['name', 'description', 'callback_url']); foreach ($requiredFields as $field) { if (empty($data[$field])) { throw new \InvalidArgumentException("字段 {$field} 是必填的"); } } } /** * 审核应用 * * @param int $appId * @param bool $approved * @param string $note * @param int $approvedBy * @return OpenApiApp */ public function approveApp(int $appId, bool $approved, string $note = '', int $approvedBy = null): OpenApiApp { $app = OpenApiApp::findOrFail($appId); if ($app->status !== APP_STATUS::PENDING->value) { throw new \InvalidArgumentException('只能审核待审核状态的应用'); } $app->update([ 'status' => $approved ? APP_STATUS::APPROVED->value : APP_STATUS::REJECTED->value, 'approved_at' => now(), 'approved_by' => $approvedBy, 'approved_note' => $note, ]); // 清除缓存 $this->clearAppCache($app->app_id); return $app; } /** * 激活应用 * * @param int $appId * @return OpenApiApp */ public function activateApp(int $appId): OpenApiApp { $app = OpenApiApp::findOrFail($appId); if (!in_array($app->status, [APP_STATUS::APPROVED->value, APP_STATUS::SUSPENDED->value])) { throw new \InvalidArgumentException('只能激活已审核或已暂停的应用'); } $app->update(['status' => APP_STATUS::ACTIVE->value]); // 清除缓存 $this->clearAppCache($app->app_id); return $app; } /** * 暂停应用 * * @param int $appId * @param string $reason * @return OpenApiApp */ public function suspendApp(int $appId, string $reason = ''): OpenApiApp { $app = OpenApiApp::findOrFail($appId); if ($app->status !== APP_STATUS::ACTIVE->value) { throw new \InvalidArgumentException('只能暂停激活状态的应用'); } $app->update([ 'status' => APP_STATUS::SUSPENDED->value, 'approved_note' => $reason, ]); // 清除缓存 $this->clearAppCache($app->app_id); return $app; } /** * 禁用应用 * * @param int $appId * @param string $reason * @return OpenApiApp */ public function disableApp(int $appId, string $reason = ''): OpenApiApp { $app = OpenApiApp::findOrFail($appId); $app->update([ 'status' => APP_STATUS::DISABLED->value, 'approved_note' => $reason, ]); // 清除缓存 $this->clearAppCache($app->app_id); return $app; } /** * 重新生成应用密钥 * * @param int $appId * @return OpenApiApp */ public function regenerateSecret(int $appId): OpenApiApp { $app = OpenApiApp::findOrFail($appId); if (!config('openapi.api_key.allow_regenerate', true)) { throw new \InvalidArgumentException('不允许重新生成密钥'); } $newSecret = OpenApiApp::generateAppSecret(); // 加密应用密钥 if (config('openapi.security.encrypt_secrets', true)) { $newSecret = encrypt($newSecret); } $app->update(['app_secret' => $newSecret]); // 清除缓存 $this->clearAppCache($app->app_id); return $app; } /** * 更新应用权限 * * @param int $appId * @param array $scopes * @return OpenApiApp */ public function updateScopes(int $appId, array $scopes): OpenApiApp { $app = OpenApiApp::findOrFail($appId); // 验证权限范围 $this->validateScopes($scopes); $app->update(['scopes' => $scopes]); // 清除缓存 $this->clearAppCache($app->app_id); return $app; } /** * 验证权限范围 * * @param array $scopes * @throws \InvalidArgumentException */ protected function validateScopes(array $scopes): void { $validScopes = array_column(SCOPE_TYPE::cases(), 'value'); $validScopes[] = '*'; // 允许通配符 foreach ($scopes as $scope) { if (!in_array($scope, $validScopes)) { throw new \InvalidArgumentException("无效的权限范围: {$scope}"); } } } /** * 通过应用ID获取应用信息 * * @param string $appId * @return OpenApiApp|null */ public function getAppByAppId(string $appId): ?OpenApiApp { $cacheKey = config('openapi.cache.keys.app_info'); $cacheKey = str_replace('{app_id}', $appId, $cacheKey); return Cache::remember($cacheKey, config('openapi.cache.default_ttl', 300), function () use ($appId) { return OpenApiApp::where('app_id', $appId)->first(); }); } /** * 验证应用认证 * * @param string $appId * @param string $appSecret * @return OpenApiApp|null */ public function validateApp(string $appId, string $appSecret): ?OpenApiApp { $app = $this->getAppByAppId($appId); if (!$app) { return null; } // 检查应用状态 if (!$app->can_call_api) { return null; } // 检查应用是否过期 if ($app->is_expired) { return null; } // 验证密钥 $storedSecret = $app->app_secret; if (config('openapi.security.encrypt_secrets', true)) { $storedSecret = decrypt($storedSecret); } if (!hash_equals($storedSecret, $appSecret)) { return null; } return $app; } /** * 检查应用权限 * * @param OpenApiApp $app * @param string $scope * @return bool */ public function checkScope(OpenApiApp $app, string $scope): bool { return $app->hasScope($scope); } /** * 检查IP白名单 * * @param OpenApiApp $app * @param string $ip * @return bool */ public function checkIpWhitelist(OpenApiApp $app, string $ip): bool { return $app->isIpAllowed($ip); } /** * 更新应用最后使用时间 * * @param OpenApiApp $app * @return void */ public function updateLastUsed(OpenApiApp $app): void { $app->updateLastUsed(); } /** * 获取应用统计信息 * * @param int $appId * @param int $days * @return array */ public function getAppStats(int $appId, int $days = 30): array { // 这里可以实现统计逻辑 // 暂时返回模拟数据 return [ 'total_requests' => 0, 'successful_requests' => 0, 'failed_requests' => 0, 'average_response_time' => 0, 'last_request_at' => null, ]; } /** * 清除应用缓存 * * @param string $appId * @return void */ protected function clearAppCache(string $appId): void { $cacheKey = config('openapi.cache.keys.app_info'); $cacheKey = str_replace('{app_id}', $appId, $cacheKey); Cache::forget($cacheKey); } /** * 批量处理过期应用 * * @return int */ public function handleExpiredApps(): int { $expiredApps = OpenApiApp::where('expires_at', '<', now()) ->where('status', '!=', APP_STATUS::EXPIRED->value) ->get(); $count = 0; foreach ($expiredApps as $app) { $app->update(['status' => APP_STATUS::EXPIRED->value]); $this->clearAppCache($app->app_id); $count++; } return $count; } /** * 获取用户的应用列表 * * @param int $userId * @return \Illuminate\Database\Eloquent\Collection */ public function getUserApps(int $userId) { return OpenApiApp::byUser($userId)->orderBy('created_at', 'desc')->get(); } /** * 检查用户是否可以创建更多应用 * * @param int $userId * @return bool */ public function canCreateMoreApps(int $userId): bool { $maxApps = config('openapi.app.max_apps_per_user', 10); $currentCount = OpenApiApp::byUser($userId)->count(); return $currentCount < $maxApps; } }