GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

Api::__construct()   A
last analyzed

Complexity

Conditions 4
Paths 8

Size

Total Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
nc 8
nop 6
dl 0
loc 14
rs 9.7998
c 0
b 0
f 0
1
<?php
2
3
/*
4
 * This file is part of the Netaxept API package.
5
 *
6
 * (c) Andrew Plank
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
declare(strict_types=1);
13
14
namespace FDM\Netaxept;
15
16
use FDM\Netaxept\Exception\Exception;
17
use FDM\Netaxept\Exception\Factory as ExceptionFactory;
18
use FDM\Netaxept\Response\ErrorInterface;
19
use FDM\Netaxept\Response\Factory as ResponseFactory;
20
use FDM\Netaxept\Response\ProcessInterface;
21
use FDM\Netaxept\Response\QueryInterface;
22
use FDM\Netaxept\Response\RegisterInterface;
23
use GuzzleHttp\Client;
24
use GuzzleHttp\Psr7\Uri;
25
use Webmozart\Assert\Assert;
26
27
class Api
28
{
29
    const PRODUCTION_URL = 'https://epayment.nets.eu/';
30
31
    const SANDBOX_URL = 'https://test.epayment.nets.eu/';
32
33
    const OPERATION_AUTH = 'auth';
34
35
    const OPERATION_VERIFY = 'verify';
36
37
    const OPERATION_SALE = 'sale';
38
39
    const OPERATION_CAPTURE = 'capture';
40
41
    const OPERATION_REFUND = 'credit';
42
43
    const OPERATION_CANCEL = 'annul';
44
45
    const ENDPOINTS = [
46
        'register' => 'Netaxept/Register.aspx',
47
        'process' => 'Netaxept/Process.aspx',
48
        'query' => 'Netaxept/Query.aspx',
49
        'terminal' => 'Terminal/Default.aspx',
50
    ];
51
52
    /**
53
     * @var string
54
     */
55
    protected $merchantId;
56
57
    /**
58
     * @var string
59
     */
60
    protected $token;
61
62
    /**
63
     * @var ResponseFactory
64
     */
65
    protected $responseFactory;
66
67
    /**
68
     * @var ExceptionFactory
69
     */
70
    protected $exceptionFactory;
71
72
    /**
73
     * @var Client
74
     */
75
    protected $client;
76
77
    /**
78
     * @var bool
79
     */
80
    protected $sandbox;
81
82
    public function __construct(
83
        string $merchantId,
84
        string $token,
85
        ResponseFactory $responseFactory = null,
86
        ExceptionFactory $exceptionFactory = null,
87
        Client $client = null,
88
        bool $sandbox = false
89
    ) {
90
        $this->merchantId = $merchantId;
91
        $this->token = $token;
92
        $this->responseFactory = $responseFactory ? $responseFactory : new ResponseFactory();
93
        $this->exceptionFactory = $exceptionFactory ? $exceptionFactory : new ExceptionFactory();
94
        $this->client = $client ? $client : new Client();
95
        $this->sandbox = $sandbox;
96
    }
97
98
    /**
99
     * Get a Query response object for the provided transaction ID.
100
     *
101
     * @param string $transactionId
102
     *
103
     * @return QueryInterface
104
     */
105
    public function getTransaction($transactionId): QueryInterface
106
    {
107
        $uri = $this->getUri('query', $this->getParameters(['transactionId' => $transactionId]));
108
        /** @var QueryInterface $response */
109
        $response = $this->performRequest((string) $uri);
110
111
        Assert::isInstanceOf($response, QueryInterface::class, 'Invalid response');
112
        Assert::isInstanceOf($response, ErrorInterface::class, 'Invalid response');
113
114
        return $response;
115
    }
116
117
    /**
118
     * Registers a transaction
119
     *
120
     * @param array $transactionData
121
     *
122
     * @return RegisterInterface
123
     */
124
    public function registerTransaction(array $transactionData): RegisterInterface
125
    {
126
        $uri = $this->getUri('register', $this->getParameters($transactionData));
127
        /** @var RegisterInterface $response */
128
        $response = $this->performRequest((string) $uri);
129
130
        Assert::isInstanceOf($response, RegisterInterface::class, 'Invalid response');
131
132
        return $response;
133
    }
134
135
    /**
136
     * Processes a transaction
137
     *
138
     * @param array $transactionData
139
     *
140
     * @return ProcessInterface
141
     */
142
    public function processTransaction(array $transactionData, string $operation): ProcessInterface
143
    {
144
        // When hitting the process endpoint, we only need the transactionId and operation key/value pairs, and
145
        // optionally the transactionAmount if we are capturing a portion of the total amount.
146
        $transactionData = array_filter($transactionData + ['operation' => $operation], function ($k) {
147
            return in_array($k, ['transactionId', 'operation', 'transactionAmount']);
148
        }, ARRAY_FILTER_USE_KEY);
149
150
        $uri = $this->getUri('process', $this->getParameters($transactionData));
151
        /** @var ProcessInterface $response */
152
        $response = $this->performRequest((string) $uri);
153
154
        Assert::isInstanceOf($response, ProcessInterface::class, 'Invalid response');
155
156
        return $response;
157
    }
158
159
    /**
160
     * Register a transaction.
161
     *
162
     * @param array $transactionData
163
     *
164
     * @return RegisterInterface
165
     */
166
    public function register(array $transactionData): RegisterInterface
167
    {
168
        return $this->registerTransaction($transactionData);
169
    }
170
171
    /**
172
     * Verify a transaction.
173
     *
174
     * @param array $transactionData
175
     *
176
     * @return ProcessInterface
177
     */
178
    public function verify(array $transactionData): ProcessInterface
179
    {
180
        return $this->processTransaction($transactionData, self::OPERATION_VERIFY);
181
    }
182
183
    /**
184
     * Authorize a transaction.
185
     *
186
     * @param array $transactionData
187
     *
188
     * @return ProcessInterface
189
     */
190
    public function authorize(array $transactionData): ProcessInterface
191
    {
192
        return $this->processTransaction($transactionData, self::OPERATION_AUTH);
193
    }
194
195
    /**
196
     * Cancel a transaction.
197
     *
198
     * @param array $transactionData
199
     *
200
     * @return ProcessInterface
201
     */
202
    public function cancel(array $transactionData): ProcessInterface
203
    {
204
        return $this->processTransaction($transactionData, self::OPERATION_CANCEL);
205
    }
206
207
    /**
208
     * Capture a transaction.
209
     *
210
     * @param array $transactionData
211
     *
212
     * @return ProcessInterface
213
     */
214
    public function capture(array $transactionData): ProcessInterface
215
    {
216
        return $this->processTransaction($transactionData, self::OPERATION_CAPTURE);
217
    }
218
219
    /**
220
     * Authorize and capture a transaction.
221
     *
222
     * @param array $transactionData
223
     *
224
     * @return ProcessInterface
225
     */
226
    public function sale(array $transactionData): ProcessInterface
227
    {
228
        return $this->processTransaction($transactionData, self::OPERATION_SALE);
229
    }
230
231
    /**
232
     * Refunds a transaction.
233
     *
234
     * @param array $transactionData
235
     *
236
     * @return ProcessInterface
237
     */
238
    public function refund(array $transactionData): ProcessInterface
239
    {
240
        return $this->processTransaction($transactionData, self::OPERATION_REFUND);
241
    }
242
243
    /**
244
     * Given the transaction ID, returns a URI that the user should be redirected to in order to enter their card
245
     * details for that transaction.
246
     *
247
     * @param string $transactionId
248
     *
249
     * @return Uri
250
     */
251
    public function getTerminalUri(string $transactionId): Uri
252
    {
253
        $uri = $this->getUri('terminal', ['merchantId' => $this->merchantId, 'transactionId' => $transactionId]);
254
255
        return $uri;
256
    }
257
258
    /**
259
     * Performs a request to the provided URI, and returns the appropriate response object, based on the content of the
260
     * HTTP response.
261
     *
262
     * @param string $uri
263
     *
264
     * @return mixed
265
     */
266
    protected function performRequest(string $uri)
267
    {
268
        $httpResponse = $this->client->get($uri);
269
        Assert::eq($httpResponse->getStatusCode(), 200, 'Request failed.');
270
271
        $content = $httpResponse->getBody()->getContents();
272
        $xml = simplexml_load_string($content);
273
274
        $this->exceptionOnError($xml);
0 ignored issues
show
Bug introduced by
It seems like $xml can also be of type false; however, parameter $xml of FDM\Netaxept\Api::exceptionOnError() does only seem to accept SimpleXMLElement, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

274
        $this->exceptionOnError(/** @scrutinizer ignore-type */ $xml);
Loading history...
275
276
        return $this->responseFactory->getResponse($xml);
277
    }
278
279
    /**
280
     * Returns the provided parameters, along with the merchantId and token that's required in every request.
281
     *
282
     * @param array $parameters
283
     *
284
     * @return array
285
     */
286
    protected function getParameters(array $parameters)
287
    {
288
        return [
289
            'merchantId' => $this->merchantId,
290
            'token' => $this->token,
291
        ] + $parameters;
292
    }
293
294
    /**
295
     * Builds a URI, based on the named endpoint and provided parameters. The Netaxept API claims to be a REST API, but
296
     * it is not in any way, shape, or form a REST API. It requires all requests to be GET requests, and all parameters
297
     * to be URLencoded and provided in the query string. About as far away from REST as you can get.
298
     *
299
     * @param string $endpoint
300
     * @param array $parameters
301
     *
302
     * @return Uri
303
     */
304
    protected function getUri(string $endpoint, array $parameters = []): Uri
305
    {
306
        Assert::keyExists(self::ENDPOINTS, $endpoint, "Named endpoint {$endpoint} is unknown.");
307
308
        $uri = $this->sandbox ? self::SANDBOX_URL : self::PRODUCTION_URL;
309
        $uri .= self::ENDPOINTS[$endpoint];
310
311
        if ($parameters) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $parameters of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
312
            $uri .= '?' . http_build_query($parameters);
313
        }
314
315
        return new Uri($uri);
316
    }
317
318
    /**
319
     * @param \SimpleXMLElement $xml
320
     *
321
     * @throws Exception
322
     */
323
    protected function exceptionOnError(\SimpleXMLElement $xml)
324
    {
325
        if ($xml->getName() == 'Exception') {
326
            throw $this->exceptionFactory->getException($xml);
327
        }
328
    }
329
}
330