client = $client; $this->setParams($params); $this->manager = $manager; } public function getParam($name) { if (in_array($name, $this->paramList)) { return $this->$name; } } public function setParam($name, $value) { if (in_array($name, $this->paramList)) { $methodName = 'set' . ucfirst($name); if (method_exists($this->client, $methodName)) { $this->client->$methodName($value); } $this->$name = $value; } } public function setParams(array $params) { foreach ($this->paramList as $name) { if (!empty($params[$name])) { $this->setParam($name, $params[$name]); } } } protected function afterTokenRefreshed($data) { if ($this->manager) { $this->manager->storeAccessToken(spl_object_hash($this), $data); } } public function getAccessTokenFromAuthorizationCode($code) { $r = $this->client->getAccessToken($this->getParam('tokenEndpoint'), Client::GRANT_TYPE_AUTHORIZATION_CODE, array( 'code' => $code, 'redirect_uri' => $this->getParam('redirectUri') )); if ($r['code'] == 200) { $data = array(); if (!empty($r['result'])) { $data['accessToken'] = $r['result']['access_token']; $data['tokenType'] = $r['result']['token_type']; $data['refreshToken'] = $r['result']['refresh_token']; } return $data; } return null; } abstract protected function getPingUrl(); public function ping() { if (empty($this->accessToken) || empty($this->clientId) || empty($this->clientSecret)) { return false; } $url = $this->getPingUrl(); try { $this->request($url); return true; } catch (\Exception $e) { return false; } } public function request($url, $params = null, $httpMethod = Client::HTTP_METHOD_GET, $contentType = null, $allowRenew = true) { $httpHeaders = array(); if (!empty($contentType)) { $httpHeaders['Content-Type'] = $contentType; switch ($contentType) { case Client::CONTENT_TYPE_MULTIPART_FORM_DATA: $httpHeaders['Content-Length'] = strlen($params); break; case Client::CONTENT_TYPE_APPLICATION_JSON: $httpHeaders['Content-Length'] = strlen($params); break; } } $r = $this->client->request($url, $params, $httpMethod, $httpHeaders); $code = null; if (!empty($r['code'])) { $code = $r['code']; } if ($code >= 200 && $code < 300) { return $r['result']; } else { $handledData = $this->handleErrorResponse($r); if ($allowRenew && is_array($handledData)) { if ($handledData['action'] == 'refreshToken') { if ($this->refreshToken()) { return $this->request($url, $params, $httpMethod, $contentType, false); } } else if ($handledData['action'] == 'renew') { return $this->request($url, $params, $httpMethod, $contentType, false); } } } throw new Error("Error after requesting {$httpMethod} {$url}.", $code); } protected function refreshToken() { if (!empty($this->refreshToken)) { $r = $this->client->getAccessToken($this->getParam('tokenEndpoint'), Client::GRANT_TYPE_REFRESH_TOKEN, array( 'refresh_token' => $this->refreshToken, )); if ($r['code'] == 200) { if (is_array($r['result'])) { if (!empty($r['result']['access_token'])) { $data = array(); $data['accessToken'] = $r['result']['access_token']; $data['tokenType'] = $r['result']['token_type']; $this->setParams($data); $this->afterTokenRefreshed($data); return true; } } } } } protected function handleErrorResponse($r) { if ($r['code'] == 401 && !empty($r['result'])) { $result = $r['result']; if (strpos($r['header'], 'error=invalid_token') !== false) { return array( 'action' => 'refreshToken' ); } else { return array( 'action' => 'renew' ); } } else if ($r['code'] == 400 && !empty($r['result'])) { if ($r['result']['error'] == 'invalid_token') { return array( 'action' => 'refreshToken' ); } } } }