Passed
Push — master ( 419110...a41d9b )
by Dmitry
02:04
created

Request::own_private_key()   B

Complexity

Conditions 4
Paths 1

Size

Total Lines 22
Code Lines 10

Duplication

Lines 22
Ratio 100 %

Importance

Changes 0
Metric Value
cc 4
eloc 10
nc 1
nop 0
dl 22
loc 22
rs 8.9197
c 0
b 0
f 0
1
<?php
2
3
namespace UAPAY;
4
5
use UAPAY\Log as Log;
6
use UAPAY\Exception;
7
use Firebase\JWT\JWT;
8
9
abstract class Request
10
{
11
    /**
12
     *      @var object
13
     */
14
    protected $client;
15
16
    /**
17
     *      @var array
18
     */
19
    protected $jwt=array(
20
        'using'         => false,
21
        'UAPAY_pubkey'  => '',
22
        'our_privkey'   => '',
23
    );
24
25
    /**
26
     *      @var array
27
     */
28
    protected $data;
29
30
    /**
31
     *      Constructor
32
     *
33
     *      @param array $options array of options
34
     *      @throws Exception\Data
35
     */
36
    public function __construct($options)
37
    {
38
        // api_url
39
        if ( ! isset($options['api_uri']))
40
        {
41
            throw new Exception\Data('parameter api_uri is not specified');
42
        }
43
44
        if (isset($options['jwt']))
45
        {
46
            // using
47
            if ( ! isset($options['jwt']['using']))
48
            {
49
                throw new Exception\Data('parameter jwt/using is not specified');
50
            }
51
            if ( ! is_bool($options['jwt']['using']))
52
            {
53
                throw new Exception\Data('parameter jwt/using is incorrect');
54
            }
55
            // using
56
            if ( ! isset($options['jwt']['UAPAY_pubkey']))
57
            {
58
                throw new Exception\Data('parameter jwt/UAPAY_pubkey is not specified');
59
            }
60
            // using
61
            if ( ! isset($options['jwt']['our_privkey']))
62
            {
63
                throw new Exception\Data('parameter jwt/our_privkey is not specified');
64
            }
65
66
            $this->jwt = $options['jwt'];
67
        }
68
69
        // http client
70
        $this->client = new \GuzzleHttp\Client([
71
            'base_uri'      => $options['api_uri'],
72
            'timeout'       => 2.0,
73
        ]);
74
    }
75
76
    /**
77
     *      get/set data
78
     *
79
     *      @param array $value
80
     *      @return array
81
     */
82
    public function data($value=null)
83
    {
84
        if ($value !== null)
85
        {
86
            $this->data = $this->as_array($value);
87
        }
88
89
        return $this->data;
90
    }
91
92
    /**
93
     *      Cast to string
94
     *
95
     *      @param mixed $value
96
     *      @return string
97
     */
98
    protected function as_string($value=null)
99
    {
100
        return (is_scalar($value))?((is_bool($value))?(($value)?'true':'false'):"$value"):null;
101
    }
102
103
    /**
104
     *      Cast to integer
105
     *
106
     *      @param mixed $value
107
     *      @return integer
108
     */
109
    protected function as_int($value=null)
110
    {
111
        return (is_int($value))?$value:null;
112
    }
113
114
    /**
115
     *      Cast to array
116
     *
117
     *      @param mixed $value
118
     *      @return array
119
     */
120
    protected function as_array($value=null)
121
    {
122
        return (is_array($value))?$value:null;
123
    }
124
125
    /**
126
     *      Returns params set
127
     *
128
     *      @return array
129
     */
130
    public function get_params()
131
    {
132
        return array();
133
    }
134
135
    /**
136
     *      Returns iat param
137
     *
138
     *      @return array
139
     */
140
    public function get_param_iat()
141
    {
142
        return time();
0 ignored issues
show
Bug Best Practice introduced by
The expression return time() returns the type integer which is incompatible with the documented return type array.
Loading history...
143
    }
144
145
    /**
146
     *      Returns the JSON representation of class
147
     *
148
     *      @return string
149
     */
150
    public function get_json()
151
    {
152
        $ar = array(
153
            'params' => $this->get_params()
154
        );
155
        if (isset($this->data))
156
        {
157
            $ar['data'] = $this->data;
158
        }
159
        if ($this->jwt['using'] === true)
160
        {
161
            $payload = $ar;
162
            $payload['iat'] = $this->get_param_iat();
163
            $ar['token'] = $this->token_encode($payload);
164
165
            if (isset($ar['data'])) unset($ar['data']);
166
        }
167
        $json = json_encode($ar, JSON_UNESCAPED_SLASHES);
168
169
        Log::instance()->debug('build JSON:');
0 ignored issues
show
Bug introduced by
The method debug() does not exist on UAPAY\Log. ( Ignorable by Annotation )

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

169
        Log::instance()->/** @scrutinizer ignore-call */ debug('build JSON:');

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
170
        Log::instance()->debug($json);
171
172
        return $json;
173
    }
174
175
    /**
176
     *      Get private key for encode payload
177
     *
178
     *      @throws Exception\Runtime
179
     *      @return string
180
     */
181 View Code Duplication
    protected function own_private_key()
0 ignored issues
show
Duplication introduced by
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...
182
    {
183
        // check private key file
184
        if ( ! file_exists($this->jwt['our_privkey']))
185
        {
186
            throw new Exception\Runtime('The file with the private key was not find!');
187
        }
188
189
        // load private key file
190
        $fpkey = fopen($this->jwt['our_privkey'], "rb");
191
        if ($fpkey === FALSE)
192
        {
193
            throw new Exception\Runtime('The file with the private key was not open!');
194
        }
195
        $private_key = fread($fpkey, 8192);
196
        if ($private_key === FALSE)
197
        {
198
            throw new Exception\Runtime('The file with the private key was not read!');
199
        }
200
        fclose($fpkey);
201
202
        return $private_key;
203
    }
204
205
    /**
206
     *      Encode payload and return token
207
     *
208
     *      @param array $payload
209
     *      @throws Exception\JSON
210
     *      @return string Token
211
     */
212 View Code Duplication
    protected function token_encode($payload)
0 ignored issues
show
Duplication introduced by
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...
213
    {
214
        Log::instance()->debug('encode payload:');
215
        Log::instance()->debug(print_r($payload, true));
216
        try
217
        {
218
            $token = JWT::encode($payload, $this->own_private_key(), 'RS512');
219
        }
220
        catch (\Exception $e)
221
        {
222
            Log::instance()->error($e->getMessage().PHP_EOL.$e->getTraceAsString());
0 ignored issues
show
Bug introduced by
The method error() does not exist on UAPAY\Log. ( Ignorable by Annotation )

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

222
            Log::instance()->/** @scrutinizer ignore-call */ error($e->getMessage().PHP_EOL.$e->getTraceAsString());

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
223
            throw new Exception\JSON('unable to create JWT token', $e);
224
        }
225
226
        return $token;
227
    }
228
229
    /**
230
     *      Send request to UAPAY
231
     *
232
     *      @throws Exception\Transfer
233
     *      @return object Response
234
     */
235
    public function send()
236
    {
237
        Log::instance()->debug('send request to '.$this->api_path);
238
        try
239
        {
240
            $httpresponse = $this->client->request('POST', $this->api_path, [
241
                'headers' => [
242
                    'User-Agent'    => 'php_UAPAY/1.0',
243
                    'Content-Type'  => 'application/json'
244
                ],
245
                'body' => $this->get_json()
246
            ]);
247
            $body = $httpresponse->getBody()->getContents();
248
            Log::instance()->debug('got response:'.PHP_EOL.$body);
249
            $response = new $this->response_class($body, $this->jwt);
250
        }
251
        catch (\GuzzleHttp\Exception\TransferException $e)
252
        {
253
            Log::instance()->debug('request:'.PHP_EOL.\GuzzleHttp\Psr7\str($e->getRequest()));
0 ignored issues
show
introduced by
The method getRequest() does not exist on GuzzleHttp\Exception\TransferException. Are you sure you never get this type here, but always one of the subclasses? ( Ignorable by Annotation )

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

253
            Log::instance()->debug('request:'.PHP_EOL.\GuzzleHttp\Psr7\str($e->/** @scrutinizer ignore-call */ getRequest()));
Loading history...
254
            if ($e->hasResponse()) {
0 ignored issues
show
introduced by
The method hasResponse() does not exist on GuzzleHttp\Exception\TransferException. Are you sure you never get this type here, but always one of the subclasses? ( Ignorable by Annotation )

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

254
            if ($e->/** @scrutinizer ignore-call */ hasResponse()) {
Loading history...
255
                Log::instance()->debug('response:'.PHP_EOL.\GuzzleHttp\Psr7\str($e->getResponse()));
0 ignored issues
show
introduced by
The method getResponse() does not exist on GuzzleHttp\Exception\TransferException. Are you sure you never get this type here, but always one of the subclasses? ( Ignorable by Annotation )

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

255
                Log::instance()->debug('response:'.PHP_EOL.\GuzzleHttp\Psr7\str($e->/** @scrutinizer ignore-call */ getResponse()));
Loading history...
256
            }
257
258
            throw new Exception\Transfer('an error occured during a transfer');
259
        }
260
261
        return $response;
262
    }
263
}
264