login('demo', 'secret123'); // 返回 ['code'=>0, ...] * $client->setToken($res['data']['token']); * $licenses = $client->licenses(['status' => 'usable']); * * 所有方法都返回接口原始数组:['code' => 0, 'message' => 'ok', 'data' => ...] * 业务失败时 code 非 0,不会抛异常;网络/HTTP 异常抛 RuntimeException。 */ class IdcgoAccountClient { public const DEFAULT_BASE = 'https://api.idcxb.com/api/v1/account'; private string $base; private ?string $token; public function __construct(?string $token = null, string $base = self::DEFAULT_BASE) { $this->token = $token; $this->base = rtrim($base, '/'); } public function setToken(?string $token): self { $this->token = $token; return $this; } public function token(): ?string { return $this->token; } /** * 发请求。 * * @param array $query * @param array|null $body * @return array */ public function request(string $method, string $path, array $query = [], ?array $body = null): array { $url = $this->base . '/' . ltrim($path, '/'); if ($query !== []) { $url .= '?' . http_build_query($query); } $ch = curl_init($url); $headers = ['Accept: application/json']; if ($this->token) { $headers[] = 'Authorization: Bearer ' . $this->token; } if ($body !== null) { $headers[] = 'Content-Type: application/json'; curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($body, JSON_UNESCAPED_UNICODE)); } curl_setopt_array($ch, [ CURLOPT_CUSTOMREQUEST => strtoupper($method), CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => $headers, CURLOPT_TIMEOUT => 20, CURLOPT_CONNECTTIMEOUT => 8, ]); $raw = curl_exec($ch); $err = curl_error($ch); $status = (int) curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); if ($raw === false || $err !== '') { throw new RuntimeException('请求失败:' . $err); } $json = json_decode((string) $raw, true); if (! is_array($json)) { throw new RuntimeException('响应不是合法 JSON(HTTP ' . $status . '):' . substr((string) $raw, 0, 200)); } $json['http_status'] = $status; return $json; } // ------------------------------------------------------------------ // 账号 // ------------------------------------------------------------------ public function register(string $username, string $email, string $password): array { return $this->request('POST', 'auth/register', [], [ 'username' => $username, 'email' => $email, 'password' => $password, 'password_confirmation' => $password, ]); } public function check(array $query): array { return $this->request('GET', 'auth/check', $query); } public function login(string $account, string $password): array { return $this->request('POST', 'auth/login', [], [ 'account' => $account, 'password' => $password, ]); } public function logout(): array { return $this->request('POST', 'auth/logout'); } public function forgotPassword(string $account): array { return $this->request('POST', 'auth/password/forgot', [], ['account' => $account]); } public function resetPassword(string $account, string $code, string $password): array { return $this->request('POST', 'auth/password/reset', [], [ 'account' => $account, 'code' => $code, 'password' => $password, 'password_confirmation' => $password, ]); } public function me(): array { return $this->request('GET', 'me'); } public function updateProfile(string $nickname, string $email, ?string $phone = null): array { return $this->request('PUT', 'me', [], [ 'nickname' => $nickname, 'email' => $email, 'phone' => $phone, ]); } public function changeUsername(string $username, string $password): array { return $this->request('PUT', 'me/username', [], [ 'username' => $username, 'password' => $password, ]); } public function changePassword(string $current, string $password): array { return $this->request('PUT', 'me/password', [], [ 'current_password' => $current, 'password' => $password, 'password_confirmation' => $password, ]); } public function resetToken(): array { $res = $this->request('POST', 'me/token'); if (($res['code'] ?? null) === 0 && ! empty($res['data']['token'])) { $this->setToken($res['data']['token']); } return $res; } // ------------------------------------------------------------------ // 概览 / 日志 // ------------------------------------------------------------------ public function dashboard(): array { return $this->request('GET', 'dashboard'); } public function logs(array $query = []): array { return $this->request('GET', 'logs', $query); } // ------------------------------------------------------------------ // 授权 // ------------------------------------------------------------------ public function licenses(array $query = []): array { return $this->request('GET', 'licenses', $query); } public function license(string $key): array { return $this->request('GET', 'licenses/' . rawurlencode($key)); } public function claim(string $key): array { return $this->request('POST', 'licenses/claim', [], ['license_key' => $key]); } public function bind(string $key, string $domain, ?string $ip = null): array { return $this->request('POST', 'licenses/' . rawurlencode($key) . '/bind', [], [ 'domain' => $domain, 'ip' => $ip, ]); } public function detectIp(string $key, string $domain): array { return $this->request('POST', 'licenses/' . rawurlencode($key) . '/detect-ip', [], ['domain' => $domain]); } public function activations(string $key): array { return $this->request('GET', 'licenses/' . rawurlencode($key) . '/activations'); } public function unbind(string $key, int $activationId): array { return $this->request('DELETE', 'licenses/' . rawurlencode($key) . '/activations/' . $activationId); } public function licenseLogs(string $key, array $query = []): array { return $this->request('GET', 'licenses/' . rawurlencode($key) . '/logs', $query); } // ------------------------------------------------------------------ // 开发者 // ------------------------------------------------------------------ public function developer(): array { return $this->request('GET', 'developer'); } public function applyDeveloper(array $payload): array { return $this->request('POST', 'developer/apply', [], $payload); } public function apps(): array { return $this->request('GET', 'developer/apps'); } public function createApp(array $payload): array { return $this->request('POST', 'developer/apps', [], $payload); } public function updateApp(int $id, array $payload): array { return $this->request('PUT', 'developer/apps/' . $id, [], $payload); } public function submitApp(int $id): array { return $this->request('POST', 'developer/apps/' . $id . '/submit'); } public function deleteApp(int $id): array { return $this->request('DELETE', 'developer/apps/' . $id); } }