1 | <?php |
||||
2 | |||||
3 | namespace PlatiOnline; |
||||
4 | |||||
5 | use sylouuu\Curl\Method as Curl; |
||||
6 | use phpseclib\Crypt\AES as AES; |
||||
7 | use phpseclib\Crypt\RSA as RSA; |
||||
8 | |||||
9 | class PO5 |
||||
10 | { |
||||
11 | // private |
||||
12 | private $f_request = null; |
||||
13 | private $f_secure = null; |
||||
14 | private $aes_key = null; |
||||
15 | private $iv = null; |
||||
16 | private $iv_itsn = null; |
||||
17 | private $rsa_key_enc = null; |
||||
18 | private $rsa_key_dec = null; |
||||
19 | private $url = 'https://secure.plationline.ro/'; |
||||
20 | private $url_sv_request_xml = 'https://secure.plationline.ro/xml_validation/po.request.v5.xsd'; // any call |
||||
21 | private $url_sv_auth_xml = 'https://secure.plationline.ro/xml_validation/f_message.auth.v5.xsd'; // auth |
||||
22 | private $url_sv_auth_url_xml = 'https://secure.plationline.ro/xml_validation/auth.url.response.v5.xsd'; // auth url |
||||
23 | private $url_sv_auth_response_xml = 'https://secure.plationline.ro/xml_validation/auth.response.v5.xsd'; // auth response |
||||
24 | private $url_sv_auth_response_soap_xml = 'https://secure.plationline.ro/xml_validation/auth.soap.response.v5.xsd';// auth response soap |
||||
0 ignored issues
–
show
introduced
by
![]() |
|||||
25 | private $url_sv_itsn_xml = 'https://secure.plationline.ro/xml_validation/itsn.v5.xsd'; // itsn |
||||
26 | private $url_sv_query_xml = 'https://secure.plationline.ro/xml_validation/f_message.query.v5.xsd'; // query |
||||
27 | private $url_sv_itsn_response_xml = 'https://secure.plationline.ro/xml_validation/query.response.v5.xsd'; // query response |
||||
28 | private $url_sv_query_by_date_xml = 'https://secure.plationline.ro/xml_validation/f_message.query-by-date.v5.xsd'; // query by date |
||||
29 | private $url_sv_query_by_date_response_xml = 'https://secure.plationline.ro/xml_validation/query-by-date.response.v5.xsd'; // query response |
||||
30 | private $url_sv_settle_xml = 'https://secure.plationline.ro/xml_validation/f_message.settle.v5.xsd'; // settle |
||||
31 | private $url_sv_settle_response_xml = 'https://secure.plationline.ro/xml_validation/settle.response.v5.xsd'; // settle response |
||||
32 | private $url_sv_void_xml = 'https://secure.plationline.ro/xml_validation/f_message.void.v5.xsd'; // void |
||||
33 | private $url_sv_void_response_xml = 'https://secure.plationline.ro/xml_validation/void.response.v5.xsd'; // void response |
||||
34 | private $url_sv_refund_xml = 'https://secure.plationline.ro/xml_validation/f_message.refund.v5.xsd'; // refund |
||||
35 | private $url_sv_refund_response_xml = 'https://secure.plationline.ro/xml_validation/refund.response.v5.xsd'; // refund response |
||||
36 | private $url_sv_paylink_xml = 'https://secure.plationline.ro/xml_validation/v5/f_message.paylink.xsd'; // paylink |
||||
37 | private $url_sv_paylink_response_xml = 'https://secure.plationline.ro/xml_validation/v5/pay.link.by.trxid.url.response.xsd'; // paylink response |
||||
38 | |||||
39 | // public |
||||
40 | public $f_login = null; |
||||
41 | public $version = null; |
||||
42 | public $test_mode = 0; |
||||
43 | |||||
44 | public function __construct() |
||||
45 | { |
||||
46 | $this->version = "PO 5.1.0 XML"; |
||||
47 | $errors = array(); |
||||
48 | $php_min_version = '5.5'; |
||||
49 | $curl_min_version = '7.29.0'; |
||||
50 | $openssl_min_version = 0x1000100f; //1.0.1 |
||||
51 | if (version_compare(phpversion(), $php_min_version, '<')) { |
||||
52 | $errors[] = 'PHP version ' . $php_min_version . ' is needed to use PlatiOnline kit. Current PHP version: ' . phpversion(); |
||||
53 | } |
||||
54 | if (!extension_loaded('soap')) { |
||||
55 | $errors[] = 'SOAP extension active is needed to use PlatiOnline kit. The SOAP extension is currently DISABLED!'; |
||||
56 | } |
||||
57 | if (!extension_loaded('curl')) { |
||||
58 | $errors[] = 'cURL extension active is needed to use PlatiOnline kit. The cURL extension is currently DISABLED!'; |
||||
59 | } |
||||
60 | if (version_compare(curl_version()['version'], $curl_min_version, '<')) { |
||||
61 | $errors[] = 'cURL version ' . $curl_min_version . ' is needed to use PlatiOnline kit. The cURL version is currently ' . curl_version()['version'] . '!'; |
||||
62 | } |
||||
63 | if (OPENSSL_VERSION_NUMBER < $openssl_min_version) { |
||||
64 | $errors[] = 'OpenSSL version 1.0.1 is needed to use PlatiOnline kit.'; |
||||
65 | } |
||||
66 | if (!empty($errors)) { //daca avem erori |
||||
67 | $errors_string = ''; |
||||
68 | foreach ($errors as $error) { |
||||
69 | $errors_string .= $error . "; "; |
||||
70 | } |
||||
71 | throw new \Exception($errors_string . 'Please fix the above mentioned errors to use this PlatiOnline kit'); |
||||
72 | } |
||||
73 | self::registerAutoload('phpseclib'); |
||||
74 | self::registerAutoload('Curl'); |
||||
75 | } |
||||
76 | |||||
77 | ////////////////////////////////////////////////////////////// |
||||
78 | // PUBLIC METHODS // |
||||
79 | ////////////////////////////////////////////////////////////// |
||||
80 | |||||
81 | // setez cheia RSA pentru criptare |
||||
82 | public function setRSAKeyEncrypt($rsa_key_enc) |
||||
83 | { |
||||
84 | $this->rsa_key_enc = $rsa_key_enc; |
||||
85 | } |
||||
86 | |||||
87 | // setez cheia RSA pentru decriptare |
||||
88 | public function setRSAKeyDecrypt($rsa_key_dec) |
||||
89 | { |
||||
90 | $this->rsa_key_dec = $rsa_key_dec; |
||||
91 | } |
||||
92 | |||||
93 | // setez initial vector |
||||
94 | public function setIV($iv) |
||||
95 | { |
||||
96 | $this->iv = $iv; |
||||
97 | } |
||||
98 | |||||
99 | // setez initial vector ITSN |
||||
100 | public function setIVITSN($iv) |
||||
101 | { |
||||
102 | $this->iv_itsn = $iv; |
||||
103 | } |
||||
104 | |||||
105 | public function paylink($f_request, $f_action = 21) |
||||
106 | { |
||||
107 | // ne asiguram ca stergem tot ce e in campul f_request |
||||
108 | $this->f_request = null; |
||||
109 | $f_request['f_action'] = $f_action; |
||||
110 | $request = $this->setFRequest($f_request, 'po_payment_link_by_trxid', $this->url_sv_paylink_xml); |
||||
111 | |||||
112 | $opts = array( |
||||
113 | 'http' => array( |
||||
114 | 'user_agent' => 'PlatiOnline-SOAP' |
||||
115 | ) |
||||
116 | ); |
||||
117 | $context = stream_context_create($opts); |
||||
118 | $client = new \SoapClient(null, array( |
||||
119 | 'location' => $this->url, |
||||
120 | 'uri' => 'pay-link-by-trxid', |
||||
121 | 'stream_context' => $context |
||||
122 | )); |
||||
123 | |||||
124 | $response = $client->__doRequest($request, $this->url, 'pay-link-by-trxid', 1); |
||||
125 | |||||
126 | if (empty($response)) { |
||||
127 | throw new \Exception('ERROR: Nu am putut comunica cu serverul PO pentru operatiunea de autorizare!'); |
||||
128 | } |
||||
129 | $this->validate_xml($response, $this->url_sv_paylink_response_xml); |
||||
130 | $paylink_response = $this->xml_to_object($response); |
||||
131 | |||||
132 | if ($this->get_xml_tag_content($paylink_response, 'PO_ERROR_CODE') == 1) { |
||||
133 | throw new \Exception($this->get_xml_tag_content($paylink_response, 'PO_ERROR_REASON')); |
||||
0 ignored issues
–
show
It seems like
$this->get_xml_tag_conte...nse, 'PO_ERROR_REASON') can also be of type false ; however, parameter $message of Exception::__construct() does only seem to accept string , 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
![]() |
|||||
134 | } else { |
||||
135 | $redirect_url = $this->get_xml_tag_content($paylink_response, 'PO_REDIRECT_URL'); |
||||
136 | $X_TRANS_ID = $this->get_xml_tag_content($paylink_response, 'X_TRANS_ID'); |
||||
0 ignored issues
–
show
|
|||||
137 | if (!empty($redirect_url)) { |
||||
138 | header('Location: ' . $redirect_url); |
||||
139 | } else { |
||||
140 | throw new \Exception('ERROR: Serverul nu a intors URL-ul pentru a finaliza tranzactia!'); |
||||
141 | } |
||||
142 | } |
||||
143 | } |
||||
144 | |||||
145 | public function auth($f_request, $f_action = 2) |
||||
146 | { |
||||
147 | // ne asiguram ca stergem tot ce e in campul f_request |
||||
148 | $this->f_request = null; |
||||
149 | $f_request['f_action'] = $f_action; |
||||
150 | $request = $this->setFRequest($f_request, 'po_auth_request', $this->url_sv_auth_xml); |
||||
151 | |||||
152 | $opts = array( |
||||
153 | 'http' => array( |
||||
154 | 'user_agent' => 'PlatiOnline-SOAP' |
||||
155 | ) |
||||
156 | ); |
||||
157 | $context = stream_context_create($opts); |
||||
158 | $client = new \SoapClient(null, array( |
||||
159 | 'location' => $this->url, |
||||
160 | 'uri' => 'auth-only', |
||||
161 | 'stream_context' => $context |
||||
162 | )); |
||||
163 | |||||
164 | $response = $client->__doRequest($request, $this->url, 'auth-only', 1); |
||||
165 | if (empty($response)) { |
||||
166 | throw new \Exception('ERROR: Nu am putut comunica cu serverul PO pentru operatiunea de autorizare!'); |
||||
167 | } |
||||
168 | |||||
169 | $this->validate_xml($response, $this->url_sv_auth_url_xml); |
||||
170 | $auth_response = $this->xml_to_object($response); |
||||
171 | if ($this->get_xml_tag_content($auth_response, 'PO_ERROR_CODE') == 1) { |
||||
172 | throw new \Exception($this->get_xml_tag_content($auth_response, 'PO_ERROR_REASON')); |
||||
0 ignored issues
–
show
It seems like
$this->get_xml_tag_conte...nse, 'PO_ERROR_REASON') can also be of type false ; however, parameter $message of Exception::__construct() does only seem to accept string , 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
![]() |
|||||
173 | } else { |
||||
174 | $redirect_url = $this->get_xml_tag_content($auth_response, 'PO_REDIRECT_URL'); |
||||
175 | if (!empty($redirect_url)) { |
||||
176 | header('Location: ' . $redirect_url); |
||||
177 | } else { |
||||
178 | throw new \Exception('ERROR: Serverul nu a intors URL-ul pentru a finaliza tranzactia!'); |
||||
179 | } |
||||
180 | } |
||||
181 | } |
||||
182 | |||||
183 | // obtin raspunsul pentru cererea de autorizare |
||||
184 | public function auth_response($f_relay_message, $f_crypt_message) |
||||
185 | { |
||||
186 | return $this->decrypt_response($f_relay_message, $f_crypt_message, $this->url_sv_auth_response_xml); |
||||
187 | } |
||||
188 | |||||
189 | // obtin datele din notificarea ITSN |
||||
190 | public function itsn($f_relay_message, $f_crypt_message) |
||||
191 | { |
||||
192 | return $this->decrypt_response($f_relay_message, $f_crypt_message, $this->url_sv_itsn_xml); |
||||
193 | } |
||||
194 | |||||
195 | // interogare |
||||
196 | public function query($f_request, $f_action = 0) |
||||
197 | { |
||||
198 | // ne asiguram ca stergem tot ce e in campul f_request |
||||
199 | $this->f_request = null; |
||||
200 | $f_request['f_action'] = $f_action; |
||||
201 | $request = $this->setFRequest($f_request, 'po_query', $this->url_sv_query_xml); |
||||
202 | |||||
203 | $opts = array( |
||||
204 | 'http' => array( |
||||
205 | 'user_agent' => 'PlatiOnline-SOAP' |
||||
206 | ) |
||||
207 | ); |
||||
208 | $context = stream_context_create($opts); |
||||
209 | $client = new \SoapClient(null, array( |
||||
210 | 'location' => $this->url, |
||||
211 | 'uri' => 'query', |
||||
212 | 'stream_context' => $context |
||||
213 | )); |
||||
214 | $response = $client->__doRequest($request, $this->url, 'query', 1); |
||||
215 | |||||
216 | if (empty($response)) { |
||||
217 | throw new \Exception('ERROR: Nu am putut comunica cu serverul PO pentru operatiunea de interogare!'); |
||||
218 | } |
||||
219 | // validez xml-ul primit ca raspuns de la PO |
||||
220 | $this->validate_xml($response, $this->url_sv_itsn_response_xml); |
||||
221 | return $this->xml_to_object($response); |
||||
222 | } |
||||
223 | |||||
224 | public function query_by_date($f_request, $f_action = 0) |
||||
225 | { |
||||
226 | // ne asiguram ca stergem tot ce e in campul f_request |
||||
227 | $this->f_request = null; |
||||
228 | $f_request['f_action'] = $f_action; |
||||
229 | $request = $this->setFRequest($f_request, 'po_query', $this->url_sv_query_by_date_xml); |
||||
230 | |||||
231 | $opts = array( |
||||
232 | 'http' => array( |
||||
233 | 'user_agent' => 'PlatiOnline-SOAP' |
||||
234 | ) |
||||
235 | ); |
||||
236 | $context = stream_context_create($opts); |
||||
237 | $client = new \SoapClient(null, array( |
||||
238 | 'location' => $this->url, |
||||
239 | 'uri' => 'query-by-date', |
||||
240 | 'stream_context' => $context |
||||
241 | )); |
||||
242 | $response = $client->__doRequest($request, $this->url, 'query-by-date', 1); |
||||
243 | if (empty($response)) { |
||||
244 | throw new \Exception('ERROR: Nu am putut comunica cu serverul PO pentru operatiunea de interogare!'); |
||||
245 | } |
||||
246 | // validez xml-ul primit ca raspuns de la PO |
||||
247 | $this->validate_xml($response, $this->url_sv_query_by_date_response_xml); |
||||
248 | return $this->xml_to_object($response); |
||||
249 | } |
||||
250 | |||||
251 | public function settle($f_request, $f_action = 3) |
||||
252 | { |
||||
253 | // ne asiguram ca stergem tot ce e in campul f_request |
||||
254 | $this->f_request = null; |
||||
255 | $f_request['f_action'] = $f_action; |
||||
256 | $request = $this->setFRequest($f_request, 'po_settle', $this->url_sv_settle_xml); |
||||
257 | |||||
258 | $opts = array( |
||||
259 | 'http' => array( |
||||
260 | 'user_agent' => 'PlatiOnline-SOAP' |
||||
261 | ) |
||||
262 | ); |
||||
263 | $context = stream_context_create($opts); |
||||
264 | $client = new \SoapClient(null, array( |
||||
265 | 'location' => $this->url, |
||||
266 | 'uri' => 'settle', |
||||
267 | 'stream_context' => $context |
||||
268 | )); |
||||
269 | $response = $client->__doRequest($request, $this->url, 'settle', 1); |
||||
270 | |||||
271 | if (empty($response)) { |
||||
272 | throw new \Exception('ERROR: Nu am putut comunica cu serverul PO pentru operatiunea de incasare!'); |
||||
273 | } |
||||
274 | |||||
275 | // validez xml-ul primit ca raspuns de la PO |
||||
276 | $this->validate_xml($response, $this->url_sv_settle_response_xml); |
||||
277 | |||||
278 | return $this->xml_to_object($response); |
||||
279 | } |
||||
280 | |||||
281 | public function void($f_request, $f_action = 7) |
||||
282 | { |
||||
283 | // ne asiguram ca stergem tot ce e in campul f_request |
||||
284 | $this->f_request = null; |
||||
285 | $f_request['f_action'] = $f_action; |
||||
286 | $request = $this->setFRequest($f_request, 'po_void', $this->url_sv_void_xml); |
||||
287 | |||||
288 | $opts = array( |
||||
289 | 'http' => array( |
||||
290 | 'user_agent' => 'PlatiOnline-SOAP' |
||||
291 | ) |
||||
292 | ); |
||||
293 | $context = stream_context_create($opts); |
||||
294 | $client = new \SoapClient(null, array( |
||||
295 | 'location' => $this->url, |
||||
296 | 'uri' => 'void', |
||||
297 | 'stream_context' => $context |
||||
298 | )); |
||||
299 | |||||
300 | $response = $client->__doRequest($request, $this->url, 'void', 1); |
||||
301 | |||||
302 | if (empty($response)) { |
||||
303 | throw new \Exception('ERROR: Nu am putut comunica cu serverul PO pentru operatiunea de anulare!'); |
||||
304 | } |
||||
305 | |||||
306 | // validez xml-ul primit ca raspuns de la PO |
||||
307 | $this->validate_xml($response, $this->url_sv_void_response_xml); |
||||
308 | |||||
309 | return $this->xml_to_object($response); |
||||
310 | } |
||||
311 | |||||
312 | public function refund($f_request, $f_action = 1) |
||||
313 | { |
||||
314 | // ne asiguram ca stergem tot ce e in campul f_request |
||||
315 | $this->f_request = null; |
||||
316 | $f_request['f_action'] = $f_action; |
||||
317 | $request = $this->setFRequest($f_request, 'po_refund', $this->url_sv_refund_xml); |
||||
318 | |||||
319 | $opts = array( |
||||
320 | 'http' => array( |
||||
321 | 'user_agent' => 'PlatiOnline-SOAP' |
||||
322 | ) |
||||
323 | ); |
||||
324 | $context = stream_context_create($opts); |
||||
325 | $client = new \SoapClient(null, array( |
||||
326 | 'location' => $this->url, |
||||
327 | 'uri' => 'refund', |
||||
328 | 'stream_context' => $context |
||||
329 | )); |
||||
330 | $response = $client->__doRequest($request, $this->url, 'refund', 1); |
||||
331 | |||||
332 | if (empty($response)) { |
||||
333 | throw new \Exception('ERROR: Nu am putut comunica cu serverul PO pentru operatiunea de creditare!'); |
||||
334 | } |
||||
335 | |||||
336 | // validez xml-ul primit ca raspuns de la PO |
||||
337 | $this->validate_xml($response, $this->url_sv_refund_response_xml); |
||||
338 | |||||
339 | return $this->xml_to_object($response); |
||||
340 | } |
||||
341 | |||||
342 | public function get_xml_tag($object, $tag) |
||||
343 | { |
||||
344 | $children = $object->children; |
||||
345 | foreach ($children as $child) { |
||||
346 | if (trim(strtoupper($child->name)) == trim(strtoupper($tag))) { |
||||
347 | return $child; |
||||
348 | } |
||||
349 | } |
||||
350 | return false; |
||||
351 | } |
||||
352 | |||||
353 | public function get_xml_tag_content($object, $tag) |
||||
354 | { |
||||
355 | $children = $object->children; |
||||
356 | foreach ($children as $child) { |
||||
357 | if (trim(strtoupper($child->name)) == trim(strtoupper($tag))) { |
||||
358 | return $child->content; |
||||
359 | } |
||||
360 | } |
||||
361 | return false; |
||||
362 | } |
||||
363 | |||||
364 | public function parse_soap_response($soap) |
||||
365 | { |
||||
366 | return $this->xml_to_object($soap); |
||||
367 | } |
||||
368 | |||||
369 | ////////////////////////////////////////////////////////////// |
||||
370 | // END PUBLIC METHODS // |
||||
371 | ////////////////////////////////////////////////////////////// |
||||
372 | |||||
373 | ////////////////////////////////////////////////////////////// |
||||
374 | // PRIVATE METHODS // |
||||
375 | ////////////////////////////////////////////////////////////// |
||||
376 | |||||
377 | private static function registerAutoload($classname) |
||||
0 ignored issues
–
show
The parameter
$classname is not used and could be removed.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check looks for parameters that have been defined for a function or method, but which are not used in the method body. ![]() |
|||||
378 | { |
||||
379 | spl_autoload_extensions('.php'); // Only Autoload PHP Files |
||||
380 | spl_autoload_register(function ($classname) { |
||||
381 | if (strpos($classname, '\\') !== false) { |
||||
382 | // Namespaced Classes |
||||
383 | $classfile = str_replace('\\', '/', $classname); |
||||
384 | if ($classname[0] !== '/') { |
||||
385 | $classfile = dirname(__FILE__) . '/libraries/' . $classfile . '.php'; |
||||
386 | } |
||||
387 | require($classfile); |
||||
388 | } |
||||
389 | }); |
||||
390 | } |
||||
391 | |||||
392 | // criptez f_request cu AES |
||||
393 | private function AESEnc() |
||||
394 | { |
||||
395 | $this->aes_key = substr(hash('sha256', uniqid(), 0), 0, 32); |
||||
396 | $aes = new AES(); |
||||
397 | $aes->setIV($this->iv); |
||||
398 | $aes->setKey($this->aes_key); |
||||
399 | $this->f_request = bin2hex(base64_encode($aes->encrypt($this->f_request))); |
||||
400 | } |
||||
401 | |||||
402 | // criptez cheia AES cu RSA |
||||
403 | private function RSAEnc() |
||||
404 | { |
||||
405 | $rsa = new RSA(); |
||||
406 | $rsa->loadKey($this->rsa_key_enc); |
||||
407 | $rsa->setEncryptionMode(RSA::ENCRYPTION_PKCS1); |
||||
408 | $this->f_secure = base64_encode($rsa->encrypt($this->aes_key)); |
||||
409 | } |
||||
410 | |||||
411 | // setez f_request, criptez f_request cu AES si cheia AES cu RSA |
||||
412 | private function setFRequest($f_request, $type, $validation_url) |
||||
413 | { |
||||
414 | // aici construiesc XML din array |
||||
415 | $xml = new \SimpleXMLElement('<' . $type . '/>'); |
||||
416 | |||||
417 | // test mode |
||||
418 | if ($type == 'po_auth_request') { |
||||
419 | if ($this->test_mode == 0) { |
||||
420 | $f_request['f_test_request'] = 0; |
||||
421 | } else { |
||||
422 | $f_request['f_test_request'] = 1; |
||||
423 | } |
||||
424 | |||||
425 | $f_request['f_sequence'] = rand(1, 1000); |
||||
426 | $f_request['f_customer_ip'] = $_SERVER['REMOTE_ADDR']; |
||||
427 | } |
||||
428 | |||||
429 | $f_request['f_timestamp'] = date('Y-m-d\TH:i:sP'); |
||||
430 | // set f_login |
||||
431 | $f_request['f_login'] = $this->f_login; |
||||
432 | |||||
433 | // sortez parametrii alfabetic |
||||
434 | ksort($f_request); |
||||
435 | |||||
436 | $this->array2xml($f_request, $xml); |
||||
437 | $this->f_request = $xml->asXML(); |
||||
438 | |||||
439 | // validez XML conform schemei (parametrul 2) |
||||
440 | $this->validate_xml($this->f_request, $validation_url); |
||||
441 | |||||
442 | $this->AESEnc(); |
||||
443 | $this->RSAEnc(); |
||||
444 | |||||
445 | $request = array(); |
||||
446 | |||||
447 | $request['f_login'] = $this->f_login; |
||||
448 | $request['f_message'] = $this->f_request; |
||||
449 | $request['f_crypt_message '] = $this->f_secure; |
||||
450 | |||||
451 | $xml_auth_soap = new \SimpleXMLElement('<po_request/>'); |
||||
452 | $this->array2xml($request, $xml_auth_soap); |
||||
453 | $xml_auth_soap = $xml_auth_soap->asXML(); |
||||
454 | $this->validate_xml($xml_auth_soap, $this->url_sv_request_xml); |
||||
455 | return $xml_auth_soap; |
||||
456 | } |
||||
457 | |||||
458 | // function definition to convert array to xml |
||||
459 | private function array2xml($arr, &$xml_arr) |
||||
460 | { |
||||
461 | foreach ($arr as $key => $value) { |
||||
462 | if (is_array($value)) { |
||||
463 | if (!is_numeric($key)) { |
||||
464 | if (strpos($key, 'coupon') !== false) { |
||||
465 | $subnode = $xml_arr->addChild("coupon"); |
||||
466 | } else { |
||||
467 | $subnode = $xml_arr->addChild("$key"); |
||||
468 | } |
||||
469 | $this->array2xml($value, $subnode); |
||||
470 | } else { |
||||
471 | $subnode = $xml_arr->addChild("item"); |
||||
472 | $this->array2xml($value, $subnode); |
||||
473 | } |
||||
474 | } else { |
||||
475 | $xml_arr->addChild("$key", htmlspecialchars("$value")); |
||||
476 | } |
||||
477 | } |
||||
478 | } |
||||
479 | |||||
480 | private function validate_xml($poxml, $url) |
||||
481 | { |
||||
482 | libxml_use_internal_errors(true); |
||||
483 | $xml = new \DOMDocument(); |
||||
484 | $xml->loadXML($poxml); |
||||
485 | $request = new Curl\Get($url); |
||||
486 | $request->send(); |
||||
487 | if ($request->getStatus() != 200) { |
||||
488 | throw new \Exception('Nu am putut obtine schema de validare de la PlatiOnline'); |
||||
489 | } |
||||
490 | $schemaPO5 = $request->getResponse(); |
||||
491 | if (!$xml->schemaValidateSource($schemaPO5)) { |
||||
492 | $errors = libxml_get_errors(); |
||||
493 | $finalmsg = array(); |
||||
0 ignored issues
–
show
|
|||||
494 | foreach ($errors as $error) { |
||||
495 | throw new \Exception($this->libxml_display_error($error)); |
||||
496 | } |
||||
497 | libxml_clear_errors(); |
||||
498 | throw new \Exception('INVALID XML'); |
||||
499 | } |
||||
500 | } |
||||
501 | |||||
502 | private function decrypt_response($f_relay_message, $f_crypt_message, $validation_url) |
||||
503 | { |
||||
504 | if (empty($f_relay_message)) { |
||||
505 | throw new \Exception('Decriptare raspuns - nu se primeste [criptul AES]'); |
||||
506 | } |
||||
507 | if (empty($f_crypt_message)) { |
||||
508 | throw new \Exception('Decriptare raspuns - nu se primeste [criptul RSA]'); |
||||
509 | } |
||||
510 | $rsa = new RSA(); |
||||
511 | $rsa->loadKey($this->rsa_key_dec); |
||||
512 | $rsa->setEncryptionMode(RSA::ENCRYPTION_PKCS1); |
||||
513 | $aes_key = $rsa->decrypt(base64_decode($f_crypt_message)); |
||||
514 | if (empty($aes_key)) { |
||||
515 | throw new \Exception('Nu am putut decripta cheia AES din RSA'); |
||||
516 | } |
||||
517 | $aes = new AES(); |
||||
518 | $aes->setIV($this->iv_itsn); |
||||
519 | $aes->setKey($aes_key); |
||||
520 | $response = $aes->decrypt(base64_decode($this->hex2str($f_relay_message))); |
||||
521 | if (empty($response)) { |
||||
522 | throw new \Exception('Nu am putut decripta mesajul din criptul AES'); |
||||
523 | } |
||||
524 | $this->validate_xml($response, $validation_url); |
||||
525 | return $this->xml_to_object($response); |
||||
526 | } |
||||
527 | |||||
528 | private function libxml_display_error($error) |
||||
529 | { |
||||
530 | $return = "\n"; |
||||
531 | switch ($error->level) { |
||||
532 | case LIBXML_ERR_WARNING: |
||||
533 | $return .= "Warning $error->code: "; |
||||
534 | break; |
||||
535 | case LIBXML_ERR_ERROR: |
||||
536 | $return .= "Error $error->code: "; |
||||
537 | break; |
||||
538 | case LIBXML_ERR_FATAL: |
||||
539 | $return .= "Fatal Error $error->code: "; |
||||
540 | break; |
||||
541 | } |
||||
542 | $return .= trim($error->message); |
||||
543 | $return .= "\n"; |
||||
544 | return $return; |
||||
545 | } |
||||
546 | |||||
547 | private function hex2str($hex) |
||||
548 | { |
||||
549 | $str = ''; |
||||
550 | for ($i=0;$i<strlen($hex);$i+=2) { |
||||
551 | $str .= chr(hexdec(substr($hex, $i, 2))); |
||||
0 ignored issues
–
show
It seems like
hexdec(substr($hex, $i, 2)) can also be of type double ; however, parameter $ascii of chr() does only seem to accept integer , 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
![]() |
|||||
552 | } |
||||
553 | return $str; |
||||
554 | } |
||||
555 | |||||
556 | private function xml_to_object($xml) |
||||
557 | { |
||||
558 | $parser = xml_parser_create(); |
||||
559 | xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0); |
||||
560 | xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1); |
||||
561 | xml_parse_into_struct($parser, $xml, $tags); |
||||
562 | xml_parser_free($parser); |
||||
563 | |||||
564 | $elements = array(); // the currently filling [child] XmlElement array |
||||
565 | $stack = array(); |
||||
566 | foreach ($tags as $tag) { |
||||
567 | $index = count($elements); |
||||
568 | if ($tag['type'] == "complete" || $tag['type'] == "open") { |
||||
569 | $elements[$index] = new XmlElement(); |
||||
570 | $elements[$index]->name = isset($tag['tag']) ? $tag['tag'] : ''; |
||||
571 | $elements[$index]->attributes = isset($tag['attributes']) ? $tag['attributes'] : ''; |
||||
572 | $elements[$index]->content = isset($tag['value']) ? $tag['value'] : ''; |
||||
573 | if ($tag['type'] == "open") { // push |
||||
574 | $elements[$index]->children = array(); |
||||
575 | $stack[count($stack)] = &$elements; |
||||
576 | $elements = &$elements[$index]->children; |
||||
577 | } |
||||
578 | } |
||||
579 | if ($tag['type'] == "close") { // pop |
||||
580 | $elements = &$stack[count($stack) - 1]; |
||||
581 | unset($stack[count($stack) - 1]); |
||||
582 | } |
||||
583 | } |
||||
584 | return $elements[0]; // the single top-level element |
||||
585 | } |
||||
586 | |||||
587 | ////////////////////////////////////////////////////////////// |
||||
588 | // END PRIVATE METHODS // |
||||
589 | ////////////////////////////////////////////////////////////// |
||||
590 | } |
||||
591 | |||||
592 | class XmlElement |
||||
593 | { |
||||
594 | public $name; |
||||
595 | public $attributes; |
||||
596 | public $content; |
||||
597 | public $children; |
||||
598 | }; |
||||
599 |