• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

stripe / stripe-php / #7087

pending completion
#7087

push

php-coveralls

pakrym-stripe
Bump version to 10.14.0-beta.2

1831 of 2732 relevant lines covered (67.02%)

3.81 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

77.67
/lib/BaseStripeClient.php
1
<?php
2

3
namespace Stripe;
4

5
class BaseStripeClient implements StripeClientInterface, StripeStreamingClientInterface
6
{
7
    /** @var string default base URL for Stripe's API */
8
    const DEFAULT_API_BASE = 'https://api.stripe.com';
9

10
    /** @var string default base URL for Stripe's OAuth API */
11
    const DEFAULT_CONNECT_BASE = 'https://connect.stripe.com';
12

13
    /** @var string default base URL for Stripe's Files API */
14
    const DEFAULT_FILES_BASE = 'https://files.stripe.com';
15

16
    /** @var array<string, mixed> */
17
    private $config;
18

19
    /** @var \Stripe\Util\RequestOptions */
20
    private $defaultOpts;
21

22
    /** @var \Stripe\Preview */
23
    public $preview;
24

25
    /**
26
     * Initializes a new instance of the {@link BaseStripeClient} class.
27
     *
28
     * The constructor takes a single argument. The argument can be a string, in which case it
29
     * should be the API key. It can also be an array with various configuration settings.
30
     *
31
     * Configuration settings include the following options:
32
     *
33
     * - api_key (null|string): the Stripe API key, to be used in regular API requests.
34
     * - client_id (null|string): the Stripe client ID, to be used in OAuth requests.
35
     * - stripe_account (null|string): a Stripe account ID. If set, all requests sent by the client
36
     *   will automatically use the {@code Stripe-Account} header with that account ID.
37
     * - stripe_version (null|string): a Stripe API verion. If set, all requests sent by the client
38
     *   will include the {@code Stripe-Version} header with that API version.
39
     *
40
     * The following configuration settings are also available, though setting these should rarely be necessary
41
     * (only useful if you want to send requests to a mock server like stripe-mock):
42
     *
43
     * - api_base (string): the base URL for regular API requests. Defaults to
44
     *   {@link DEFAULT_API_BASE}.
45
     * - connect_base (string): the base URL for OAuth requests. Defaults to
46
     *   {@link DEFAULT_CONNECT_BASE}.
47
     * - files_base (string): the base URL for file creation requests. Defaults to
48
     *   {@link DEFAULT_FILES_BASE}.
49
     *
50
     * @param array<string, mixed>|string $config the API key as a string, or an array containing
51
     *   the client configuration settings
52
     */
53
    public function __construct($config = [])
54
    {
55
        if (\is_string($config)) {
24✔
56
            $config = ['api_key' => $config];
2✔
57
        } elseif (!\is_array($config)) {
22✔
58
            throw new \Stripe\Exception\InvalidArgumentException('$config must be a string or an array');
1✔
59
        }
60

61
        $config = \array_merge($this->getDefaultConfig(), $config);
23✔
62
        $this->validateConfig($config);
23✔
63

64
        $this->config = $config;
19✔
65

66
        $this->defaultOpts = \Stripe\Util\RequestOptions::parse([
19✔
67
            'stripe_account' => $config['stripe_account'],
19✔
68
            'stripe_version' => $config['stripe_version'],
19✔
69
        ]);
19✔
70

71
        $this->preview = new Preview($this);
19✔
72
    }
73

74
    /**
75
     * Gets the API key used by the client to send requests.
76
     *
77
     * @return null|string the API key used by the client to send requests
78
     */
79
    public function getApiKey()
80
    {
81
        return $this->config['api_key'];
15✔
82
    }
83

84
    /**
85
     * Gets the client ID used by the client in OAuth requests.
86
     *
87
     * @return null|string the client ID used by the client in OAuth requests
88
     */
89
    public function getClientId()
90
    {
91
        return $this->config['client_id'];
×
92
    }
93

94
    /**
95
     * Gets the base URL for Stripe's API.
96
     *
97
     * @return string the base URL for Stripe's API
98
     */
99
    public function getApiBase()
100
    {
101
        return $this->config['api_base'];
15✔
102
    }
103

104
    /**
105
     * Gets the base URL for Stripe's OAuth API.
106
     *
107
     * @return string the base URL for Stripe's OAuth API
108
     */
109
    public function getConnectBase()
110
    {
111
        return $this->config['connect_base'];
×
112
    }
113

114
    /**
115
     * Gets the base URL for Stripe's Files API.
116
     *
117
     * @return string the base URL for Stripe's Files API
118
     */
119
    public function getFilesBase()
120
    {
121
        return $this->config['files_base'];
×
122
    }
123

124
    /**
125
     * Sends a request to Stripe's API.
126
     *
127
     * @param 'delete'|'get'|'post' $method the HTTP method
128
     * @param string $path the path of the request
129
     * @param array $params the parameters of the request
130
     * @param array|\Stripe\Util\RequestOptions $opts the special modifiers of the request
131
     *
132
     * @return \Stripe\StripeObject the object returned by Stripe's API
133
     */
134
    public function request($method, $path, $params, $opts)
135
    {
136
        $opts = $this->defaultOpts->merge($opts, true);
12✔
137
        $baseUrl = $opts->apiBase ?: $this->getApiBase();
10✔
138
        $requestor = new \Stripe\ApiRequestor($this->apiKeyForRequest($opts), $baseUrl);
10✔
139
        list($response, $opts->apiKey) = $requestor->request($method, $path, $params, $opts->headers);
9✔
140
        $opts->discardNonPersistentHeaders();
8✔
141
        $obj = \Stripe\Util\Util::convertToStripeObject($response->json, $opts);
8✔
142
        $obj->setLastResponse($response);
8✔
143

144
        return $obj;
8✔
145
    }
146

147
    /**
148
     * Sends a raw request to Stripe's API. This is the lowest level method for interacting
149
     * with the Stripe API. This method is useful for interacting with endpoints that are not
150
     * covered yet in stripe-php.
151
     *
152
     * @param 'delete'|'get'|'post' $method the HTTP method
153
     * @param string $path the path of the request
154
     * @param array $params the parameters of the request
155
     * @param array $opts the special modifiers of the request
156
     *
157
     * @return \Stripe\ApiResponse
158
     */
159
    public function rawRequest($method, $path, $params, $opts)
160
    {
161
        if ('post' !== $method && null !== $params) {
6✔
162
            throw new Exception\InvalidArgumentException('Error: rawRequest only supports $params on post requests. Please pass null and add your parameters to $path');
1✔
163
        }
164
        $apiMode = 'standard';
5✔
165
        $headers = [];
5✔
166
        if (\is_array($opts) && \array_key_exists('api_mode', $opts)) {
5✔
167
            $apiMode = $opts['api_mode'];
4✔
168
            unset($opts['api_mode']);
4✔
169
        }
170
        if (\is_array($opts) && \array_key_exists('headers', $opts)) {
5✔
171
            $headers = $opts['headers'] ?: [];
×
172
            unset($opts['headers']);
×
173
        }
174
        if (\is_array($opts) && \array_key_exists('stripe_context', $opts)) {
5✔
175
            $headers['Stripe-Context'] = $opts['stripe_context'];
1✔
176
            unset($opts['stripe_context']);
1✔
177
        }
178
        $opts = $this->defaultOpts->merge($opts, true);
5✔
179
        // Concatenate $headers to $opts->headers, removing duplicates.
180
        $opts->headers = \array_merge($opts->headers, $headers);
5✔
181
        $baseUrl = $opts->apiBase ?: $this->getApiBase();
5✔
182
        $requestor = new \Stripe\ApiRequestor($this->apiKeyForRequest($opts), $baseUrl);
5✔
183
        list($response) = $requestor->request($method, $path, $params, $opts->headers, $apiMode);
5✔
184

185
        return $response;
5✔
186
    }
187

188
    /**
189
     * Sends a request to Stripe's API, passing chunks of the streamed response
190
     * into a user-provided $readBodyChunkCallable callback.
191
     *
192
     * @param 'delete'|'get'|'post' $method the HTTP method
193
     * @param string $path the path of the request
194
     * @param callable $readBodyChunkCallable a function that will be called
195
     * @param array $params the parameters of the request
196
     * @param array|\Stripe\Util\RequestOptions $opts the special modifiers of the request
197
     * with chunks of bytes from the body if the request is successful
198
     */
199
    public function requestStream($method, $path, $readBodyChunkCallable, $params, $opts)
200
    {
201
        $opts = $this->defaultOpts->merge($opts, true);
×
202
        $baseUrl = $opts->apiBase ?: $this->getApiBase();
×
203
        $requestor = new \Stripe\ApiRequestor($this->apiKeyForRequest($opts), $baseUrl);
×
204
        list($response, $opts->apiKey) = $requestor->requestStream($method, $path, $readBodyChunkCallable, $params, $opts->headers);
×
205
    }
206

207
    /**
208
     * Sends a request to Stripe's API.
209
     *
210
     * @param 'delete'|'get'|'post' $method the HTTP method
211
     * @param string $path the path of the request
212
     * @param array $params the parameters of the request
213
     * @param array|\Stripe\Util\RequestOptions $opts the special modifiers of the request
214
     *
215
     * @return \Stripe\Collection of ApiResources
216
     */
217
    public function requestCollection($method, $path, $params, $opts)
218
    {
219
        $obj = $this->request($method, $path, $params, $opts);
2✔
220
        if (!($obj instanceof \Stripe\Collection)) {
2✔
221
            $received_class = \get_class($obj);
1✔
222
            $msg = "Expected to receive `Stripe\\Collection` object from Stripe API. Instead received `{$received_class}`.";
1✔
223

224
            throw new \Stripe\Exception\UnexpectedValueException($msg);
1✔
225
        }
226
        $obj->setFilters($params);
1✔
227

228
        return $obj;
1✔
229
    }
230

231
    /**
232
     * Sends a request to Stripe's API.
233
     *
234
     * @param 'delete'|'get'|'post' $method the HTTP method
235
     * @param string $path the path of the request
236
     * @param array $params the parameters of the request
237
     * @param array|\Stripe\Util\RequestOptions $opts the special modifiers of the request
238
     *
239
     * @return \Stripe\SearchResult of ApiResources
240
     */
241
    public function requestSearchResult($method, $path, $params, $opts)
242
    {
243
        $obj = $this->request($method, $path, $params, $opts);
×
244
        if (!($obj instanceof \Stripe\SearchResult)) {
×
245
            $received_class = \get_class($obj);
×
246
            $msg = "Expected to receive `Stripe\\SearchResult` object from Stripe API. Instead received `{$received_class}`.";
×
247

248
            throw new \Stripe\Exception\UnexpectedValueException($msg);
×
249
        }
250
        $obj->setFilters($params);
×
251

252
        return $obj;
×
253
    }
254

255
    /**
256
     * @param \Stripe\Util\RequestOptions $opts
257
     *
258
     * @throws \Stripe\Exception\AuthenticationException
259
     *
260
     * @return string
261
     */
262
    private function apiKeyForRequest($opts)
263
    {
264
        $apiKey = $opts->apiKey ?: $this->getApiKey();
15✔
265

266
        if (null === $apiKey) {
15✔
267
            $msg = 'No API key provided. Set your API key when constructing the '
1✔
268
                . 'StripeClient instance, or provide it on a per-request basis '
1✔
269
                . 'using the `api_key` key in the $opts argument.';
1✔
270

271
            throw new \Stripe\Exception\AuthenticationException($msg);
1✔
272
        }
273

274
        return $apiKey;
14✔
275
    }
276

277
    /**
278
     * TODO: replace this with a private constant when we drop support for PHP < 5.
279
     *
280
     * @return array<string, mixed>
281
     */
282
    private function getDefaultConfig()
283
    {
284
        return [
23✔
285
            'api_key' => null,
23✔
286
            'client_id' => null,
23✔
287
            'stripe_account' => null,
23✔
288
            'stripe_version' => null,
23✔
289
            'api_base' => self::DEFAULT_API_BASE,
23✔
290
            'connect_base' => self::DEFAULT_CONNECT_BASE,
23✔
291
            'files_base' => self::DEFAULT_FILES_BASE,
23✔
292
        ];
23✔
293
    }
294

295
    /**
296
     * @param array<string, mixed> $config
297
     *
298
     * @throws \Stripe\Exception\InvalidArgumentException
299
     */
300
    private function validateConfig($config)
301
    {
302
        // api_key
303
        if (null !== $config['api_key'] && !\is_string($config['api_key'])) {
23✔
304
            throw new \Stripe\Exception\InvalidArgumentException('api_key must be null or a string');
1✔
305
        }
306

307
        if (null !== $config['api_key'] && ('' === $config['api_key'])) {
22✔
308
            $msg = 'api_key cannot be the empty string';
1✔
309

310
            throw new \Stripe\Exception\InvalidArgumentException($msg);
1✔
311
        }
312

313
        if (null !== $config['api_key'] && (\preg_match('/\s/', $config['api_key']))) {
21✔
314
            $msg = 'api_key cannot contain whitespace';
1✔
315

316
            throw new \Stripe\Exception\InvalidArgumentException($msg);
1✔
317
        }
318

319
        // client_id
320
        if (null !== $config['client_id'] && !\is_string($config['client_id'])) {
20✔
321
            throw new \Stripe\Exception\InvalidArgumentException('client_id must be null or a string');
×
322
        }
323

324
        // stripe_account
325
        if (null !== $config['stripe_account'] && !\is_string($config['stripe_account'])) {
20✔
326
            throw new \Stripe\Exception\InvalidArgumentException('stripe_account must be null or a string');
×
327
        }
328

329
        // stripe_version
330
        if (null !== $config['stripe_version'] && !\is_string($config['stripe_version'])) {
20✔
331
            throw new \Stripe\Exception\InvalidArgumentException('stripe_version must be null or a string');
×
332
        }
333

334
        // api_base
335
        if (!\is_string($config['api_base'])) {
20✔
336
            throw new \Stripe\Exception\InvalidArgumentException('api_base must be a string');
×
337
        }
338

339
        // connect_base
340
        if (!\is_string($config['connect_base'])) {
20✔
341
            throw new \Stripe\Exception\InvalidArgumentException('connect_base must be a string');
×
342
        }
343

344
        // files_base
345
        if (!\is_string($config['files_base'])) {
20✔
346
            throw new \Stripe\Exception\InvalidArgumentException('files_base must be a string');
×
347
        }
348

349
        // check absence of extra keys
350
        $extraConfigKeys = \array_diff(\array_keys($config), \array_keys($this->getDefaultConfig()));
20✔
351
        if (!empty($extraConfigKeys)) {
20✔
352
            // Wrap in single quote to more easily catch trailing spaces errors
353
            $invalidKeys = "'" . \implode("', '", $extraConfigKeys) . "'";
1✔
354

355
            throw new \Stripe\Exception\InvalidArgumentException('Found unknown key(s) in configuration array: ' . $invalidKeys);
1✔
356
        }
357
    }
358

359
    /**
360
     * Deserializes the raw JSON string returned by rawRequest into a similar class.
361
     *
362
     * @param string $json
363
     *
364
     * @return \Stripe\StripeObject
365
     * */
366
    public function deserialize($json)
367
    {
368
        return \Stripe\Util\Util::convertToStripeObject(\json_decode($json, true), []);
×
369
    }
370
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc