· 7 years ago · Feb 08, 2018, 12:58 PM
1<?php
2namespace rsb;
3
4use Exception;
5use linker\establ\financialService;
6
7define(__NAMESPACE__ . '\DS', DIRECTORY_SEPARATOR);
8define(__NAMESPACE__ . '\SAVE_LOG', false);
9
10
11abstract class CMainCurl
12{
13 /**
14 * @var array
15 */
16 private $headers = [];
17 /**
18 * @var array
19 */
20 private $options = [];
21 /**
22 * @var null|resource
23 */
24 private $ch = null;
25
26 /**
27 * @return CMainCurl
28 */
29 protected function clearHeaders()
30 {
31 $this->headers = [];
32 return $this;
33 }
34
35 /**
36 * @return CMainCurl
37 */
38 protected function clearOptions()
39 {
40 $this->options = [];
41 return $this;
42 }
43
44 /**
45 * @param string $key
46 * @param string $value
47 * @return CMainCurl
48 */
49 protected function addOption($key, $value)
50 {
51 $this->options[$key] = $value;
52 return $this;
53 }
54
55 /**
56 * @return bool
57 */
58 protected function setOptions()
59 {
60 return \curl_setopt_array($this->ch, $this->getOptions());
61 }
62
63 /**
64 * @return array
65 */
66 protected function getOptions()
67 {
68 return $this->options;
69 }
70
71 /**
72 * @param string $key
73 * @param string $value
74 * @return bool
75 */
76 protected function addHeader($key, $value)
77 {
78 if (isset($this->headers[$key]) === true) {
79 return false;
80 }
81 $this->headers[$key] = $value;
82 return true;
83 }
84
85 /**
86 * @return array|bool
87 */
88 protected function getHeaderArrayCurl()
89 {
90 if (empty($this->headers) === true)
91 return false;
92 $result = [];
93 foreach ($this->headers as $nameHeader => $value) {
94 $result[] = $nameHeader . ': ' . $value;
95 }
96
97 return $result;
98 }
99
100 /**
101 * @param string|null $url
102 * @return false|resource
103 */
104 protected function createConnection($url = null)
105 {
106 return ($this->ch = \curl_init($url));
107 }
108
109 /**
110 * @return string|false
111 */
112 protected function executeConnection()
113 {
114 $execute = \curl_exec($this->ch);
115
116 return $execute;
117 }
118
119 /**
120 * @param string $login
121 * @param string $password
122 * @return bool
123 */
124 protected function setBasicAuth($login, $password)
125 {
126 return \curl_setopt($this->ch, \CURLOPT_USERPWD, $login . ':' . $password);
127 }
128
129 /**
130 * @return string
131 */
132 protected function getError()
133 {
134 return \curl_error($this->ch);
135 }
136
137 /**
138 * @param int|null $opt
139 * @return mixed
140 */
141 protected function getInfo($opt = null)
142 {
143 return \curl_getinfo($this->ch, $opt);
144 }
145
146 /**
147 * close Curl connection
148 */
149 protected function closeConnection()
150 {
151 \curl_close($this->ch);
152 }
153}
154
155interface ErrorsCodeCurl
156{
157 const OMG32423 = [
158 'ERROR' => 1,
159 ];
160}
161
162interface ErrorsCodeOpenSSL
163{
164 const OMG = [
165 'ERROR' => 1,
166 ];
167}
168
169final class BankException extends \Exception implements ErrorsCodeCurl, ErrorsCodeOpenSSL
170{
171 public function __construct($message = '', $code = 0, Exception $previous = null)
172 {
173 parent::__construct($message, $code, $previous);
174 }
175}
176
177final class CRsbBank extends CMainCurl
178{
179 const HOST = '194.67.29.216:8443';
180 const URL = 'https://' . self::HOST . '/';
181
182 const PRIVATE_KEY_FILE_EXPANSION = '.key';
183 const OPENSSL_ALGO = \OPENSSL_ALGO_SHA1;
184 const RESPONSE_CHARSET = 'windows-1251';
185 const DEFAULT_CHARSET = 'utf-8';
186
187
188 private static $listUser = [
189 'LIZING' => [
190 'login' => 'LIZING',
191 'password' => 'LIZING',
192 'passwordPrivateKey' => 'LIZING',
193 ],
194 'STARLIZING' => [
195 'login' => 'STARLIZING',
196 'password' => 'STARLIZING',
197 'passwordPrivateKey' => 'STARLIZING',
198 ],
199 ];
200
201 public function __construct()
202 {
203// static::OMG['ERROR'];
204 }
205
206 public function generateRequest($params, $user)
207 {
208 @set_time_limit(0);
209// header('Content-type: application/xml; charset=windows-1251');
210 header('Content-type: text/html; charset=' . self::RESPONSE_CHARSET);
211 $dataXmlString = $this->generateRequestData($params);
212
213// echo $dataXmlString;
214// var_dump($dataXmlString);
215// die();
216 $signature = $this->generateSignature($dataXmlString, $user, true);
217
218 $fullXml = $this->generateXML([
219 'requestString' => $dataXmlString,
220 'signatureString' => $signature,
221 ], 'request_full');
222
223 echo $fullXml, "\n\n\n";
224 if (SAVE_LOG === true) {
225 \logger\CLogger::addLog('bank_rsb',
226 'Тіло запиту:', $dataXmlString,
227 'ПідпиÑ:', $signature,
228 'Повний xml:', $fullXml);
229 }
230 $result = $this->send($fullXml, $user);
231 echo $result;
232 //todo обробка відповіді
233 $parseResult = $this->parseResult($result);
234 }
235
236
237 private function generateRequestData($params)
238 {
239 //todo Ð²Ð°Ð»Ñ–Ð´Ð°Ñ†Ñ–Ñ Ð¿Ð°Ñ€Ð°Ð¼ÐµÑ‚Ñ€Ñ–Ð²
240 $xml = $this->generateXML($params, 'request_body');
241 return $xml;
242 }
243
244 private function basicAuth($user)
245 {
246 if (empty($user) === true || $this->checkUser($user) === false) {
247 throw new \Exception('Ðе переданий кориÑтувач/КориÑтувач не знайдений');
248 }
249
250 $userData = $this->getUser($user);
251 return parent::setBasicAuth($userData['login'], $userData['password']);
252 }
253
254 private function send($requestXml, $user)
255 {
256 if (empty($user) === true) {
257 throw new \Exception('Ðе переданий $user');
258 }
259
260 if ($this->createConnection(self::URL) === false) {
261 throw new \Exception('Ðе можу Ñтворити curl:' . self::URL);
262 }
263 $this->clearHeaders();
264 $this->addHeader('Content-Type', 'text/xml');
265 $this->addHeader('Accept', 'text/xml');
266 $this->addHeader('Accept-Encoding', '*');
267 $this->addHeader('Pragma', 'no-cache');
268 $this->addHeader('User-Agent', 'Mozilla/4.0');
269 $this->addHeader('Cache-Control', 'no-cache');
270 $this->addHeader('Host', self::HOST);
271
272 $contentLength = \mb_strlen($requestXml, '8bit');
273 $this->addHeader('Content-Length', $contentLength);
274
275 $this->addHeader('Expect', '100-continue');
276 $this->addHeader('Connection', 'Keep-Alive');
277
278 $this->clearOptions()
279 ->addOption(\CURLINFO_HEADER_OUT, true)
280 ->addOption(\CURLOPT_RETURNTRANSFER, true)
281 ->addOption(\CURLOPT_POST, true)
282 ->addOption(\CURLOPT_POSTFIELDS, $requestXml)
283 ->addOption(\CURLOPT_CONNECTTIMEOUT, 60)
284 ->addOption(\CURLOPT_TIMEOUT, 60)
285 ->addOption(\CURLOPT_VERBOSE, true)
286 ->addOption(\CURLOPT_SSL_VERIFYHOST, 2)
287 ->addOption(\CURLOPT_SSL_VERIFYPEER, false)
288 ->addOption(\CURLOPT_HTTPHEADER, $this->getHeaderArrayCurl())
289 ->setOptions();
290
291 $this->basicAuth($user);
292 if (($data = $this->executeConnection()) === false) {
293 if (SAVE_LOG === true) {
294 \logger\CLogger::addLog('bank_rsb', 'CUrl не получив відповіді:', $this->getError(), $this->getInfo());
295 }
296
297 $this->closeConnection();
298 throw new \Exception('CUrl не получив відповіді:', $this->getError(), $this->getInfo());
299 }
300 $this->closeConnection();
301
302 return $data;
303 }
304
305 private function parseResult($xml)
306 {
307 if (empty($xml) === true) {
308 throw new \Exception('Переданий пуÑьтив xml відповіді');
309 }
310 if (($xmlObjectResponse = \simplexml_load_string($xml, 'SimpleXMLElement')) === false) {
311 throw new \Exception('Ðе мову відкрити XML, Ñкий прийшов у відповідь');
312 }
313
314 return $xmlObjectResponse;
315 }
316
317 private function generateXML($params, $file)
318 {
319 if (empty($params) === true || \is_array($params) === false) {
320 throw new \Exception('$params error:' . \print_r($params, true));
321 }
322
323 if (empty($file) === true) {
324 throw new \Exception('FileName is empty:' . $file);
325 }
326
327 $filePath = __DIR__ . DS . 'xml' . DS . $file . '.php';
328 if (\file_exists($filePath) === false) {
329 throw new \Exception('Файл не найдет:' . $filePath);
330 }
331
332 \ob_start();
333 \extract($params);
334 require($filePath);
335 $xml = \ob_get_clean();
336
337 return $xml;
338 }
339
340
341 private function generateSignature($xml, $user, $binToHex = true)
342 {
343 if (empty($xml) === true) {
344 throw new \Exception('Переданий пуÑтий xml.');
345 }
346 if (empty($user) === true || $this->checkUser($user) === false) {
347 throw new \Exception('Ðе переданий кориÑтувач/КориÑтувач не знайдений');
348 }
349
350 $pathToKey = __DIR__ . DS . 'privateKey' . DS . \mb_strtolower($user) . self::PRIVATE_KEY_FILE_EXPANSION;
351
352 if (\file_exists($pathToKey) === false) {
353 throw new \Exception('Ðе знайдений файл із приватним ключем:' . $pathToKey);
354 }
355
356 if (($privateKey = \file_get_contents($pathToKey)) === false) {
357 throw new \Exception('Ðе можу прочитати файл:' . $pathToKey);
358 }
359
360
361 $userData = $this->getUser($user);
362 if (($secretKey = \openssl_pkey_get_private($privateKey, $userData['passwordPrivateKey'])) === false) {
363 throw new \Exception('Ðе можу получити приватний ключ(openssl_pkey_get_private).');
364 }
365
366 if ((\openssl_sign($xml, $signature, $secretKey, self::OPENSSL_ALGO)) === false) {
367 throw new \Exception('Ðе можу згеренувати підпиÑ(openssl_sign).');
368 }
369
370 if ($binToHex === true) {
371 return \bin2hex($signature);
372 }
373
374 return $signature;
375 }
376
377 /**
378 * @param string $user
379 * @return bool
380 */
381 private function checkUser($user)
382 {
383 //todo перевідка Ñ–ÑÐ½ÑƒÐ²Ð°Ð½Ð½Ñ ÐºÐ¾Ñ€Ð¸Ñтувача
384 return (isset(self::$listUser[$user]) === true);
385 }
386
387 /**
388 * @param $user
389 * @return array|bool
390 */
391 private function getUser($user)
392 {
393 if ($this->checkUser($user) === true) {
394 return [
395 'login' => self::$listUser[$user]['login'],
396 'password' => self::$listUser[$user]['password'],
397 'passwordPrivateKey' => self::$listUser[$user]['passwordPrivateKey'],
398 ];
399 }
400 return false;
401 }
402
403 /**
404 * @param string $value
405 * @return string
406 */
407 public static function convertToBankCharset($value)
408 {
409 return \iconv(self::DEFAULT_CHARSET, self::RESPONSE_CHARSET, $value);
410 }
411
412 /**
413 * @param string $value
414 * @return string
415 */
416 public static function convertFromBankCharset($value)
417 {
418 return \iconv(self::RESPONSE_CHARSET, self::DEFAULT_CHARSET, $value);
419 }
420}
421
422
423-------------------------------------------------
424
425
426$class = new \rsb\CRsbBank();
427try {
428
429 $class->generateRequest([
430 //зарезервовано
431 'target' => 'client_system',
432 'operation' => 'AddRevPrePaid',
433
434 //ФІО
435 'clientsurname' => \rsb\CRsbBank::convertToBankCharset('Оверчук'),
436 'clientname' => \rsb\CRsbBank::convertToBankCharset('Михаил'),
437 'clientlastname' => \rsb\CRsbBank::convertToBankCharset('Олегович'),
438
439 'sex' => 1,
440 'birthday' => '08.06.1994',
441 'Born_country' => 1,
442 'bornplace' => \rsb\CRsbBank::convertToBankCharset('гор. Тамбов'),
443 'citizenship' => 1,
444 'changefio' => 0,
445 'idresident' => 1,
446 'isAnotherGrajd' => 0,
447 'AgreePersData' => 1,
448
449 /*
450 173: паÑпорт проÑрочен, не Ñовпадает ФИО , дата рождениÑ(еÑли в базе уже еÑть клиент Ñ Ñ‚Ð°ÐºÐ¸Ð¼Ð¸ же паÑпортными данными),недейÑтвительный паÑпорт по данным уфмÑ
451 * */
452 //паÑпорт
453 'docseries' => '7514', //Ð¡ÐµÑ€Ð¸Ñ Ð¿Ð°Ñпорта
454 'docnum' => '461997', //Ðомер паÑпорта
455 'docgive' => \rsb\CRsbBank::convertToBankCharset('отделением ÑƒÑ„Ð¼Ñ Ñ€Ð¾ÑÑии по ЧелÑбинÑкой облаÑти в ЧебаркульÑком районе'), //Кем выдан паÑпорт
456 'docgivedate' => '03.07.2014', //Дата выдачи паÑпорта в формате dd.mm.yyyy (не допуÑкать лишних пробелов)
457 'depcode' => '740-044',
458
459 'country_reg' => 1,
460 'postindex_reg' => 347640,
461 'region_reg' => \rsb\CRsbBank::convertToBankCharset('РоÑтовÑÐºÐ°Ñ Ð¾Ð±Ð»'),
462 'district_reg' => \rsb\CRsbBank::convertToBankCharset('СальÑкий Ñ€-н'),
463 'city_reg' => \rsb\CRsbBank::convertToBankCharset('СальÑк г'),
464 'settlement_reg' => '',
465 'street_reg' => \rsb\CRsbBank::convertToBankCharset('ÐйвазовÑкого'),
466 'street_reg_ext' => \rsb\CRsbBank::convertToBankCharset('ул'),
467 'housenumber_reg' => 8,
468 'housecase_reg' => '',
469 'appartment_reg' => '',
470 'idTimeReg' => 2,
471 'country_post' => 1,
472 'postindex_post' => 347640,
473 'region_post' => \rsb\CRsbBank::convertToBankCharset('РоÑтовÑÐºÐ°Ñ Ð¾Ð±Ð»'),
474 'district_post' => \rsb\CRsbBank::convertToBankCharset('СальÑкий Ñ€-н'),
475 'city_post' => \rsb\CRsbBank::convertToBankCharset('СальÑк г'),
476 'settlement_post' => 1,
477 'street_post' => \rsb\CRsbBank::convertToBankCharset('ÐйвазовÑкого'),
478 'street_post_ext' => \rsb\CRsbBank::convertToBankCharset('ул'),
479 'housenumber_post' => 8,
480 'housecase_post' => 8,
481
482
483 'appartment_post' => '9001260134',
484 'mobilphone' => '9001260134',
485 'POFDeclare' => 0,
486 'isPublicOfficer' => 1,
487 'codeword' => \rsb\CRsbBank::convertToBankCharset('codeword'),
488 'idcard' => '1000282867017',
489 //зарезервовано,завжди 3810
490 'currency' => 3810,
491
492 'amount' => 123.11,//12345.67
493 'transaction_id' => mt_rand(10000, 99999),
494 ], 'STARLIZING');
495} catch (\Exception $error) {
496 //todo має бути код помилки
497 echo 'Error:', $error->getMessage();
498}