Completed
Push — master ( 3150c4...4cbb1c )
by
unknown
02:06
created

src/WooCommerce/HttpClient/OAuth.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/**
3
 * WooCommerce oAuth1.0
4
 *
5
 * @category HttpClient
6
 * @package  Automattic/WooCommerce
7
 */
8
9
namespace Automattic\WooCommerce\HttpClient;
10
11
/**
12
 * oAuth1.0 class.
13
 *
14
 * @package Automattic/WooCommerce
15
 */
16
class OAuth
17
{
18
19
    /**
20
     * OAuth signature method algorithm.
21
     */
22
    const HASH_ALGORITHM = 'SHA256';
23
24
    /**
25
     * API endpoint URL.
26
     *
27
     * @var string
28
     */
29
    protected $url;
30
31
    /**
32
     * Consumer key.
33
     *
34
     * @var string
35
     */
36
    protected $consumerKey;
37
38
    /**
39
     * Consumer secret.
40
     *
41
     * @var string
42
     */
43
    protected $consumerSecret;
44
45
    /**
46
     * API version.
47
     *
48
     * @var array
49
     */
50
    protected $apiVersion;
51
52
    /**
53
     * Request method.
54
     *
55
     * @var string
56
     */
57
    protected $method;
58
59
    /**
60
     * Request parameters.
61
     *
62
     * @var array
63
     */
64
    protected $parameters;
65
66
    /**
67
     * Timestamp.
68
     *
69
     * @var string
70
     */
71
    protected $timestamp;
72
73
    /**
74
     * Initialize oAuth class.
75
     *
76
     * @param string $url            Store URL.
77
     * @param string $consumerKey    Consumer key.
78
     * @param string $consumerSecret Consumer Secret.
79
     * @param string $method         Request method.
80
     * @param string $apiVersion     API version.
81
     * @param array  $parameters     Request parameters.
82
     * @param string $timestamp      Timestamp.
83
     */
84
    public function __construct($url, $consumerKey, $consumerSecret, $apiVersion, $method, $parameters = [], $timestamp = '')
85
    {
86
        $this->url            = $url;
87
        $this->consumerKey    = $consumerKey;
88
        $this->consumerSecret = $consumerSecret;
89
        $this->apiVersion     = $apiVersion;
0 ignored issues
show
Documentation Bug introduced by
It seems like $apiVersion of type string is incompatible with the declared type array of property $apiVersion.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
90
        $this->method         = $method;
91
        $this->parameters     = $parameters;
92
        $this->timestamp      = $timestamp;
93
    }
94
95
    /**
96
     * Normalize strings.
97
     *
98
     * @param string $string String to be normalized.
99
     *
100
     * @return string
101
     */
102
    protected function normalizeString($string)
103
    {
104
        return \str_replace('%', '%25', \rawurlencode(\rawurldecode($string)));
105
    }
106
107
    /**
108
     * Normalize parameters.
109
     *
110
     * @param array $parameters Parameters to normalize.
111
     *
112
     * @return array
113
     */
114
    protected function normalizeParameters($parameters)
115
    {
116
        $normalized = [];
117
118
        foreach ($parameters as $key => $value) {
119
            // Percent symbols (%) must be double-encoded.
120
            $key   = $this->normalizeString($key);
121
            $value = $this->normalizeString($value);
122
123
            $normalized[$key] = $value;
124
        }
125
126
        return $normalized;
127
    }
128
129
    /**
130
     * Process filters.
131
     *
132
     * @param array $parameters Request parameters.
133
     *
134
     * @return array
135
     */
136
    protected function processFilters($parameters)
137
    {
138
        if (isset($parameters['filter'])) {
139
            $filters = $parameters['filter'];
140
            unset($parameters['filter']);
141
            foreach ($filters as $filter => $value) {
142
                $parameters['filter[' . $filter . ']'] = $value;
143
            }
144
        }
145
146
        return $parameters;
147
    }
148
149
    /**
150
     * Get secret.
151
     *
152
     * @return string
153
     */
154
    protected function getSecret()
155
    {
156
        $secret = $this->consumerSecret;
157
158
        // Fix secret for v3 or later.
159
        if (!\in_array($this->apiVersion, ['v1', 'v2'])) {
160
            $secret .= '&';
161
        }
162
163
        return $secret;
164
    }
165
166
    /**
167
     * Generate oAuth1.0 signature.
168
     *
169
     * @param array $parameters Request parameters including oauth.
170
     *
171
     * @return string
172
     */
173
    protected function generateOauthSignature($parameters)
174
    {
175
        $baseRequestUri = \rawurlencode($this->url);
176
177
        // Extract filters.
178
        $parameters = $this->processFilters($parameters);
179
180
        // Normalize parameter key/values and sort them.
181
        $parameters = $this->normalizeParameters($parameters);
182
        \uksort($parameters, 'strcmp');
183
184
        // Set query string.
185
        $query = [];
186
        foreach ($parameters as $key => $value) {
187
            $query[] = $key . '%3D' . $value; // Join with equals sign.
188
        }
189
190
        $queryString  = \implode('%26', $query); // Join with ampersand.
191
        $stringToSign = $this->method . '&' . $baseRequestUri . '&' . $queryString;
192
        $secret       = $this->getSecret();
193
194
        return \base64_encode(\hash_hmac(self::HASH_ALGORITHM, $stringToSign, $secret, true));
195
    }
196
197
    /**
198
     * Sort parameters.
199
     *
200
     * @param array $parameters Parameters to sort in byte-order.
201
     *
202
     * @return array
203
     */
204
    protected function getSortedParameters($parameters)
205
    {
206
        \uksort($parameters, 'strcmp');
207
208
        foreach ($parameters as $key => $value) {
209
            if (\is_array($value)) {
210
                \uksort($parameters[$key], 'strcmp');
211
            }
212
        }
213
214
        return $parameters;
215
    }
216
217
    /**
218
     * Get oAuth1.0 parameters.
219
     *
220
     * @return string
221
     */
222
    public function getParameters()
223
    {
224
        $parameters = \array_merge($this->parameters, [
225
            'oauth_consumer_key'     => $this->consumerKey,
226
            'oauth_timestamp'        => $this->timestamp,
227
            'oauth_nonce'            => \sha1(\microtime()),
228
            'oauth_signature_method' => 'HMAC-' . self::HASH_ALGORITHM,
229
        ]);
230
231
        // The parameters above must be included in the signature generation.
232
        $parameters['oauth_signature'] = $this->generateOauthSignature($parameters);
233
234
        return $this->getSortedParameters($parameters);
235
    }
236
}
237