Issues (10)

Security Analysis    no request data  

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

src/Client.php (9 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php declare(strict_types=1);
2
/**
3
 * Client for Smartcall's Restful Proxy.
4
 *
5
 * @author    Jacques Marneweck <[email protected]>
6
 * @copyright 2016-2019 Jacques Marneweck.  All rights strictly reserved.
7
 * @license   MIT
8
 */
9
10
namespace Jacques\SmartCallProxy;
11
12
class Client extends \GuzzleHttp\Client
13
{
14
    /**
15
     * @const string Version number
16
     */
17
    const VERSION = '0.1.1';
18
19
    /**
20
     * Defaults to expecting that Apache Tomcat runs on port 8080 on localhost
21
     * (127.0.0.1).
22
     *
23
     * @var array[]
24
     */
25
    protected $options = [
26
        'scheme'   => 'http',
27
        'hostname' => 'localhost',
28
        'port'     => '8080',
29
    ];
30
31
    /**
32
     * @param   $options array
33
     *
34
     * @return void
35
     */
36 2
    public function __construct($options = [])
37
    {
38
        /*
39
         * Allow on instantiation to overwrite the defaults
40
         */
41 2
        $this->options = array_merge(
0 ignored issues
show
Documentation Bug introduced by
It seems like array_merge($this->options, $options) of type array is incompatible with the declared type array<integer,array> of property $options.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
42 2
            $this->options,
43 2
            $options
44
        );
45
46
        $config = [
47 2
            'base_uri' => sprintf(
48 2
                '%s://%s:%s/',
49 2
                $this->options['scheme'],
50 2
                $this->options['hostname'],
51 2
                $this->options['port']
52
            ),
53
            'headers' => [
54 2
                'User-Agent' => 'SmartcallRestfulProxyClient-PHP/'.self::VERSION.' '.\GuzzleHttp\default_user_agent(),
55
            ],
56
        ];
57
58 2
        parent::__construct($config);
59 2
    }
60
61
    /**
62
     * Facility provided to cancel recharges.  This does not work if the recharge
63
     * has been processed by the MNO.
64
     *
65
     * @param int $reference Order Reference from SmartCall
66
     *
67
     * @throws Exception
68
     *
69
     * @return array
70
     */
71 2
    public function cancelRecharge($reference)
72
    {
73
        try {
74 2
            $response = $this->post(
75 2
                '/SmartcallRestfulProxy/cancel_recharge_js',
76
                [
77
                    'json' => [
78 2
                        'orderReferenceId' => $reference,
79
                    ],
80
                ]
81
            );
82
83
            return [
84 2
                'status'    => 'ok',
85 2
                'http_code' => $response->getStatusCode(),
86 2
                'body'      => (string) $response->getBody(),
87
            ];
88
        } catch (\GuzzleHttp\Exception\ServerException $e) {
89
            return $this->parseError($e);
90
        }
91
    }
92
93
    /**
94
     * Transfer funds to another SmartCall Dealer Account.
95
     *
96
     * @param int  $amount  Amount in rands (ZAR) to transfer to the recipients SmartCall Dealer Account
97
     * @param int  $msisdn  MSISDN of the account to receive the funds being transfered
98
     * @param bool $sendSms true = send sms | false do not send a sms
99
     *
100
     * @throws Exception
101
     *
102
     * @return array
103
     */
104 1
    public function fundsTransfer($amount, $msisdn, $sendSms)
105
    {
106
        try {
107 1
            $response = $this->post(
108 1
                '/SmartcallRestfulProxy/funds_transfer_js',
109
                [
110
                    'json' => [
111 1
                        'amount'          => $amount,
112 1
                        'recipientMsisdn' => $msisdn,
113 1
                        'sendSms'         => (bool) $sendSms,
114
                    ],
115
                ]
116
            );
117
118
            return [
119 1
                'status'    => 'ok',
120 1
                'http_code' => $response->getStatusCode(),
121 1
                'body'      => (string) $response->getBody(),
122
            ];
123
        } catch (\GuzzleHttp\Exception\ServerException $e) {
124
            return $this->parseError($e);
125
        }
126
    }
127
128
    /**
129
     * Fetches the Dealer Balance from SmartCall.
130
     *
131
     * @throws Exception
132
     *
133
     * @return array
134
     */
135 3 View Code Duplication
    public function getDealerBalance()
0 ignored issues
show
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
136
    {
137
        try {
138 3
            $response = $this->get('/SmartcallRestfulProxy/balance');
139
140
            return [
141 1
                'status'    => 'ok',
142 1
                'http_code' => $response->getStatusCode(),
143 1
                'body'      => (string) $response->getBody(),
144
            ];
145 2
        } catch (\GuzzleHttp\Exception\ServerException $e) {
146 2
            return $this->parseError($e);
147
        }
148
    }
149
150
    /**
151
     * Fetches the Dealer Balance from SmartCall.
152
     *
153
     * @throws Exception
154
     *
155
     * @return array
156
     */
157 1 View Code Duplication
    public function isDealerRegistered($msisdn)
0 ignored issues
show
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
158
    {
159
        try {
160 1
            $response = $this->get(
161 1
                sprintf(
162 1
                    '/SmartcallRestfulProxy/registered/%s',
163 1
                    $msisdn
164
                )
165
            );
166
167
            return [
168 1
                'status'    => 'ok',
169 1
                'http_code' => $response->getStatusCode(),
170 1
                'body'      => (string) $response->getBody(),
171
            ];
172
        } catch (\GuzzleHttp\Exception\ServerException $e) {
173
            return $this->parseError($e);
174
        }
175
    }
176
177
    /**
178
     * Fetches the Product from SmartCall.
179
     *
180
     * @param int $productId Product Identifier
181
     *
182
     * @throws Exception
183
     *
184
     * @return array
185
     */
186 2 View Code Duplication
    public function getProduct($productId)
0 ignored issues
show
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
187
    {
188
        try {
189 2
            $response = $this->get(
190 2
                sprintf(
191 2
                    '/SmartcallRestfulProxy/product_js/%d',
192 2
                    $productId
193
                )
194
            );
195
196
            return [
197 1
                'status'    => 'ok',
198 1
                'http_code' => $response->getStatusCode(),
199 1
                'body'      => (string) $response->getBody(),
200
            ];
201 1
        } catch (\GuzzleHttp\Exception\ServerException $e) {
202 1
            return $this->parseError($e);
203
        }
204
    }
205
206
    /**
207
     * Fetches the Product List from SmartCall.
208
     *
209
     * @throws Exception
210
     *
211
     * @return array
212
     */
213 1 View Code Duplication
    public function getProducts()
0 ignored issues
show
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
214
    {
215
        try {
216 1
            $response = $this->get('/SmartcallRestfulProxy/all_networks_js');
217
218
            return [
219 1
                'status'    => 'ok',
220 1
                'http_code' => $response->getStatusCode(),
221 1
                'body'      => (string) $response->getBody(),
222
            ];
223
        } catch (\GuzzleHttp\Exception\ServerException $e) {
224
            return $this->parseError($e);
225
        }
226
    }
227
228
    /**
229
     * Fetches the details of the last transaction processed from SmartCall.
230
     *
231
     * @throws Exception
232
     *
233
     * @return array
234
     */
235 1 View Code Duplication
    public function getLastTransaction()
0 ignored issues
show
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
236
    {
237
        try {
238 1
            $response = $this->get('/SmartcallRestfulProxy/last_transaction_js');
239
240
            return [
241 1
                'status'    => 'ok',
242 1
                'http_code' => $response->getStatusCode(),
243 1
                'body'      => (string) $response->getBody(),
244
            ];
245
        } catch (\GuzzleHttp\Exception\ServerException $e) {
246
            return $this->parseError($e);
247
        }
248
    }
249
250
    /**
251
     * Fetches the Product List by the specified network identifier from SmartCall.
252
     *
253
     * @param int $networkId identifier for the network
254
     *
255
     * @throws Exception
256
     *
257
     * @return array
258
     */
259 1 View Code Duplication
    public function getProductsByNetwork($networkId)
0 ignored issues
show
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
260
    {
261
        try {
262 1
            $response = $this->get(
263 1
                sprintf(
264 1
                    '/SmartcallRestfulProxy/network_js/%d',
265 1
                    $networkId
266
                )
267
            );
268
269
            return [
270 1
                'status'    => 'ok',
271 1
                'http_code' => $response->getStatusCode(),
272 1
                'body'      => (string) $response->getBody(),
273
            ];
274
        } catch (\GuzzleHttp\Exception\ServerException $e) {
275
            return $this->parseError($e);
276
        }
277
    }
278
279
    /**
280
     * Prevend an item.  The client reference needs to be passed in when performing the purchase.
281
     * Vodacom requires that the client reference used for the prevend gets passed back in for
282
     * the actual vend.
283
     *
284
     * @param int    $productId identifier for the product
285
     * @param int    $amount    amount in rands of the product
286
     * @param int    $msisdn    mobile number of the recipient of the product
287
     * @param int    $deviceId  mobile number or meter number of the device being recharged
288
     * @param string $clientRef Client Reference (use a UUID)
289
     * @param bool   $pinless   true = device will be recharged via the network's IN platform | false = pinbased virtual voucher
290
     * @param bool   $sendSms   true = SmartCall will send the voucher via SMS | false don't send the voucher via SMS
291
     *
292
     * @throws Exception
293
     *
294
     * @return array
295
     */
296 View Code Duplication
    public function prevendProduct($productId, $amount, $msisdn, $deviceId, $clientRef, $pinless, $sendSms)
0 ignored issues
show
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
297
    {
298
        try {
299
            $response = $this->post(
300
                sprintf(
301
                    '/SmartcallRestfulProxy/prevend_js/%s',
302
                    $clientRef
303
                ),
304
                [
305
                    'json' => [
306
                        'amount'             => $amount,
307
                        'deviceId'           => $deviceId,
308
                        'pinless'            => $pinless,
309
                        'productId'          => $productId,
310
                        'sendSms'            => $sendSms,
311
                        'smsRecipientMsisdn' => $msisdn,
312
                    ],
313
                ]
314
            );
315
316
            return [
317
                'status'    => 'ok',
318
                'http_code' => $response->getStatusCode(),
319
                'body'      => (string) $response->getBody(),
320
            ];
321
        } catch (\GuzzleHttp\Exception\ServerException $e) {
322
            return $this->parseError($e);
323
        }
324
    }
325
326
    /**
327
     * Purchase a voucher or do a pinless recharge on SmartCall.
328
     *
329
     * @param int    $productId identifier for the product
330
     * @param int    $amount    amount in rands of the product
331
     * @param int    $msisdn    mobile number of the recipient of the product
332
     * @param int    $deviceId  mobile number or meter number of the device being recharged
333
     * @param string $clientRef Client Reference (use a UUID)
334
     * @param bool   $pinless   true = device will be recharged via the network's IN platform | false = pinbased virtual voucher
335
     * @param bool   $sendSms   true = SmartCall will send the voucher via SMS | false don't send the voucher via SMS
336
     *
337
     * @throws Exception
338
     *
339
     * @return array
340
     */
341 4 View Code Duplication
    public function purchaseProduct($productId, $amount, $msisdn, $deviceId, $clientRef, $pinless, $sendSms)
0 ignored issues
show
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
342
    {
343
        try {
344 4
            $response = $this->post(
345 4
                sprintf(
346 4
                    '/SmartcallRestfulProxy/recharge_js/%s',
347 4
                    $clientRef
348
                ),
349
                [
350
                    'json' => [
351 4
                        'amount'             => $amount,
352 4
                        'deviceId'           => $deviceId,
353 4
                        'pinless'            => $pinless,
354 4
                        'productId'          => $productId,
355 4
                        'sendSms'            => $sendSms,
356 4
                        'smsRecipientMsisdn' => $msisdn,
357
                    ],
358
                ]
359
            );
360
361
            return [
362 4
                'status'    => 'ok',
363 4
                'http_code' => $response->getStatusCode(),
364 4
                'body'      => (string) $response->getBody(),
365
            ];
366
        } catch (\GuzzleHttp\Exception\ServerException $e) {
367
            return $this->parseError($e);
368
        }
369
    }
370
371
    /**
372
     * Searches SmartCall for a specified transaction using a specified key and string to search
373
     * against at SmartCall.
374
     *
375
     * @param string $field  client_ref | msisdn | order_reference
376
     * @param string $search Client Reference when client_ref or a users MSISDN when msisdn
377
     *
378
     * @throws Exception
379
     *
380
     * @return array
381
     */
382 6
    public function searchTransaction($field, $search)
383
    {
384
        /**
385
         * Map Smartcall's longer version of the url to shorter param to pass in.
386
         */
387
        $fields = [
388 6
            'client_ref' => 'client_reference',
389
            'msisdn'     => 'msisdn',
390
            'order_ref'  => 'order_reference',
391
        ];
392
393
        try {
394 6
            $response = $this->get(
395 6
                sprintf(
396 6
                    '/SmartcallRestfulProxy/last_transaction_%s_js/%s',
397 6
                    (string) $fields[$field],
398 6
                    (string) $search
399
                )
400
            );
401
402
            return [
403 6
                'status'    => 'ok',
404 6
                'http_code' => $response->getStatusCode(),
405 6
                'body'      => (string) $response->getBody(),
406
            ];
407
        } catch (\GuzzleHttp\Exception\ServerException $e) {
408
            return $this->parseError($e);
409
        }
410
    }
411
412
    /**
413
     * Parse the java exception that we receive from Smartcall's Tomcat's.
414
     *
415
     * @param \GuzzleHttp\Exception\ServerException $exception
416
     *
417
     * @return array
418
     */
419 1
    private function parseError(\GuzzleHttp\Exception\ServerException $exception)
420
    {
421 1
        $body = (string) $exception->getResponse()->getBody();
422
423 1
        preg_match('!<p><b>type</b> Exception report</p><p><b>message</b> <u>(.*[^</u>])</u></p><p><b>description</b>!', $body, $matches);
424
425
        return [
426 1
            'status'    => 'error',
427 1
            'http_code' => $exception->getResponse()->getStatusCode(),
428 1
            'body'      => $matches['1'],
429
        ];
430
    }
431
}
432