1<?php
2
3namespace OAuth\OAuth2\Service;
4
5use OAuth\OAuth2\Token\StdOAuth2Token;
6use OAuth\Common\Http\Exception\TokenResponseException;
7use OAuth\Common\Http\Uri\Uri;
8use OAuth\Common\Consumer\CredentialsInterface;
9use OAuth\Common\Http\Client\ClientInterface;
10use OAuth\Common\Storage\TokenStorageInterface;
11use OAuth\Common\Http\Uri\UriInterface;
12
13class Bitrix24 extends AbstractService
14{
15    const SCOPE_DEPARTMENT = 'department';
16    const SCOPE_CRM = 'crm';
17    const SCOPE_CALENDAR = 'calendar';
18    const SCOPE_USER = 'user';
19    const SCOPE_ENTITY = 'entity';
20    const SCOPE_TASK = 'task';
21    const SCOPE_TASKS_EXTENDED = 'tasks_extended';
22    const SCOPE_IM = 'im';
23    const SCOPE_LOG = 'log';
24    const SCOPE_SONET_GROUP = 'sonet_group';
25
26    /**
27     * {@inheritdoc}
28     */
29    public function getAuthorizationEndpoint()
30    {
31        return new Uri(sprintf('%s/oauth/authorize/', $this->baseApiUri));
32    }
33
34    /**
35     * {@inheritdoc}
36     */
37    public function getAccessTokenEndpoint()
38    {
39        return new Uri(sprintf('%s/oauth/token/', $this->baseApiUri));
40    }
41
42    /**
43     * {@inheritdoc}
44     */
45    protected function getAuthorizationMethod()
46    {
47        return static::AUTHORIZATION_METHOD_QUERY_STRING_V4;
48    }
49
50    /**
51     * {@inheritdoc}
52     */
53    public function requestAccessToken($code, $state = null)
54    {
55        if (null !== $state) {
56            $this->validateAuthorizationState($state);
57        }
58
59        $responseBody = $this->httpClient->retrieveResponse(
60            $this->getAccessTokenUri($code),
61            array(),
62            $this->getExtraOAuthHeaders(),
63            'GET'
64        );
65
66        $token = $this->parseAccessTokenResponse($responseBody);
67        $this->storage->storeAccessToken($this->service(), $token);
68
69        return $token;
70    }
71
72    /**
73     * {@inheritdoc}
74     */
75    public function getAccessTokenUri($code)
76    {
77        $parameters = array(
78            'code'          => $code,
79            'client_id'     => $this->credentials->getConsumerId(),
80            'client_secret' => $this->credentials->getConsumerSecret(),
81            'redirect_uri'  => $this->credentials->getCallbackUrl(),
82            'grant_type'    => 'authorization_code',
83            'scope'         => $this->scopes
84        );
85
86        $parameters['scope'] = implode(' ', $this->scopes);
87
88        // Build the url
89        $url = $this->getAccessTokenEndpoint();
90        foreach ($parameters as $key => $val) {
91            $url->addToQuery($key, $val);
92        }
93
94        return $url;
95    }
96
97    /**
98     * {@inheritdoc}
99     */
100    protected function parseAccessTokenResponse($responseBody)
101    {
102        $data = json_decode($responseBody, true);
103
104        if (null === $data || !is_array($data)) {
105            throw new TokenResponseException('Unable to parse response.');
106        } elseif (isset($data['error'])) {
107            throw new TokenResponseException('Error in retrieving token: "' . $data['error'] . '"');
108        }
109
110        $token = new StdOAuth2Token();
111        $token->setAccessToken($data['access_token']);
112        $token->setLifetime($data['expires_in']);
113
114        if (isset($data['refresh_token'])) {
115            $token->setRefreshToken($data['refresh_token']);
116            unset($data['refresh_token']);
117        }
118
119        unset($data['access_token']);
120        unset($data['expires_in']);
121
122        $token->setExtraParams($data);
123
124        return $token;
125    }
126}
127