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
|
|
|
$jo = new JWTOptions($options); |
45
|
|
|
$this->jwt = $jo->get(); |
46
|
|
|
|
47
|
|
|
// http client |
48
|
|
|
$this->client = new \GuzzleHttp\Client([ |
49
|
|
|
'base_uri' => $options['api_uri'], |
50
|
|
|
'timeout' => 2.0, |
51
|
|
|
]); |
52
|
|
|
} |
53
|
|
|
|
54
|
|
|
/** |
55
|
|
|
* get/set data |
56
|
|
|
* |
57
|
|
|
* @param array $value |
58
|
|
|
* @return array |
59
|
|
|
*/ |
60
|
|
|
public function data($value=null) |
61
|
|
|
{ |
62
|
|
|
if ($value !== null) |
63
|
|
|
{ |
64
|
|
|
$this->data = $this->as_array($value); |
65
|
|
|
} |
66
|
|
|
|
67
|
|
|
return $this->data; |
68
|
|
|
} |
69
|
|
|
|
70
|
|
|
/** |
71
|
|
|
* Cast to string |
72
|
|
|
* |
73
|
|
|
* @param mixed $value |
74
|
|
|
* @return string |
75
|
|
|
*/ |
76
|
|
|
protected function as_string($value=null) |
77
|
|
|
{ |
78
|
|
|
return (is_scalar($value))?((is_bool($value))?(($value)?'true':'false'):"$value"):null; |
79
|
|
|
} |
80
|
|
|
|
81
|
|
|
/** |
82
|
|
|
* Cast to integer |
83
|
|
|
* |
84
|
|
|
* @param mixed $value |
85
|
|
|
* @return integer |
86
|
|
|
*/ |
87
|
|
|
protected function as_int($value=null) |
88
|
|
|
{ |
89
|
|
|
return (is_int($value))?$value:null; |
90
|
|
|
} |
91
|
|
|
|
92
|
|
|
/** |
93
|
|
|
* Cast to array |
94
|
|
|
* |
95
|
|
|
* @param mixed $value |
96
|
|
|
* @return array |
97
|
|
|
*/ |
98
|
|
|
protected function as_array($value=null) |
99
|
|
|
{ |
100
|
|
|
return (is_array($value))?$value:null; |
101
|
|
|
} |
102
|
|
|
|
103
|
|
|
/** |
104
|
|
|
* Returns params set |
105
|
|
|
* |
106
|
|
|
* @return array |
107
|
|
|
*/ |
108
|
|
|
public function get_params() |
109
|
|
|
{ |
110
|
|
|
return array(); |
111
|
|
|
} |
112
|
|
|
|
113
|
|
|
/** |
114
|
|
|
* Returns iat param |
115
|
|
|
* |
116
|
|
|
* @return integer |
117
|
|
|
*/ |
118
|
|
|
public function get_param_iat() |
119
|
|
|
{ |
120
|
|
|
return time(); |
121
|
|
|
} |
122
|
|
|
|
123
|
|
|
/** |
124
|
|
|
* Returns the JSON representation of class |
125
|
|
|
* |
126
|
|
|
* @return string |
127
|
|
|
*/ |
128
|
|
|
public function get_json() |
129
|
|
|
{ |
130
|
|
|
$ar = array( |
131
|
|
|
'params' => $this->get_params() |
132
|
|
|
); |
133
|
|
|
if (isset($this->data)) |
134
|
|
|
{ |
135
|
|
|
$ar['data'] = $this->data; |
136
|
|
|
} |
137
|
|
|
if ($this->jwt['using'] === true) |
138
|
|
|
{ |
139
|
|
|
$payload = $ar; |
140
|
|
|
$payload['iat'] = $this->get_param_iat(); |
141
|
|
|
$ar['token'] = $this->token_encode($payload); |
142
|
|
|
|
143
|
|
|
if (isset($ar['data'])) unset($ar['data']); |
144
|
|
|
} |
145
|
|
|
$json = json_encode($ar, JSON_UNESCAPED_SLASHES); |
146
|
|
|
|
147
|
|
|
Log::instance()->debug('build JSON:'); |
148
|
|
|
Log::instance()->debug($json); |
149
|
|
|
|
150
|
|
|
return $json; |
151
|
|
|
} |
152
|
|
|
|
153
|
|
|
/** |
154
|
|
|
* Get private key for encode payload |
155
|
|
|
* |
156
|
|
|
* @return string |
157
|
|
|
*/ |
158
|
|
|
protected function own_private_key() |
159
|
|
|
{ |
160
|
|
|
return (new Key())->get($this->jwt['our_privkey'], 'private'); |
161
|
|
|
} |
162
|
|
|
|
163
|
|
|
/** |
164
|
|
|
* Encode payload and return token |
165
|
|
|
* |
166
|
|
|
* @param array $payload |
167
|
|
|
* @throws Exception\JSON |
168
|
|
|
* @return string Token |
169
|
|
|
*/ |
170
|
|
View Code Duplication |
protected function token_encode($payload) |
|
|
|
|
171
|
|
|
{ |
172
|
|
|
Log::instance()->debug('encode payload:'); |
173
|
|
|
Log::instance()->debug(print_r($payload, true)); |
174
|
|
|
try |
175
|
|
|
{ |
176
|
|
|
$token = JWT::encode($payload, $this->own_private_key(), 'RS512'); |
177
|
|
|
} |
178
|
|
|
catch (\Exception $e) |
179
|
|
|
{ |
180
|
|
|
Log::instance()->error($e->getMessage().PHP_EOL.$e->getTraceAsString()); |
181
|
|
|
throw new Exception\JSON('unable to create JWT token', $e); |
182
|
|
|
} |
183
|
|
|
|
184
|
|
|
return $token; |
185
|
|
|
} |
186
|
|
|
|
187
|
|
|
/** |
188
|
|
|
* Send request to UAPAY |
189
|
|
|
* |
190
|
|
|
* @return object Response |
191
|
|
|
*/ |
192
|
|
|
public function send() |
193
|
|
|
{ |
194
|
|
|
Log::instance()->add('send request to '.$this->api_path); |
195
|
|
|
try |
196
|
|
|
{ |
197
|
|
|
$httpresponse = $this->client->request('POST', $this->api_path, [ |
198
|
|
|
'headers' => [ |
199
|
|
|
'User-Agent' => 'php_UAPAY/1.0', |
200
|
|
|
'Content-Type' => 'application/json' |
201
|
|
|
], |
202
|
|
|
'body' => $this->get_json() |
203
|
|
|
]); |
204
|
|
|
$body = $httpresponse->getBody()->getContents(); |
205
|
|
|
Log::instance()->debug('got response:'.PHP_EOL.$body); |
206
|
|
|
return new $this->response_class($body, $this->jwt); |
207
|
|
|
} |
208
|
|
|
catch (\GuzzleHttp\Exception\RequestException $e) |
209
|
|
|
{ |
210
|
|
|
$this->handle_request_exception($e); |
211
|
|
|
} |
212
|
|
|
} |
213
|
|
|
|
214
|
|
|
/** |
215
|
|
|
* Handle request exception |
216
|
|
|
* |
217
|
|
|
* @param \GuzzleHttp\Exception\RequestException $e |
218
|
|
|
* @throws Exception\Transfer |
219
|
|
|
*/ |
220
|
|
|
protected function handle_request_exception($e) |
221
|
|
|
{ |
222
|
|
|
Log::instance()->debug('request:'.PHP_EOL.\GuzzleHttp\Psr7\str($e->getRequest())); |
223
|
|
|
if ($e->hasResponse()) { |
224
|
|
|
Log::instance()->debug('response:'.PHP_EOL.\GuzzleHttp\Psr7\str($e->getResponse())); |
225
|
|
|
} |
226
|
|
|
|
227
|
|
|
throw new Exception\Transfer('an error occured during a transfer'); |
228
|
|
|
} |
229
|
|
|
} |
230
|
|
|
|
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.