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}");
}
}