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

stripe / stripe-php / 9290737472

29 May 2024 05:46PM UTC coverage: 66.176% (+0.06%) from 66.119%
9290737472

Pull #1700

github

web-flow
Merge 3ff408655 into 7038876e7
Pull Request #1700: Add optional appInfo to StripeClient config

22 of 32 new or added lines in 2 files covered. (68.75%)

1 existing line in 1 file now uncovered.

2383 of 3601 relevant lines covered (66.18%)

3.35 hits per line

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

72.04
/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, null|string> */
17
    const DEFAULT_CONFIG = [
18
        'api_key' => null,
19
        'app_info' => null,
20
        'client_id' => null,
21
        'stripe_account' => null,
22
        'stripe_version' => \Stripe\Util\ApiVersion::CURRENT,
23
        'api_base' => self::DEFAULT_API_BASE,
24
        'connect_base' => self::DEFAULT_CONNECT_BASE,
25
        'files_base' => self::DEFAULT_FILES_BASE,
26
    ];
27

28
    /** @var array<string, mixed> */
29
    private $config;
30

31
    /** @var \Stripe\Util\RequestOptions */
32
    private $defaultOpts;
33

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

72
        $config = \array_merge(self::DEFAULT_CONFIG, $config);
23✔
73
        $this->validateConfig($config);
23✔
74

75
        $this->config = $config;
18✔
76

77
        $this->defaultOpts = \Stripe\Util\RequestOptions::parse([
18✔
78
            'stripe_account' => $config['stripe_account'],
18✔
79
            'stripe_version' => $config['stripe_version'],
18✔
80
        ]);
18✔
81
    }
82

83
    /**
84
     * Gets the API key used by the client to send requests.
85
     *
86
     * @return null|string the API key used by the client to send requests
87
     */
88
    public function getApiKey()
15✔
89
    {
90
        return $this->config['api_key'];
15✔
91
    }
92

93
    /**
94
     * Gets the client ID used by the client in OAuth requests.
95
     *
96
     * @return null|string the client ID used by the client in OAuth requests
97
     */
98
    public function getClientId()
×
99
    {
100
        return $this->config['client_id'];
×
101
    }
102

103
    /**
104
     * Gets the base URL for Stripe's API.
105
     *
106
     * @return string the base URL for Stripe's API
107
     */
108
    public function getApiBase()
15✔
109
    {
110
        return $this->config['api_base'];
15✔
111
    }
112

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

123
    /**
124
     * Gets the base URL for Stripe's Files API.
125
     *
126
     * @return string the base URL for Stripe's Files API
127
     */
128
    public function getFilesBase()
×
129
    {
130
        return $this->config['files_base'];
×
131
    }
132

133
    /**
134
     * Gets the app info for this client.
135
     *
136
     * @return null|array information to identify a plugin that integrates Stripe using this library
137
     */
138
    public function getAppInfo()
14✔
139
    {
140
        return $this->config['app_info'];
14✔
141
    }
142

143
    /**
144
     * Sends a request to Stripe's API.
145
     *
146
     * @param 'delete'|'get'|'post' $method the HTTP method
147
     * @param string $path the path of the request
148
     * @param array $params the parameters of the request
149
     * @param array|\Stripe\Util\RequestOptions $opts the special modifiers of the request
150
     *
151
     * @return \Stripe\StripeObject the object returned by Stripe's API
152
     */
153
    public function request($method, $path, $params, $opts)
17✔
154
    {
155
        $opts = $this->defaultOpts->merge($opts, true);
17✔
156
        $baseUrl = $opts->apiBase ?: $this->getApiBase();
15✔
157
        $requestor = new \Stripe\ApiRequestor($this->apiKeyForRequest($opts), $baseUrl, $this->getAppInfo());
15✔
158
        list($response, $opts->apiKey) = $requestor->request($method, $path, $params, $opts->headers, ['stripe_client']);
14✔
159
        $opts->discardNonPersistentHeaders();
13✔
160
        $obj = \Stripe\Util\Util::convertToStripeObject($response->json, $opts);
13✔
161
        $obj->setLastResponse($response);
13✔
162

163
        return $obj;
13✔
164
    }
165

166
    /**
167
     * Sends a request to Stripe's API, passing chunks of the streamed response
168
     * into a user-provided $readBodyChunkCallable callback.
169
     *
170
     * @param 'delete'|'get'|'post' $method the HTTP method
171
     * @param string $path the path of the request
172
     * @param callable $readBodyChunkCallable a function that will be called
173
     * @param array $params the parameters of the request
174
     * @param array|\Stripe\Util\RequestOptions $opts the special modifiers of the request
175
     * with chunks of bytes from the body if the request is successful
176
     */
177
    public function requestStream($method, $path, $readBodyChunkCallable, $params, $opts)
×
178
    {
179
        $opts = $this->defaultOpts->merge($opts, true);
×
180
        $baseUrl = $opts->apiBase ?: $this->getApiBase();
×
NEW
181
        $requestor = new \Stripe\ApiRequestor($this->apiKeyForRequest($opts), $baseUrl, $this->getAppInfo());
×
182
        list($response, $opts->apiKey) = $requestor->requestStream($method, $path, $readBodyChunkCallable, $params, $opts->headers, ['stripe_client']);
×
183
    }
184

185
    /**
186
     * Sends a request to Stripe's API.
187
     *
188
     * @param 'delete'|'get'|'post' $method the HTTP method
189
     * @param string $path the path of the request
190
     * @param array $params the parameters of the request
191
     * @param array|\Stripe\Util\RequestOptions $opts the special modifiers of the request
192
     *
193
     * @return \Stripe\Collection of ApiResources
194
     */
195
    public function requestCollection($method, $path, $params, $opts)
2✔
196
    {
197
        $obj = $this->request($method, $path, $params, $opts);
2✔
198
        if (!($obj instanceof \Stripe\Collection)) {
2✔
199
            $received_class = \get_class($obj);
1✔
200
            $msg = "Expected to receive `Stripe\\Collection` object from Stripe API. Instead received `{$received_class}`.";
1✔
201

202
            throw new \Stripe\Exception\UnexpectedValueException($msg);
1✔
203
        }
204
        $obj->setFilters($params);
1✔
205

206
        return $obj;
1✔
207
    }
208

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

226
            throw new \Stripe\Exception\UnexpectedValueException($msg);
×
227
        }
228
        $obj->setFilters($params);
×
229

230
        return $obj;
×
231
    }
232

233
    /**
234
     * @param \Stripe\Util\RequestOptions $opts
235
     *
236
     * @throws \Stripe\Exception\AuthenticationException
237
     *
238
     * @return string
239
     */
240
    private function apiKeyForRequest($opts)
15✔
241
    {
242
        $apiKey = $opts->apiKey ?: $this->getApiKey();
15✔
243

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

249
            throw new \Stripe\Exception\AuthenticationException($msg);
1✔
250
        }
251

252
        return $apiKey;
14✔
253
    }
254

255
    /**
256
     * @param array<string, mixed> $config
257
     *
258
     * @throws \Stripe\Exception\InvalidArgumentException
259
     */
260
    private function validateConfig($config)
23✔
261
    {
262
        // api_key
263
        if (null !== $config['api_key'] && !\is_string($config['api_key'])) {
23✔
264
            throw new \Stripe\Exception\InvalidArgumentException('api_key must be null or a string');
1✔
265
        }
266

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

270
            throw new \Stripe\Exception\InvalidArgumentException($msg);
1✔
271
        }
272

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

276
            throw new \Stripe\Exception\InvalidArgumentException($msg);
1✔
277
        }
278

279
        // client_id
280
        if (null !== $config['client_id'] && !\is_string($config['client_id'])) {
20✔
281
            throw new \Stripe\Exception\InvalidArgumentException('client_id must be null or a string');
×
282
        }
283

284
        // stripe_account
285
        if (null !== $config['stripe_account'] && !\is_string($config['stripe_account'])) {
20✔
286
            throw new \Stripe\Exception\InvalidArgumentException('stripe_account must be null or a string');
×
287
        }
288

289
        // stripe_version
290
        if (null !== $config['stripe_version'] && !\is_string($config['stripe_version'])) {
20✔
291
            throw new \Stripe\Exception\InvalidArgumentException('stripe_version must be null or a string');
×
292
        }
293

294
        // api_base
295
        if (!\is_string($config['api_base'])) {
20✔
296
            throw new \Stripe\Exception\InvalidArgumentException('api_base must be a string');
×
297
        }
298

299
        // connect_base
300
        if (!\is_string($config['connect_base'])) {
20✔
301
            throw new \Stripe\Exception\InvalidArgumentException('connect_base must be a string');
×
302
        }
303

304
        // files_base
305
        if (!\is_string($config['files_base'])) {
20✔
306
            throw new \Stripe\Exception\InvalidArgumentException('files_base must be a string');
×
307
        }
308

309
        // app info
310
        if (null !== $config['app_info'] && !\is_array($config['app_info'])) {
20✔
NEW
311
            throw new \Stripe\Exception\InvalidArgumentException('app_info must be an array');
×
312
        }
313

314
        $appInfoKeys = ['name', 'version', 'url', 'appPartnerId'];
20✔
315
        if (null !== $config['app_info'] && array_diff_key($config['app_info'], array_flip($appInfoKeys))) {
20✔
316
            $msg = 'app_info must be of type array{name: string, version?: string, url?: string, appPartnerId?: string}';
1✔
317

318
            throw new \Stripe\Exception\InvalidArgumentException($msg);
1✔
319
        }
320

321
        // check absence of extra keys
322
        $extraConfigKeys = \array_diff(\array_keys($config), \array_keys(self::DEFAULT_CONFIG));
19✔
323
        if (!empty($extraConfigKeys)) {
19✔
324
            // Wrap in single quote to more easily catch trailing spaces errors
325
            $invalidKeys = "'" . \implode("', '", $extraConfigKeys) . "'";
1✔
326

327
            throw new \Stripe\Exception\InvalidArgumentException('Found unknown key(s) in configuration array: ' . $invalidKeys);
1✔
328
        }
329
    }
330
}
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

© 2024 Coveralls, Inc