where('config_group', self::GROUP) ->column('config_value', 'config_key'); return [ 'driver' => $this->normalizeDriver((string)($rows['driver'] ?? 'local')), 'public_base_url' => trim((string)($rows['public_base_url'] ?? '')), 'oss_endpoint' => trim((string)($rows['oss_endpoint'] ?? '')), 'oss_upload_endpoint' => trim((string)($rows['oss_upload_endpoint'] ?? '')), 'oss_bucket' => trim((string)($rows['oss_bucket'] ?? '')), 'oss_access_key_id' => trim((string)($rows['oss_access_key_id'] ?? '')), 'oss_access_key_secret' => trim((string)($rows['oss_access_key_secret'] ?? '')), 'oss_bucket_domain' => trim((string)($rows['oss_bucket_domain'] ?? '')), 'oss_path_prefix' => trim((string)($rows['oss_path_prefix'] ?? '')), 'direct_upload_max_size_mb' => trim((string)($rows['direct_upload_max_size_mb'] ?? '200')), 'qiniu_bucket' => trim((string)($rows['qiniu_bucket'] ?? '')), 'qiniu_access_key' => trim((string)($rows['qiniu_access_key'] ?? '')), 'qiniu_secret_key' => trim((string)($rows['qiniu_secret_key'] ?? '')), 'qiniu_bucket_domain' => trim((string)($rows['qiniu_bucket_domain'] ?? '')), 'qiniu_path_prefix' => trim((string)($rows['qiniu_path_prefix'] ?? '')), ]; } public function clearCache(): void { // noop; kept for call-site compatibility. } public function driver(): string { return $this->getConfig()['driver']; } public function isOss(): bool { return $this->driver() === 'oss'; } public function isQiniu(): bool { return $this->driver() === 'qiniu'; } public function assertReady(): void { if ($this->isOss()) { $config = $this->getConfig(); $requiredKeys = [ 'oss_endpoint' => 'OSS Endpoint', 'oss_bucket' => 'OSS Bucket', 'oss_access_key_id' => 'OSS AccessKey ID', 'oss_access_key_secret' => 'OSS AccessKey Secret', ]; foreach ($requiredKeys as $key => $label) { if (trim((string)($config[$key] ?? '')) === '') { throw new \RuntimeException(sprintf('%s 未配置,当前无法使用 OSS 存储', $label)); } } return; } if ($this->isQiniu()) { $config = $this->getConfig(); $requiredKeys = [ 'qiniu_bucket' => '七牛 Bucket', 'qiniu_access_key' => '七牛 AccessKey', 'qiniu_secret_key' => '七牛 SecretKey', ]; foreach ($requiredKeys as $key => $label) { if (trim((string)($config[$key] ?? '')) === '') { throw new \RuntimeException(sprintf('%s 未配置,当前无法使用七牛云存储', $label)); } } } } public function publicBaseUrl(): string { $config = $this->getConfig(); if ($config['public_base_url'] !== '') { return $this->normalizeBaseUrl($config['public_base_url']); } if ($this->isOss() && $config['oss_bucket_domain'] !== '') { return $this->normalizeBaseUrl($config['oss_bucket_domain']); } if ($this->isOss() && $config['oss_endpoint'] !== '' && $config['oss_bucket'] !== '') { return $this->normalizeBaseUrl(sprintf( 'https://%s.%s', $config['oss_bucket'], $this->normalizeEndpointHost($config['oss_endpoint']) )); } if ($this->isQiniu() && $config['qiniu_bucket_domain'] !== '') { return $this->normalizeBaseUrl($config['qiniu_bucket_domain']); } $notifyUrl = Db::name('system_configs') ->where('config_group', 'payment') ->where('config_key', 'notify_url') ->value('config_value'); if (is_string($notifyUrl) && trim($notifyUrl) !== '') { return $this->extractOrigin($notifyUrl); } return ''; } public function bucket(): string { return $this->getConfig()['oss_bucket']; } public function qiniuBucket(): string { return $this->getConfig()['qiniu_bucket']; } public function endpoint(): string { return $this->normalizeEndpointHost($this->getConfig()['oss_endpoint']); } public function uploadEndpoint(): string { $config = $this->getConfig(); $endpoint = $config['oss_upload_endpoint'] !== '' ? $config['oss_upload_endpoint'] : $config['oss_endpoint']; return $this->normalizeEndpointHost($endpoint); } public function directUploadMaxBytes(): int { $value = (int)$this->getConfig()['direct_upload_max_size_mb']; $megabytes = max(1, min(2048, $value > 0 ? $value : 200)); return $megabytes * 1024 * 1024; } public function directUploadMaxLabel(): string { return sprintf('%dMB', (int)($this->directUploadMaxBytes() / 1024 / 1024)); } public function accessKeyId(): string { return $this->getConfig()['oss_access_key_id']; } public function qiniuAccessKey(): string { return $this->getConfig()['qiniu_access_key']; } public function accessKeySecret(): string { return $this->getConfig()['oss_access_key_secret']; } public function qiniuSecretKey(): string { return $this->getConfig()['qiniu_secret_key']; } public function objectKey(string $relativePath): string { $relativePath = ltrim($relativePath, '/'); $config = $this->getConfig(); $prefix = trim((string)($this->isQiniu() ? ($config['qiniu_path_prefix'] ?? '') : ($config['oss_path_prefix'] ?? '')), '/'); if ($prefix === '') { return $relativePath; } return $prefix . '/' . $relativePath; } public function removePathPrefix(string $objectKey): string { $objectKey = ltrim($objectKey, '/'); $config = $this->getConfig(); $prefix = trim((string)($this->isQiniu() ? ($config['qiniu_path_prefix'] ?? '') : ($config['oss_path_prefix'] ?? '')), '/'); if ($prefix === '') { return $objectKey; } if (str_starts_with($objectKey, $prefix . '/')) { return substr($objectKey, strlen($prefix) + 1); } return $objectKey; } public function normalizeDriver(string $value): string { return in_array($value, ['oss', 'qiniu'], true) ? $value : 'local'; } public function normalizeBaseUrl(string $baseUrl): string { $baseUrl = trim($baseUrl); if ($baseUrl === '') { return ''; } if (!preg_match('/^https?:\/\//i', $baseUrl)) { $baseUrl = 'https://' . ltrim($baseUrl, '/'); } return rtrim($baseUrl, '/'); } private function extractOrigin(string $url): string { $parts = parse_url(trim($url)); $scheme = (string)($parts['scheme'] ?? ''); $host = (string)($parts['host'] ?? ''); $port = (string)($parts['port'] ?? ''); if ($host === '') { return $this->normalizeBaseUrl($url); } $origin = ($scheme !== '' ? $scheme : 'https') . '://' . $host; if ($port !== '' && !(($scheme === 'http' && $port === '80') || ($scheme === 'https' && $port === '443'))) { $origin .= ':' . $port; } return rtrim($origin, '/'); } public function normalizeEndpointHost(string $endpoint): string { $endpoint = trim($endpoint); if ($endpoint === '') { return ''; } if (preg_match('/^https?:\/\//i', $endpoint)) { $host = parse_url($endpoint, PHP_URL_HOST); if (is_string($host) && $host !== '') { return $host; } } return preg_replace('#^https?://#i', '', rtrim($endpoint, '/')) ?: ''; } }