getConfig()->has('base_url')) { $this->baseUrl = $this->getConfig()->get('base_url'); } if ($this->getConfig()->has('agent_id')) { $this->agentId = $this->getConfig()->get('agent_id'); } } public function getBaseUrl(): ?string { return $this->baseUrl; } public function userFromCode(string $code): Contracts\UserInterface { $token = $this->getApiAccessToken(); $user = $this->getUser($token, $code); if ($this->detailed) { $user = $this->getUserById($user['UserId']); } return $this->mapUserToObject($user)->setProvider($this)->setRaw($user); } public function withAgentId(int $agentId): self { $this->agentId = $agentId; return $this; } public function detailed(): self { $this->detailed = true; return $this; } public function asQrcode(): self { $this->asQrcode = true; return $this; } public function withApiAccessToken(string $apiAccessToken): self { $this->apiAccessToken = $apiAccessToken; return $this; } public function getAuthUrl(): string { $scopes = $this->formatScopes($this->scopes, $this->scopeSeparator); $queries = array_filter([ 'appid' => $this->getClientId(), 'agentid' => $this->agentId, Contracts\RFC6749_ABNF_REDIRECT_URI => $this->redirectUrl, Contracts\RFC6749_ABNF_RESPONSE_TYPE => Contracts\RFC6749_ABNF_CODE, Contracts\RFC6749_ABNF_SCOPE => $scopes, Contracts\RFC6749_ABNF_STATE => $this->state, ]); if (! $this->agentId && (str_contains($scopes, 'snsapi_privateinfo') || $this->asQrcode)) { throw new Exceptions\InvalidArgumentException("agent_id is require when qrcode mode or scopes is 'snsapi_privateinfo'"); } if ($this->asQrcode) { unset($queries[Contracts\RFC6749_ABNF_SCOPE]); return \sprintf('https://open.work.weixin.qq.com/wwopen/sso/qrConnect?%s', http_build_query($queries)); } return \sprintf('https://open.weixin.qq.com/connect/oauth2/authorize?%s#wechat_redirect', \http_build_query($queries)); } /** * @throws Exceptions\MethodDoesNotSupportException */ protected function getUserByToken(string $token): array { throw new Exceptions\MethodDoesNotSupportException('WeWork doesn\'t support access_token mode'); } protected function getApiAccessToken(): string { return $this->apiAccessToken ?? $this->apiAccessToken = $this->requestApiAccessToken(); } protected function getUser(string $token, string $code): array { $responseInstance = $this->getHttpClient()->get( $this->baseUrl.'/cgi-bin/user/getuserinfo', [ 'query' => \array_filter( [ Contracts\RFC6749_ABNF_ACCESS_TOKEN => $token, Contracts\RFC6749_ABNF_CODE => $code, ] ), ] ); $response = $this->fromJsonBody($responseInstance); if (($response['errcode'] ?? 1) > 0 || (empty($response['UserId']) && empty($response['OpenId']))) { throw new Exceptions\AuthorizeFailedException((string) $responseInstance->getBody(), $response); } elseif (empty($response['UserId'])) { $this->detailed = false; } return $response; } /** * @throws Exceptions\AuthorizeFailedException */ protected function getUserById(string $userId): array { $responseInstance = $this->getHttpClient()->post($this->baseUrl.'/cgi-bin/user/get', [ 'query' => [ Contracts\RFC6749_ABNF_ACCESS_TOKEN => $this->getApiAccessToken(), 'userid' => $userId, ], ]); $response = $this->fromJsonBody($responseInstance); if (($response['errcode'] ?? 1) > 0 || empty($response['userid'])) { throw new Exceptions\AuthorizeFailedException((string) $responseInstance->getBody(), $response); } return $response; } #[Pure] protected function mapUserToObject(array $user): Contracts\UserInterface { return new User($this->detailed ? [ Contracts\ABNF_ID => $user['userid'] ?? null, Contracts\ABNF_NAME => $user[Contracts\ABNF_NAME] ?? null, Contracts\ABNF_AVATAR => $user[Contracts\ABNF_AVATAR] ?? null, Contracts\ABNF_EMAIL => $user[Contracts\ABNF_EMAIL] ?? null, ] : [ Contracts\ABNF_ID => $user['UserId'] ?? null ?: $user['OpenId'] ?? null, ]); } /** * @throws Exceptions\AuthorizeFailedException */ protected function requestApiAccessToken(): string { $responseInstance = $this->getHttpClient()->get($this->baseUrl.'/cgi-bin/gettoken', [ 'query' => \array_filter( [ 'corpid' => $this->config->get('corp_id') ?? $this->config->get('corpid') ?? $this->config->get(Contracts\RFC6749_ABNF_CLIENT_ID), 'corpsecret' => $this->config->get('corp_secret') ?? $this->config->get('corpsecret') ?? $this->config->get(Contracts\RFC6749_ABNF_CLIENT_SECRET), ] ), ]); $response = $this->fromJsonBody($responseInstance); if (($response['errcode'] ?? 1) > 0) { throw new Exceptions\AuthorizeFailedException((string) $responseInstance->getBody(), $response); } return $response[Contracts\RFC6749_ABNF_ACCESS_TOKEN]; } protected function getTokenUrl(): string { return ''; } }