ErrorsHandler::getAPIException()   B
last analyzed

Complexity

Conditions 4
Paths 2

Size

Total Lines 23
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 16
CRAP Score 4

Importance

Changes 0
Metric Value
dl 0
loc 23
c 0
b 0
f 0
cc 4
eloc 16
nc 2
nop 0
ccs 16
cts 16
cp 1
crap 4
rs 8.7972
1
<?php namespace Arcanedev\Stripe\Utilities;
2
3
use Arcanedev\Stripe\Contracts\Utilities\ApiErrorsHandler as ApiErrorsHandlerContract;
4
use Arcanedev\Stripe\Exceptions;
5
6
/**
7
 * Class     ErrorsHandler
8
 *
9
 * @package  Arcanedev\Stripe\Utilities
10
 * @author   ARCANEDEV <[email protected]>
11
 */
12
class ErrorsHandler implements ApiErrorsHandlerContract
13
{
14
    /* -----------------------------------------------------------------
15
     |  Properties
16
     | -----------------------------------------------------------------
17
     */
18
19
    /** @var string */
20
    private $respBody;
21
22
    /** @var int */
23
    private $respCode;
24
25
    /** @var array */
26
    protected $respHeaders;
27
28
    /** @var array */
29
    private $response   = [];
30
31
    /** @var array */
32
    private static $apiExceptions = [
33
        400 => Exceptions\InvalidRequestException::class,
34
        401 => Exceptions\AuthenticationException::class,
35
        402 => Exceptions\CardException::class,
36
        403 => Exceptions\PermissionException::class,
37
        404 => Exceptions\InvalidRequestException::class,
38
        429 => Exceptions\RateLimitException::class,
39
        500 => Exceptions\ApiException::class,
40
    ];
41
42
    /** @var array */
43
    private static $oauthExceptions = [
44
        'invalid_grant'             => Exceptions\OAuth\InvalidGrantException::class,
45
        'invalid_request'           => Exceptions\OAuth\InvalidRequestException::class,
46
        'invalid_scope'             => Exceptions\OAuth\InvalidScopeException::class,
47
        'unsupported_grant_type'    => Exceptions\OAuth\UnsupportedGrantTypeException::class,
48
        'unsupported_response_type' => Exceptions\OAuth\UnsupportedResponseTypeException::class,
49
    ];
50
51
    /* -----------------------------------------------------------------
52
     |  Getters & Setters
53
     | -----------------------------------------------------------------
54
     */
55
56
    /**
57
     * Set Response body (JSON).
58
     *
59
     * @param  string  $respBody
60
     *
61
     * @return self
62
     */
63 72
    private function setRespBody($respBody)
64
    {
65 72
        $this->respBody = $respBody;
66
67 72
        return $this;
68
    }
69
70
    /**
71
     * Set Response Code.
72
     *
73
     * @param  int  $respCode
74
     *
75
     * @return self
76
     */
77 72
    private function setRespCode($respCode)
78
    {
79 72
        $this->respCode = $respCode;
80
81 72
        return $this;
82
    }
83
84
    /**
85
     * Set Response Headers.
86
     *
87
     * @param  array  $respHeaders
88
     *
89
     * @return self
90
     */
91 72
    private function setRespHeaders($respHeaders)
92
    {
93 72
        $this->respHeaders = $respHeaders;
94
95 72
        return $this;
96
    }
97
98
    /**
99
     * Set Response.
100
     *
101
     * @param  array  $response
102
     *
103
     * @return self
104
     */
105 72
    private function setResponse($response)
106
    {
107 72
        $this->checkResponse($response);
108
109 70
        $this->response = $response;
110
111 70
        return $this;
112
    }
113
114
    /**
115
     * Get Exception class by status code.
116
     *
117
     * @param  int  $code
118
     *
119
     * @return string
120
     */
121 62
    private function getApiExceptionByCode($code)
122
    {
123 62
        return self::$apiExceptions[$code];
124
    }
125
126
    /* -----------------------------------------------------------------
127
     |  Main Methods
128
     | -----------------------------------------------------------------
129
     */
130
131
    /**
132
     * Handle API Errors.
133
     *
134
     * @param  string  $respBody
135
     * @param  int     $respCode
136
     * @param  array   $respHeaders
137
     * @param  array   $response
138
     *
139
     * @throws \Arcanedev\Stripe\Exceptions\ApiException
140
     * @throws \Arcanedev\Stripe\Exceptions\AuthenticationException
141
     * @throws \Arcanedev\Stripe\Exceptions\CardException
142
     * @throws \Arcanedev\Stripe\Exceptions\InvalidRequestException
143
     * @throws \Arcanedev\Stripe\Exceptions\PermissionException
144
     * @throws \Arcanedev\Stripe\Exceptions\RateLimitException
145
     */
146 74
    public function handle($respBody, $respCode, $respHeaders, $response)
147
    {
148 74
        if ($respCode >= 200 && $respCode < 300)
149 2
            return;
150
151 72
        $this->setRespBody($respBody);
152 72
        $this->setRespCode($respCode);
153 72
        $this->setRespHeaders($respHeaders);
154 72
        $this->setResponse($response);
155
156 70
        $exception = is_string($this->response['error'])
157 8
            ? $this->getOAuthException()
158 70
            : $this->getAPIException();
159
160 70
        throw $exception;
161
    }
162
163
    /* -----------------------------------------------------------------
164
     |  Check Methods
165
     | -----------------------------------------------------------------
166
     */
167
168
    /**
169
     * Check Response.
170
     *
171
     * @param  mixed  $response
172
     *
173
     * @throws \Arcanedev\Stripe\Exceptions\ApiException
174
     */
175 72
    private function checkResponse($response)
176
    {
177 72
        if ( ! $this->hasErrorResponse($response)) {
178 2
            $msg = str_replace([
179 2
                '{resp-body}',
180
                '{resp-code}'
181
            ], [
182 2
                $this->respBody,
183 2
                $this->respCode,
184 2
            ], 'Invalid response object from API: {resp-body} (HTTP response code was {resp-code})');
185
186 2
            throw new Exceptions\ApiException($msg, $this->respCode, $this->respBody, $response);
187
        }
188 70
    }
189
190
    /**
191
     * Check if has Response.
192
     *
193
     * @param  mixed  $response
194
     *
195
     * @return bool
196
     */
197 72
    private function hasErrorResponse($response)
198
    {
199 72
        return is_array($response) && isset($response['error']);
200
    }
201
202
    /**
203
     * Check if has Exception.
204
     *
205
     * @return bool
206
     */
207 62
    private function hasException()
208
    {
209 62
        return array_key_exists($this->respCode, self::$apiExceptions);
210
    }
211
212
    /* ------------------------------------------------------------------------------------------------
213
     |  Other Functions
214
     | ------------------------------------------------------------------------------------------------
215
     */
216
    /**
217
     * Parse response error.
218
     *
219
     * @return \Arcanedev\Stripe\Exceptions\StripeException
220
     */
221 62
    private function getAPIException()
222
    {
223 62
        $stripeCode = $this->getResponseError('code');
224 62
        $exception  = $this->getApiExceptionByCode(
225 62
            $this->hasException() ? $this->respCode : 500
226
        );
227
228 62
        if ($this->respCode === 400 && $stripeCode === 'rate_limit') {
229 2
            $this->setRespCode(429);
230 2
            $exception = $this->getApiExceptionByCode(429);
231
        }
232
233 62
        return new $exception(
234 62
            $this->getResponseError('message'),
235 62
            $this->respCode,
236 62
            $this->getResponseError('type'),
237 62
            $stripeCode,
238 62
            $this->respBody,
239 62
            $this->response,
240 62
            $this->getResponseError('param'),
241 62
            $this->respHeaders
242
        );
243
    }
244
245
    /**
246
     * Get the OAuth exception.
247
     *
248
     * @return \Arcanedev\Stripe\Exceptions\OAuth\OAuthException
249
     */
250 8
    private function getOAuthException()
251
    {
252 8
        $errorCode   = $this->response['error'];
253 8
        $description = $this->response['error_description'] ?: $errorCode;
254
255 8
        $exception = self::$oauthExceptions[$errorCode];
256
257 8
        return new $exception(
258 8
            $errorCode,
259 8
            $description,
260 8
            $this->respCode,
261 8
            $this->respBody,
262 8
            $this->response,
263 8
            $this->respHeaders
264
        );
265
    }
266
267
    /**
268
     * Get Error attribute.
269
     *
270
     * @param  string  $name
271
     *
272
     * @return mixed
273
     */
274 62
    private function getResponseError($name)
275
    {
276 62
        $error = null;
277
278 62
        if (isset($this->response['error'][$name])) {
279 58
            $error   = $this->response['error'][$name];
280
        }
281
282 62
        if ($name === 'param' && is_null($error)) {
283 28
            $ignored = ['type', 'message', 'code'];
284 28
            $error   = array_diff_key($this->response['error'], array_flip($ignored));
285
        }
286
287 62
        return $error;
288
    }
289
}
290