info('开始同步第三方服务...'); try { $services = $this->loadServicesConfig(); if (empty($services)) { $this->warn('没有找到需要同步的服务配置'); return Command::SUCCESS; } $this->displayServicesToSync($services); if ($this->option('dry-run')) { $this->info('这是预览模式,没有实际同步服务'); return Command::SUCCESS; } if (!$this->option('force') && !$this->confirm('确认要同步这些服务吗?')) { $this->info('操作已取消'); return Command::SUCCESS; } $results = $this->syncServices($services); $this->displayResults($results); return Command::SUCCESS; } catch (\Exception $e) { $this->error("同步失败: {$e->getMessage()}"); return Command::FAILURE; } } /** * 加载服务配置 * * @return array */ protected function loadServicesConfig(): array { $configPath = $this->option('config'); if ($configPath) { if (!file_exists($configPath)) { throw new \Exception("配置文件不存在: {$configPath}"); } $config = json_decode(file_get_contents($configPath), true); if (json_last_error() !== JSON_ERROR_NONE) { throw new \Exception("配置文件格式错误: " . json_last_error_msg()); } return $config['services'] ?? []; } // 使用默认配置 return $this->getDefaultServicesConfig(); } /** * 获取默认服务配置 * * @return array */ protected function getDefaultServicesConfig(): array { return [ [ 'name' => '阿里云短信服务', 'code' => 'aliyun_sms', 'type' => 'SMS', 'provider' => 'ALIYUN', 'description' => '阿里云短信发送服务', 'base_url' => 'https://dysmsapi.aliyuncs.com', 'auth_type' => 'API_KEY', 'status' => 'INACTIVE', ], [ 'name' => '腾讯云短信服务', 'code' => 'tencent_sms', 'type' => 'SMS', 'provider' => 'TENCENT', 'description' => '腾讯云短信发送服务', 'base_url' => 'https://sms.tencentcloudapi.com', 'auth_type' => 'SIGNATURE', 'status' => 'INACTIVE', ], [ 'name' => '支付宝支付', 'code' => 'alipay', 'type' => 'PAYMENT', 'provider' => 'ALIPAY', 'description' => '支付宝开放平台支付服务', 'base_url' => 'https://openapi.alipay.com/gateway.do', 'auth_type' => 'SIGNATURE', 'status' => 'INACTIVE', ], [ 'name' => '微信支付', 'code' => 'wechat_pay', 'type' => 'PAYMENT', 'provider' => 'WECHAT', 'description' => '微信支付API服务', 'base_url' => 'https://api.mch.weixin.qq.com', 'auth_type' => 'SIGNATURE', 'status' => 'INACTIVE', ], ]; } /** * 显示将要同步的服务 * * @param array $services * @return void */ protected function displayServicesToSync(array $services): void { $this->info("\n将要同步的服务:"); $this->line(str_repeat('-', 80)); $headers = ['名称', '代码', '类型', '提供商', '状态']; $rows = []; foreach ($services as $service) { $rows[] = [ $service['name'], $service['code'], $service['type'], $service['provider'], $service['status'] ?? 'INACTIVE', ]; } $this->table($headers, $rows); } /** * 同步服务 * * @param array $services * @return array */ protected function syncServices(array $services): array { $results = [ 'created' => [], 'updated' => [], 'skipped' => [], 'failed' => [], ]; $progressBar = $this->output->createProgressBar(count($services)); $progressBar->start(); foreach ($services as $serviceConfig) { try { $result = $this->syncSingleService($serviceConfig); $results[$result['action']][] = $result; $this->line("\n{$result['action']}: {$serviceConfig['name']}"); } catch (\Exception $e) { $results['failed'][] = [ 'service' => $serviceConfig, 'error' => $e->getMessage(), ]; $this->line("\n失败: {$serviceConfig['name']}: {$e->getMessage()}"); } $progressBar->advance(); } $progressBar->finish(); $this->line(''); return $results; } /** * 同步单个服务 * * @param array $serviceConfig * @return array */ protected function syncSingleService(array $serviceConfig): array { // 验证配置 $this->validateServiceConfig($serviceConfig); $existingService = ThirdPartyService::where('code', $serviceConfig['code'])->first(); if ($existingService) { if ($this->option('force')) { // 更新现有服务 $existingService->update($serviceConfig); return [ 'action' => 'updated', 'service' => $existingService, ]; } else { // 跳过现有服务 return [ 'action' => 'skipped', 'service' => $existingService, 'reason' => '服务已存在', ]; } } else { // 创建新服务 $service = ThirdPartyService::create($serviceConfig); return [ 'action' => 'created', 'service' => $service, ]; } } /** * 验证服务配置 * * @param array $config * @return void * @throws \Exception */ protected function validateServiceConfig(array $config): void { $required = ['name', 'code', 'type', 'provider', 'auth_type']; foreach ($required as $field) { if (empty($config[$field])) { throw new \Exception("服务配置缺少必填字段: {$field}"); } } // 验证服务类型 if (!SERVICE_TYPE::tryFrom($config['type'])) { throw new \Exception("无效的服务类型: {$config['type']}"); } // 验证认证类型 if (!AUTH_TYPE::tryFrom($config['auth_type'])) { throw new \Exception("无效的认证类型: {$config['auth_type']}"); } // 验证URL格式 if (isset($config['base_url']) && !filter_var($config['base_url'], FILTER_VALIDATE_URL)) { throw new \Exception("无效的基础URL: {$config['base_url']}"); } } /** * 显示同步结果 * * @param array $results * @return void */ protected function displayResults(array $results): void { $this->line(str_repeat('-', 80)); $this->info('同步结果:'); $created = count($results['created']); $updated = count($results['updated']); $skipped = count($results['skipped']); $failed = count($results['failed']); $this->line("创建: {$created}"); $this->line("更新: {$updated}"); $this->line("跳过: {$skipped}"); $this->line("失败: {$failed}"); // 显示失败的详情 if ($failed > 0) { $this->line(''); $this->error('失败的服务:'); foreach ($results['failed'] as $failure) { $this->line("- {$failure['service']['name']}: {$failure['error']}"); } } // 显示跳过的详情 if ($skipped > 0 && !$this->option('force')) { $this->line(''); $this->warn('跳过的服务 (使用 --force 强制更新):'); foreach ($results['skipped'] as $skipped) { $this->line("- {$skipped['service']['name']}: {$skipped['reason']}"); } } } /** * 生成示例配置文件 * * @return void */ protected function generateExampleConfig(): void { $config = [ 'services' => $this->getDefaultServicesConfig() ]; $configPath = storage_path('app/thirdparty_services_example.json'); file_put_contents($configPath, json_encode($config, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE)); $this->info("示例配置文件已生成: {$configPath}"); } }