Passed
Push — master ( 094188...b924bf )
by Dmitry
01:55
created

Request::own_private_key()   A

Complexity

Conditions 3
Paths 1

Size

Total Lines 16
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 6
nc 1
nop 0
dl 0
loc 16
rs 9.4285
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 file contents
177
     *
178
     *      @param string $fname
179
     *      @return string
180
     */
181
    protected function file_get_contents($fname)
182
    {
183
        return file_get_contents($fname);
184
    }
185
186
    /**
187
     *      Get private key for encode payload
188
     *
189
     *      @throws Exception\Runtime
190
     *      @return string
191
     */
192
    protected function own_private_key()
193
    {
194
        // check private key file
195
        if ( ! file_exists($this->jwt['our_privkey']))
196
        {
197
            throw new Exception\Runtime('The file with the private key was not find!');
198
        }
199
200
        // load private key file
201
        $private_key = $this->file_get_contents($this->jwt['our_privkey']);
202
        if ($private_key === FALSE)
203
        {
204
            throw new Exception\Runtime('The file with the private key was not read!');
205
        }
206
207
        return $private_key;
208
    }
209
210
    /**
211
     *      Encode payload and return token
212
     *
213
     *      @param array $payload
214
     *      @throws Exception\JSON
215
     *      @return string Token
216
     */
217 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...
218
    {
219
        Log::instance()->debug('encode payload:');
220
        Log::instance()->debug(print_r($payload, true));
221
        try
222
        {
223
            $token = JWT::encode($payload, $this->own_private_key(), 'RS512');
224
        }
225
        catch (\Exception $e)
226
        {
227
            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

227
            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...
228
            throw new Exception\JSON('unable to create JWT token', $e);
229
        }
230
231
        return $token;
232
    }
233
234
    /**
235
     *      Send request to UAPAY
236
     *
237
     *      @throws Exception\Transfer
238
     *      @return object Response
239
     */
240
    public function send()
241
    {
242
        Log::instance()->debug('send request to '.$this->api_path);
243
        try
244
        {
245
            $httpresponse = $this->client->request('POST', $this->api_path, [
246
                'headers' => [
247
                    'User-Agent'    => 'php_UAPAY/1.0',
248
                    'Content-Type'  => 'application/json'
249
                ],
250
                'body' => $this->get_json()
251
            ]);
252
            $body = $httpresponse->getBody()->getContents();
253
            Log::instance()->debug('got response:'.PHP_EOL.$body);
254
            $response = new $this->response_class($body, $this->jwt);
255
        }
256
        catch (\GuzzleHttp\Exception\TransferException $e)
257
        {
258
            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

258
            Log::instance()->debug('request:'.PHP_EOL.\GuzzleHttp\Psr7\str($e->/** @scrutinizer ignore-call */ getRequest()));
Loading history...
259
            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

259
            if ($e->/** @scrutinizer ignore-call */ hasResponse()) {
Loading history...
260
                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

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