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

stripe / stripe-php / 11129599820

01 Oct 2024 04:33PM UTC coverage: 62.613% (-1.3%) from 63.944%
11129599820

push

github

web-flow
Support for APIs in the new API version 2024-09-30.acacia (#1756)

175 of 409 new or added lines in 26 files covered. (42.79%)

3 existing lines in 3 files now uncovered.

3547 of 5665 relevant lines covered (62.61%)

2.46 hits per line

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

93.51
/lib/Util/RequestOptions.php
1
<?php
2

3
namespace Stripe\Util;
4

5
/**
6
 * @phpstan-type RequestOptionsArray array{api_key?: string, idempotency_key?: string, stripe_account?: string, stripe_context?: string, stripe_version?: string, api_base?: string }
7
 * @psalm-type RequestOptionsArray = array{api_key?: string, idempotency_key?: string, stripe_account?: string, stripe_context?: string, stripe_version?: string, api_base?: string }
8
 */
9
class RequestOptions
10
{
11
    /**
12
     * @var array<string> a list of headers that should be persisted across requests
13
     */
14
    public static $HEADERS_TO_PERSIST = [
15
        'Stripe-Account',
16
        'Stripe-Version',
17
    ];
18

19
    /** @var array<string, string> */
20
    public $headers;
21

22
    /** @var null|string */
23
    public $apiKey;
24

25
    /** @var null|string */
26
    public $apiBase;
27

28
    /**
29
     * @param null|string $key
30
     * @param array<string, string> $headers
31
     * @param null|string $base
32
     */
33
    public function __construct($key = null, $headers = [], $base = null)
11✔
34
    {
35
        $this->apiKey = $key;
11✔
36
        $this->headers = $headers;
11✔
37
        $this->apiBase = $base;
11✔
38
    }
39

40
    /**
41
     * @return array<string, string>
42
     */
43
    public function __debugInfo()
1✔
44
    {
45
        return [
1✔
46
            'apiKey' => $this->redactedApiKey(),
1✔
47
            'headers' => $this->headers,
1✔
48
            'apiBase' => $this->apiBase,
1✔
49
        ];
1✔
50
    }
51

52
    /**
53
     * Unpacks an options array and merges it into the existing RequestOptions
54
     * object.
55
     *
56
     * @param null|array|RequestOptions|string $options a key => value array
57
     * @param bool $strict when true, forbid string form and arbitrary keys in array form
58
     *
59
     * @return RequestOptions
60
     */
61
    public function merge($options, $strict = false)
1✔
62
    {
63
        $other_options = self::parse($options, $strict);
1✔
64
        if (null === $other_options->apiKey) {
1✔
65
            $other_options->apiKey = $this->apiKey;
1✔
66
        }
67
        if (null === $other_options->apiBase) {
1✔
68
            $other_options->apiBase = $this->apiBase;
1✔
69
        }
70
        $other_options->headers = \array_merge($this->headers, $other_options->headers);
1✔
71

72
        return $other_options;
1✔
73
    }
74

75
    /**
76
     * Discards all headers that we don't want to persist across requests.
77
     */
78
    public function discardNonPersistentHeaders()
1✔
79
    {
80
        foreach ($this->headers as $k => $v) {
1✔
81
            if (!\in_array($k, self::$HEADERS_TO_PERSIST, true)) {
1✔
82
                unset($this->headers[$k]);
1✔
83
            }
84
        }
85
    }
86

87
    /**
88
     * Unpacks an options array into an RequestOptions object.
89
     *
90
     * @param null|array|RequestOptions|string $options a key => value array
91
     * @param bool $strict when true, forbid string form and arbitrary keys in array form
92
     *
93
     * @throws \Stripe\Exception\InvalidArgumentException
94
     *
95
     * @return RequestOptions
96
     */
97
    public static function parse($options, $strict = false)
14✔
98
    {
99
        if ($options instanceof self) {
14✔
100
            return clone $options;
×
101
        }
102

103
        if (null === $options) {
14✔
104
            return new RequestOptions(null, [], null);
1✔
105
        }
106

107
        if (\is_string($options)) {
13✔
108
            if ($strict) {
2✔
109
                $message = 'Do not pass a string for request options. If you want to set the '
1✔
110
                    . 'API key, pass an array like ["api_key" => <apiKey>] instead.';
1✔
111

112
                throw new \Stripe\Exception\InvalidArgumentException($message);
1✔
113
            }
114

115
            return new RequestOptions($options, [], null);
1✔
116
        }
117

118
        if (\is_array($options)) {
11✔
119
            $headers = [];
10✔
120
            $key = null;
10✔
121
            $base = null;
10✔
122

123
            if (\array_key_exists('api_key', $options)) {
10✔
124
                $key = $options['api_key'];
6✔
125
                unset($options['api_key']);
6✔
126
            }
127
            if (\array_key_exists('idempotency_key', $options)) {
10✔
128
                $headers['Idempotency-Key'] = $options['idempotency_key'];
4✔
129
                unset($options['idempotency_key']);
4✔
130
            }
131
            if (\array_key_exists('stripe_account', $options)) {
10✔
132
                if (null !== $options['stripe_account']) {
1✔
133
                    $headers['Stripe-Account'] = $options['stripe_account'];
1✔
134
                }
135
                unset($options['stripe_account']);
1✔
136
            }
137
            if (\array_key_exists('stripe_context', $options)) {
10✔
138
                if (null !== $options['stripe_context']) {
1✔
139
                    $headers['Stripe-Context'] = $options['stripe_context'];
1✔
140
                }
141
                unset($options['stripe_context']);
1✔
142
            }
143
            if (\array_key_exists('stripe_version', $options)) {
10✔
NEW
144
                if (null !== $options['stripe_version']) {
×
NEW
145
                    $headers['Stripe-Version'] = $options['stripe_version'];
×
146
                }
UNCOV
147
                unset($options['stripe_version']);
×
148
            }
149
            if (\array_key_exists('api_base', $options)) {
10✔
150
                $base = $options['api_base'];
1✔
151
                unset($options['api_base']);
1✔
152
            }
153

154
            if ($strict && !empty($options)) {
10✔
155
                $message = 'Got unexpected keys in options array: ' . \implode(', ', \array_keys($options));
1✔
156

157
                throw new \Stripe\Exception\InvalidArgumentException($message);
1✔
158
            }
159

160
            return new RequestOptions($key, $headers, $base);
9✔
161
        }
162

163
        $message = 'The second argument to Stripe API method calls is an '
1✔
164
            . 'optional per-request apiKey, which must be a string, or '
1✔
165
            . 'per-request options, which must be an array. (HINT: you can set '
1✔
166
            . 'a global apiKey by "Stripe::setApiKey(<apiKey>)")';
1✔
167

168
        throw new \Stripe\Exception\InvalidArgumentException($message);
1✔
169
    }
170

171
    /** @return string */
172
    private function redactedApiKey()
1✔
173
    {
174
        if (null === $this->apiKey) {
1✔
175
            return '';
1✔
176
        }
177

178
        $pieces = \explode('_', $this->apiKey, 3);
1✔
179
        $last = \array_pop($pieces);
1✔
180
        $redactedLast = \strlen($last) > 4
1✔
181
            ? (\str_repeat('*', \strlen($last) - 4) . \substr($last, -4))
1✔
182
            : $last;
×
183
        $pieces[] = $redactedLast;
1✔
184

185
        return \implode('_', $pieces);
1✔
186
    }
187
}
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