api.opayz.php 37 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118
  1. <?php
  2. /**
  3. * Basic OpenPayz implementation
  4. */
  5. class OpenPayz {
  6. /**
  7. * Contains available virtualid=>realid mappings
  8. *
  9. * @var array
  10. */
  11. protected $allCustomers = array();
  12. /**
  13. * Contains existing transactions data
  14. *
  15. * @var array
  16. */
  17. protected $allTransactions = array();
  18. /**
  19. * Existing payment systems names
  20. *
  21. * @var array
  22. */
  23. protected $allPaySys = array();
  24. /**
  25. * Contains system alter.ini config as key=>value
  26. *
  27. * @var array
  28. */
  29. protected $altCfg = array();
  30. /**
  31. * Contains available users address data as login=>address
  32. *
  33. * @var array
  34. */
  35. protected $allAddress = array();
  36. /**
  37. * Contains available users realnames as login=>realname
  38. *
  39. * @var array
  40. */
  41. protected $allRealnames = array();
  42. /**
  43. * System message helper object placeholder
  44. *
  45. * @var object
  46. */
  47. protected $messages = '';
  48. /**
  49. * Placeholder for UbillingConfig object
  50. *
  51. * @var object
  52. */
  53. protected $ubConfig = '';
  54. /**
  55. * Placeholder for OP_SMS_NOTIFY_PAYMENTS_PULL_INTERVAL alter.ini option
  56. *
  57. * @var int
  58. */
  59. protected $smsNotysPullInterval = 10;
  60. /**
  61. * Placeholder for OP_SMS_NOTIFY_USE_EXTMOBILES alter.ini option
  62. *
  63. * @var bool
  64. */
  65. protected $smsUseExtMobiles = false;
  66. /**
  67. * Placeholder for OP_SMS_NOTIFY_FORCED_TRANSLIT alter.ini option
  68. *
  69. * @var bool
  70. */
  71. protected $smsForceTranslit = false;
  72. /**
  73. * Placeholder for OP_SMS_NOTIFY_DEBUG_ON alter.ini option
  74. *
  75. * @var bool
  76. */
  77. protected $smsDebugON = false;
  78. /**
  79. * Placeholder for OP_SMS_NOTIFY_TEXT alter.ini option
  80. *
  81. * @var string
  82. */
  83. protected $smsNotysText = '';
  84. /**
  85. * Placeholder for OP_SMS_NOTIFY_RESPECT_REMINDER_TAGID alter.ini option
  86. *
  87. * @var bool
  88. */
  89. protected $smsRespectReminderTagID = false;
  90. /**
  91. * Placeholder for REMINDER_TAGID alter.ini option
  92. *
  93. * @var int
  94. */
  95. protected $smsReminderTagID = 0;
  96. /**
  97. * All users tags to use if $smsRespectReminderTagID is true
  98. *
  99. * @var array
  100. */
  101. protected $allUsersTags = array();
  102. /**
  103. * Customers database abstraction layer placeholder
  104. *
  105. * @var object
  106. */
  107. protected $customersDb = '';
  108. /**
  109. * Transactions database abstraction layer placeholder
  110. *
  111. * @var object
  112. */
  113. protected $transactionsDb = '';
  114. /**
  115. * Static customers database abstraction layer placeholder
  116. *
  117. * @var object
  118. */
  119. protected $staticDb = '';
  120. /**
  121. * Length of generated static payment ID
  122. *
  123. * @var int
  124. */
  125. protected $payidStaticLen = 0;
  126. /**
  127. * Prefix for newly generated static payment IDs
  128. *
  129. * @var string
  130. */
  131. protected $payIdStaticPrefix = '';
  132. /**
  133. * Funds flow instance placeholder
  134. *
  135. * @var object
  136. */
  137. protected $fundsFlow = '';
  138. /**
  139. * System caching object placeholder
  140. *
  141. * @var object
  142. */
  143. protected $cache = '';
  144. /**
  145. * Default cached data timeout. May be configurable in future?
  146. *
  147. * @var int
  148. */
  149. protected $cacheTimeout = 86400;
  150. /**
  151. * Transactions list ajax callback URL
  152. */
  153. const URL_AJAX_SOURCE = '?module=openpayz&ajax=true';
  154. /**
  155. * Payment systems charts URL
  156. */
  157. const URL_CHARTS = '?module=openpayz&graphs=true';
  158. /**
  159. * Default module URL
  160. */
  161. const URL_ME = '?module=openpayz';
  162. /**
  163. * Some other predefined stuff
  164. */
  165. const TABLE_CUSTOMERS = 'op_customers';
  166. const TABLE_TRANSACTIONS = 'op_transactions';
  167. const TABLE_STATIC = 'op_static';
  168. const KEY_PSYS = 'OPPAYSYS';
  169. const KEY_CHARTS = 'OPCHARTS_';
  170. /**
  171. * Creates new OpenPayz instance
  172. *
  173. * @param bool $loadPaySys
  174. * @param bool $loadCustomers
  175. *
  176. * @return void
  177. */
  178. public function __construct($loadPaySys = false, $loadCustomers = false) {
  179. global $ubillingConfig;
  180. $this->ubConfig = $ubillingConfig;
  181. $this->loadAlter();
  182. $this->loadOptions();
  183. $this->initMessages();
  184. $this->initDbLayers();
  185. $this->initCache();
  186. //preloading some optional data
  187. if ($loadPaySys) {
  188. $this->loadPaySys();
  189. }
  190. if ($loadCustomers) {
  191. $this->loadCustomers();
  192. }
  193. if ($this->smsRespectReminderTagID) {
  194. $this->allUsersTags = zb_UserGetAllTags();
  195. }
  196. }
  197. /**
  198. * Loads global alter config into protected property
  199. *
  200. * @global object $ubillingConfig
  201. *
  202. * @return void
  203. */
  204. protected function loadAlter() {
  205. global $ubillingConfig;
  206. $this->altCfg = $ubillingConfig->getAlter();
  207. }
  208. /**
  209. * Getting an alter.ini options
  210. */
  211. protected function loadOptions() {
  212. $this->smsNotysPullInterval = ubRouting::filters($this->ubConfig->getAlterParam('OP_SMS_NOTIFY_PAYMENTS_PULL_INTERVAL', 5), 'int');
  213. $this->smsUseExtMobiles = ubRouting::filters($this->ubConfig->getAlterParam('OP_SMS_NOTIFY_USE_EXTMOBILES'), 'fi', FILTER_VALIDATE_BOOLEAN);
  214. $this->smsForceTranslit = ubRouting::filters($this->ubConfig->getAlterParam('OP_SMS_NOTIFY_FORCED_TRANSLIT'), 'fi', FILTER_VALIDATE_BOOLEAN);
  215. $this->smsDebugON = ubRouting::filters($this->ubConfig->getAlterParam('OP_SMS_NOTIFY_DEBUG_ON'), 'fi', FILTER_VALIDATE_BOOLEAN);
  216. $this->smsNotysText = $this->ubConfig->getAlterParam('OP_SMS_NOTIFY_TEXT', '');
  217. $this->smsRespectReminderTagID = ubRouting::filters($this->ubConfig->getAlterParam('OP_SMS_NOTIFY_RESPECT_REMINDER_TAGID'), 'fi', FILTER_VALIDATE_BOOLEAN);
  218. $this->smsReminderTagID = ubRouting::filters($this->ubConfig->getAlterParam('REMINDER_TAGID', 0), 'int');
  219. $this->payidStaticLen = ubRouting::filters($this->ubConfig->getAlterParam('OPENPAYZ_STATIC_ID', 0), 'int');
  220. $this->payIdStaticPrefix = $this->ubConfig->getAlterParam('OPENPAYZ_STATIC_ID_PREFIX', '');
  221. }
  222. /**
  223. * Inits all required database abstraction layers
  224. *
  225. * @return void
  226. */
  227. protected function initDbLayers() {
  228. $this->customersDb = new NyanORM(self::TABLE_CUSTOMERS);
  229. $this->transactionsDb = new NyanORM(self::TABLE_TRANSACTIONS);
  230. $this->staticDb = new NyanORM(self::TABLE_STATIC);
  231. }
  232. /**
  233. * Inits Ubilling caching engine for further usage
  234. *
  235. * @return void
  236. */
  237. protected function initCache() {
  238. $this->cache = new UbillingCache();
  239. }
  240. /**
  241. * Loads users address list into protected property
  242. *
  243. * @return void
  244. */
  245. protected function loadAddress() {
  246. $this->allAddress = zb_AddressGetFulladdresslistCached();
  247. }
  248. /**
  249. * Loads users realnames list into protected property
  250. *
  251. * @return void
  252. */
  253. protected function loadRealname() {
  254. $this->allRealnames = zb_UserGetAllRealnames();
  255. }
  256. /**
  257. * Loads all op_customers from database into protected prop
  258. *
  259. * @return void
  260. */
  261. protected function loadCustomers() {
  262. $allCustomers = $this->customersDb->getAll();
  263. if (!empty($allCustomers)) {
  264. foreach ($allCustomers as $io => $eachcustomer) {
  265. $this->allCustomers[$eachcustomer['virtualid']] = $eachcustomer['realid'];
  266. }
  267. }
  268. }
  269. /**
  270. * Loads available openpayz transactions into private data property
  271. *
  272. * @param int $year
  273. * @param int $transactionId
  274. *
  275. * @return void
  276. */
  277. protected function loadTransactions($year = '', $transactionId = 0) {
  278. $year = ubRouting::filters($year, 'int');
  279. $transactionId = ubRouting::filters($transactionId, 'int');
  280. if (!empty($year) and $year != '1488') {
  281. $this->transactionsDb->where('date', 'LIKE', $year . '-%');
  282. }
  283. if ($transactionId) {
  284. //only one transaction
  285. $this->transactionsDb->where('id', '=', $transactionId);
  286. } else {
  287. //or natural ordering?
  288. $this->transactionsDb->orderBy('id', 'ASC');
  289. }
  290. $this->allTransactions = $this->transactionsDb->getAll('id');
  291. }
  292. /**
  293. * Public getter of preloaded users mappings as paymentId=>userLogin
  294. *
  295. * @return array
  296. */
  297. public function getCustomers() {
  298. if (empty($this->allCustomers)) {
  299. $this->loadCustomers();
  300. }
  301. return ($this->allCustomers);
  302. }
  303. /**
  304. * Public getter of preloaded users mappings as userLogin=>paymentId
  305. *
  306. * @return array
  307. */
  308. public function getCustomersPaymentIds() {
  309. $result = array();
  310. if (empty($this->allCustomers)) {
  311. $this->loadCustomers();
  312. }
  313. if (!empty($this->allCustomers)) {
  314. $result = array_flip($this->allCustomers);
  315. }
  316. return ($result);
  317. }
  318. /**
  319. * Returns some specified user paymentId
  320. *
  321. * @param string $userLogin
  322. *
  323. * @return string
  324. */
  325. public function getCustomerPaymentId($userLogin) {
  326. $result = '';
  327. $userLogin = ubRouting::filters($userLogin, 'mres');
  328. if (!empty($this->allCustomers)) {
  329. //already preloaded from database
  330. $tmp = array_flip($this->allCustomers);
  331. if (isset($tmp[$userLogin])) {
  332. $result = $tmp[$userLogin];
  333. }
  334. } else {
  335. //not loaded at start, performing database query
  336. $this->customersDb->where('realid', '=', $userLogin);
  337. $rawData = $this->customersDb->getAll();
  338. if (!empty($rawData)) {
  339. $result = $rawData[0]['virtualid'];
  340. }
  341. }
  342. return ($result);
  343. }
  344. /**
  345. * Loads array of available payment systems
  346. *
  347. * @return void
  348. */
  349. protected function loadPaySys() {
  350. $paySysCached = $this->cache->get(self::KEY_PSYS, $this->cacheTimeout);
  351. if (empty($paySysCached)) {
  352. $all = $this->transactionsDb->getAll('', true, 'paysys');
  353. if (!empty($all)) {
  354. foreach ($all as $io => $each) {
  355. $this->allPaySys[$each['paysys']] = $each['paysys'];
  356. }
  357. }
  358. $this->cache->set(self::KEY_PSYS, $this->allPaySys, $this->cacheTimeout);
  359. } else {
  360. $this->allPaySys = $paySysCached;
  361. }
  362. }
  363. /**
  364. * Inits system messages helper
  365. *
  366. * @return voids
  367. */
  368. protected function initMessages() {
  369. $this->messages = new UbillingMessageHelper();
  370. }
  371. /**
  372. * Generates unique payment ID of configurable length
  373. *
  374. * @return int
  375. */
  376. protected function generateUniquePaymentId() {
  377. $result = 0;
  378. if ($this->payidStaticLen > 0) {
  379. $result = $this->payIdStaticPrefix . zb_rand_digits($this->payidStaticLen);
  380. while (isset($this->allCustomers[$result])) {
  381. $result = $this->payIdStaticPrefix . zb_rand_digits($this->payidStaticLen);
  382. }
  383. }
  384. return ($result);
  385. }
  386. /**
  387. * Creates new static payment ID in database for some user
  388. *
  389. * @param string $userLogin
  390. *
  391. * @return int
  392. */
  393. public function registerStaticPaymentId($userLogin) {
  394. $result = '';
  395. $userLoginF = ubRouting::filters($userLogin, 'mres');
  396. if ($this->payidStaticLen > 0) {
  397. $noPaymentId = true; //payment ID registered flag
  398. $existingPayId = ''; //contains existing payment ID if it exists now
  399. if (!empty($this->allCustomers)) {
  400. foreach ($this->allCustomers as $eachPayId => $eachLogin) {
  401. if ($eachLogin == $userLogin) {
  402. $noPaymentId = false;
  403. $existingPayId = $eachPayId;
  404. break;
  405. }
  406. }
  407. }
  408. //user have no payment ID yet?
  409. if ($noPaymentId) {
  410. $newPaymentId = $this->generateUniquePaymentId();
  411. $this->staticDb->data('realid', $userLoginF);
  412. $this->staticDb->data('virtualid', $newPaymentId);
  413. $this->staticDb->create();
  414. log_register('OPENPAYZ STATIC REGISTER (' . $userLogin . ') PAYID `' . $newPaymentId . '`');
  415. $result = $newPaymentId;
  416. } else {
  417. log_register('OPENPAYZ STATIC REGISTER FAIL (' . $userLogin . ') ALREADY `' . $existingPayId . '`');
  418. }
  419. }
  420. return ($result);
  421. }
  422. /**
  423. * Deregisters static payment ID by username
  424. *
  425. * @param string $userLogin
  426. *
  427. * @return void
  428. */
  429. public function degisterStaticPaymentId($userLogin) {
  430. $userLoginF = ubRouting::filters($userLogin, 'mres');
  431. $this->staticDb->where('realid', '=', $userLoginF);
  432. $this->staticDb->delete();
  433. log_register('OPENPAYZ STATIC DELETE (' . $userLogin . ')');
  434. }
  435. /**
  436. * Returns openpayz search form
  437. *
  438. * @return string
  439. */
  440. public function renderSearchForm() {
  441. $result = '';
  442. $curYear = (ubRouting::checkPost('searchyear')) ? ubRouting::post('searchyear', 'int') : date("Y");
  443. $curMonth = (ubRouting::checkPost('searchmonth')) ? ubRouting::post('searchmonth', 'int') : date("m");
  444. $curPaysys = (ubRouting::checkPost('searchpaysys')) ? ubRouting::post('searchpaysys', 'mres') : '';
  445. /**
  446. * No lights, no sights, every fright, every night
  447. * Alone, hurt and cold, she‘s shackled to the pipes
  448. */
  449. $paySysSelector['ANY'] = __('All');
  450. $paySysSelector += $this->allPaySys;
  451. $inputs = wf_YearSelectorPreset('searchyear', __('Year'), false, $curYear) . ' ';
  452. $inputs .= wf_MonthSelector('searchmonth', __('Month'), $curMonth, false) . ' ';
  453. $inputs .= wf_Selector('searchpaysys', $paySysSelector, __('Payment system'), $curPaysys, false) . ' ';
  454. $inputs .= wf_Submit(__('Search'));
  455. $result .= wf_BackLink(self::URL_ME);
  456. $result .= wf_delimiter();
  457. $result .= wf_Form("", 'POST', $inputs, 'glamour');
  458. return ($result);
  459. }
  460. /**
  461. * Performs openpayz search in database and shows result
  462. *
  463. * @param int $year
  464. * @param string $month
  465. * @param string $paysys
  466. *
  467. * @return void
  468. */
  469. public function doSearch($year, $month, $paysys) {
  470. $this->loadTransactions();
  471. $this->loadRealname();
  472. $this->loadAddress();
  473. $this->loadCustomers();
  474. $csvdata = '';
  475. $totalsumm = 0;
  476. $totalcount = 0;
  477. $cells = wf_TableCell(__('ID'));
  478. $cells .= wf_TableCell(__('Date'));
  479. $cells .= wf_TableCell(__('Cash'));
  480. $cells .= wf_TableCell(__('Payment ID'));
  481. $cells .= wf_TableCell(__('Real Name'));
  482. $cells .= wf_TableCell(__('Full address'));
  483. $cells .= wf_TableCell(__('Payment system'));
  484. $cells .= wf_TableCell(__('Processed'));
  485. $cells .= wf_TableCell(__('Actions'));
  486. $rows = wf_TableRow($cells, 'row1');
  487. if (!empty($this->allTransactions)) {
  488. $csvdata = __('ID') . ';' . __('Date') . ';' . __('Cash') . ';' . __('Payment ID') . ';' . __('Real Name') . ';' . __('Full address') . ';' . __('Payment system') . "\n";
  489. foreach ($this->allTransactions as $io => $eachtransaction) {
  490. if (ispos($eachtransaction['date'], $year . '-' . $month)) {
  491. if (($eachtransaction['paysys'] == $paysys) or (($paysys == 'ANY'))) {
  492. @$user_login = $this->allCustomers[$eachtransaction['customerid']];
  493. @$user_realname = $this->allRealnames[$user_login];
  494. @$user_address = $this->allAddress[$user_login];
  495. $cells = wf_TableCell($eachtransaction['id']);
  496. $cells .= wf_TableCell($eachtransaction['date']);
  497. $cells .= wf_TableCell($eachtransaction['summ']);
  498. $cells .= wf_TableCell($eachtransaction['customerid']);
  499. $cells .= wf_TableCell($user_realname);
  500. $cells .= wf_TableCell($user_address);
  501. $cells .= wf_TableCell($eachtransaction['paysys']);
  502. $cells .= wf_TableCell(web_bool_led($eachtransaction['processed']));
  503. $cells .= wf_TableCell(wf_Link('?module=userprofile&username=' . $user_login, web_profile_icon()));
  504. $rows .= wf_TableRow($cells, 'row3');
  505. if ($eachtransaction['summ'] > 0) {
  506. $totalsumm = $totalsumm + $eachtransaction['summ'];
  507. $totalcount = $totalcount + 1;
  508. }
  509. $csvSumm = str_replace('.', ',', $eachtransaction['summ']);
  510. $csvdata .= $eachtransaction['id'] . ';' . $eachtransaction['date'] . ';' . $csvSumm . ';' . $eachtransaction['customerid'] . ';' . $user_realname . ';' . $user_address . ';' . $eachtransaction['paysys'] . "\n";
  511. }
  512. }
  513. }
  514. }
  515. $result = wf_TableBody($rows, '100%', '0', 'sortable');
  516. $result .= __('Total') . ': ' . $totalcount . ' ' . __('payments') . ' ' . __('with total amount') . ' ' . $totalsumm;
  517. if (!empty($csvdata)) {
  518. $exportFilename = 'exports/opsearch_' . $paysys . '_' . $year . '-' . $month . '.csv';
  519. file_put_contents($exportFilename, $csvdata);
  520. $exportLink = wf_Link(self::URL_ME . '&dload=' . base64_encode($exportFilename), wf_img('skins/excel.gif', __('Export')), false, '');
  521. } else {
  522. $exportLink = '';
  523. }
  524. show_window(__('Search results') . ' ' . $paysys . ': ' . $year . '-' . $month . ' ' . $exportLink, $result);
  525. }
  526. /**
  527. * Inits funds flow object instance
  528. *
  529. * @return void
  530. */
  531. protected function initFundsFlow() {
  532. $this->fundsFlow = new FundsFlow();
  533. $this->fundsFlow->runDataLoders();
  534. }
  535. /**
  536. * Returns user online left days without additional DB queries
  537. * runDataLoaders() must be run once, before usage
  538. *
  539. * @param string $login existing users login
  540. *
  541. * @return int >=0: days left, -1: debt, -2: zero tariff price
  542. */
  543. protected function getUserOnlineLeftDayCount($login) {
  544. $result = 0;
  545. $onlineLeftCount = $this->fundsFlow->getOnlineLeftCountFast($login);
  546. if ($onlineLeftCount >= 0) {
  547. $result = $onlineLeftCount;
  548. }
  549. return ($result);
  550. }
  551. /**
  552. * Returns user online to date
  553. *
  554. * @param string $login existing users login
  555. *
  556. * @return string
  557. */
  558. protected function getUserOnlineToDate($login) {
  559. $result = date("d.m.Y");
  560. $daysOnLine = $this->fundsFlow->getOnlineLeftCountFast($login);
  561. if ($daysOnLine >= 0) {
  562. $result = date("d.m.Y", time() + ($daysOnLine * 24 * 60 * 60));
  563. }
  564. return ($result);
  565. }
  566. /**
  567. * Renders year selection form for charts
  568. *
  569. * @return string
  570. */
  571. protected function renderChartsYearForm() {
  572. $result = '';
  573. $curYear = ubRouting::checkPost('chartsyear') ? ubRouting::post('chartsyear', 'int') : curyear();
  574. $inputs = wf_YearSelectorPreset('chartsyear', __('Year'), false, $curYear, true) . ' ';
  575. $inputs .= wf_Submit(__('Show'));
  576. $result .= wf_Form('', 'POST', $inputs, 'glamour');
  577. return ($result);
  578. }
  579. /**
  580. * Renders per-payment system openpayz transaction charts
  581. *
  582. * @return string
  583. */
  584. public function renderGraphs() {
  585. $showYear = ubRouting::checkPost('chartsyear') ? ubRouting::post('chartsyear', 'int') : curyear();
  586. $curMonth = curmonth();
  587. $curDay = curdate();
  588. $curYear = curyear();
  589. $psysdata = array();
  590. $gcAllData = array();
  591. $gcYearData = array();
  592. $gcMonthData = array();
  593. $gcDayData = array();
  594. $gchartsData = array();
  595. $chartsOptions = "
  596. 'focusTarget': 'category',
  597. 'hAxis': {
  598. 'color': 'none',
  599. 'baselineColor': 'none',
  600. },
  601. 'vAxis': {
  602. 'color': 'none',
  603. 'baselineColor': 'none',
  604. },
  605. 'curveType': 'function',
  606. 'pointSize': 5,
  607. 'crosshair': {
  608. trigger: 'none'
  609. },";
  610. $result = wf_BackLink(self::URL_ME, '', true);
  611. //cahche data extraction
  612. $cacheKeyName = self::KEY_CHARTS . $showYear;
  613. $cacheDataRaw = $this->cache->get($cacheKeyName, $this->cacheTimeout);
  614. //something in cache
  615. if (!empty($cacheDataRaw)) {
  616. $psysdata = $cacheDataRaw['psysdata'];
  617. $gcYearData = $cacheDataRaw['gcYearData'];
  618. $gcMonthData = $cacheDataRaw['gcMonthData'];
  619. $gcDayData = $cacheDataRaw['gcDayData'];
  620. } else {
  621. $cacheDataRaw = array();
  622. //real data loading
  623. $this->loadTransactions($showYear);
  624. if (!empty($this->allTransactions)) {
  625. foreach ($this->allTransactions as $io => $each) {
  626. $timestamp = strtotime($each['date']);
  627. $date = date("Y-m", $timestamp);
  628. $dateFull = date("Y-m-d", $timestamp);
  629. if (isset($psysdata[$each['paysys']][$date]['count'])) {
  630. $psysdata[$each['paysys']][$date]['count']++;
  631. $psysdata[$each['paysys']][$date]['summ'] = $psysdata[$each['paysys']][$date]['summ'] + $each['summ'];
  632. } else {
  633. $psysdata[$each['paysys']][$date]['count'] = 1;
  634. $psysdata[$each['paysys']][$date]['summ'] = $each['summ'];
  635. }
  636. //current year stats
  637. if (ispos($date, $curYear)) {
  638. if (isset($gcYearData[$each['paysys']])) {
  639. $gcYearData[$each['paysys']]++;
  640. } else {
  641. $gcYearData[$each['paysys']] = 1;
  642. }
  643. }
  644. //current month stats
  645. if (ispos($date, $curMonth)) {
  646. if (isset($gcMonthData[$each['paysys']])) {
  647. $gcMonthData[$each['paysys']]++;
  648. } else {
  649. $gcMonthData[$each['paysys']] = 1;
  650. }
  651. }
  652. //current day stats
  653. if (ispos($dateFull, $curDay)) {
  654. if (isset($gcDayData[$each['paysys']])) {
  655. $gcDayData[$each['paysys']]++;
  656. } else {
  657. $gcDayData[$each['paysys']] = 1;
  658. }
  659. }
  660. }
  661. }
  662. //store in cache
  663. $cacheDataRaw['psysdata'] = $psysdata;
  664. $cacheDataRaw['gcYearData'] = $gcYearData;
  665. $cacheDataRaw['gcMonthData'] = $gcMonthData;
  666. $cacheDataRaw['gcDayData'] = $gcDayData;
  667. $this->cache->set($cacheKeyName, $cacheDataRaw, $this->cacheTimeout);
  668. }
  669. $chartOpts = "chartArea: { width: '90%', height: '90%' }, legend : {position: 'right'}, ";
  670. $fixedColors = @$this->altCfg['OPENPAYZ_PALETTE'];
  671. if (!empty($gcDayData)) {
  672. $gcDayPie = wf_gcharts3DPie($gcDayData, __('Today'), '300px', '300px', $chartOpts, $fixedColors);
  673. } else {
  674. $gcDayPie = '';
  675. }
  676. if (!empty($gcMonthData)) {
  677. $gcMonthPie = wf_gcharts3DPie($gcMonthData, __('Current month'), '300px', '300px', $chartOpts, $fixedColors);
  678. } else {
  679. $gcMonthPie = '';
  680. }
  681. if (!empty($gcYearData)) {
  682. $gcYearPie = wf_gcharts3DPie($gcYearData, __('Current year'), '300px', '300px', $chartOpts, $fixedColors);
  683. } else {
  684. $gcYearPie = '';
  685. }
  686. $gcells = wf_TableCell($gcYearPie);
  687. $gcells .= wf_TableCell($gcMonthPie);
  688. $gcells .= wf_TableCell($gcDayPie);
  689. $grows = wf_TableRow($gcells);
  690. $result .= wf_tag('br');
  691. $result .= $this->renderChartsYearForm();
  692. $result .= wf_CleanDiv();
  693. $result .= wf_TableBody($grows, '100%', 0, '');
  694. if (!empty($psysdata)) {
  695. foreach ($psysdata as $psys => $opdate) {
  696. $gchartsData[] = array(__('Date'), __('Count'), __('Cash'));
  697. foreach ($opdate as $datestamp => $optrans) {
  698. $gchartsData[] = array($datestamp, $optrans['count'], $optrans['summ']);
  699. }
  700. $result .= wf_gchartsLine($gchartsData, $psys, '100%', '300px;', $chartsOptions);
  701. $gchartsData = array();
  702. }
  703. }
  704. return ($result);
  705. }
  706. /**
  707. * Sets openpayz transaction as processed in database
  708. *
  709. * @param int $transactionId
  710. *
  711. * @return void
  712. */
  713. public function transactionSetProcessed($transactionId) {
  714. $transactionId = ubRouting::filters($transactionId, 'int');
  715. $this->transactionsDb->where('id', '=', $transactionId);
  716. $this->transactionsDb->data('processed', '1');
  717. $this->transactionsDb->save();
  718. log_register('OPENPAYZ PROCESSED [' . $transactionId . ']');
  719. }
  720. /**
  721. * Pushes user payment with some payment system
  722. *
  723. * @param string $login
  724. * @param float $cash
  725. * @param string $paysys
  726. *
  727. * @return void
  728. */
  729. public function cashAdd($login, $cash, $paysys) {
  730. $note = 'OP:' . $paysys;
  731. zb_CashAdd($login, $cash, 'add', $this->altCfg['OPENPAYZ_CASHTYPEID'], $note);
  732. }
  733. /**
  734. * Returns openpayz transaction data by its ID
  735. *
  736. * @param int $transactionid
  737. *
  738. * @return array
  739. */
  740. function transactionGetData($transactionid) {
  741. $result = array();
  742. if (empty($this->allTransactions)) {
  743. $this->loadTransactions();
  744. }
  745. if (isset($this->allTransactions[$transactionid])) {
  746. $result = $this->allTransactions[$transactionid];
  747. }
  748. return ($result);
  749. }
  750. /**
  751. * Retruns json data for jquery data tables with transactions list
  752. *
  753. * @global object $ubillingConfig
  754. *
  755. * @return void
  756. */
  757. public function transactionAjaxSource() {
  758. $this->loadCustomers();
  759. $this->loadAddress();
  760. $this->loadRealname();
  761. $curYear = curyear();
  762. $manual_mode = $this->altCfg['OPENPAYZ_MANUAL'];
  763. //loading current year transactions
  764. $this->loadTransactions($curYear);
  765. $json = new wf_JqDtHelper();
  766. if (!empty($this->allTransactions)) {
  767. foreach ($this->allTransactions as $io => $eachtransaction) {
  768. $control = '';
  769. if ($manual_mode) {
  770. if ($eachtransaction['processed'] == 0) {
  771. $control .= ' ' . wf_Link(self::URL_ME . '&process=' . $eachtransaction['id'], web_add_icon('Payment'));
  772. }
  773. }
  774. @$user_login = $this->allCustomers[$eachtransaction['customerid']];
  775. @$user_realname = $this->allRealnames[$user_login];
  776. @$user_address = $this->allAddress[$user_login];
  777. if (!empty($user_login)) {
  778. $profileLink = wf_Link('?module=userprofile&username=' . $user_login, web_profile_icon() . ' ' . @$user_address);
  779. } else {
  780. $profileLink = '';
  781. }
  782. $stateIcon = web_bool_led($eachtransaction['processed']);
  783. $detailsControl = ' ' . wf_Link(self::URL_ME . '&showtransaction=' . $eachtransaction['id'], $eachtransaction['id']);
  784. $data[] = $detailsControl;
  785. $data[] = $eachtransaction['date'];
  786. $data[] = $eachtransaction['summ'];
  787. $data[] = $eachtransaction['customerid'];
  788. $data[] = $user_realname;
  789. $data[] = $profileLink;
  790. $data[] = $eachtransaction['paysys'];
  791. $data[] = $stateIcon . $control;
  792. $json->addRow($data);
  793. unset($data);
  794. }
  795. }
  796. $json->getJson();
  797. }
  798. /**
  799. * Renders transaction list container
  800. *
  801. * @return void
  802. */
  803. public function renderTransactionList() {
  804. $opts = '"order": [[ 0, "desc" ]]';
  805. $columns = array('ID', 'Date', 'Cash', 'Payment ID', 'Real Name', 'Full address', 'Payment system', 'Processed');
  806. $graphsUrl = wf_Link(self::URL_CHARTS, wf_img('skins/icon_stats.gif', __('Graphs')), false, '') . ' ';
  807. $searchUrl = wf_Link(self::URL_ME . '&transactionsearch=true', web_icon_search(), false, '');
  808. show_window(__('OpenPayz transactions') . ' ' . $graphsUrl . $searchUrl, wf_JqDtLoader($columns, self::URL_AJAX_SOURCE, false, 'payments', 100, $opts));
  809. }
  810. /**
  811. * Renders transaction details
  812. *
  813. * @param int $transactionId
  814. *
  815. * @return void
  816. */
  817. public function renderTransactionDetails($transactionId) {
  818. $transactionId = ubRouting::filters($transactionId, 'int');
  819. $this->loadTransactions('', $transactionId);
  820. $result = '';
  821. $result .= wf_BackLink(self::URL_ME, '', true);
  822. if (isset($this->allTransactions[$transactionId])) {
  823. $result .= wf_tag('pre', false, 'floatpanelswide', '') . print_r($this->allTransactions[$transactionId], true) . wf_tag('pre', true);
  824. $result .= wf_CleanDiv();
  825. } else {
  826. $result .= $this->messages->getStyledMessage(__('Non existent transaction ID'), 'error');
  827. }
  828. show_window(__('Transaction') . ': ' . $transactionId, $result);
  829. }
  830. /**
  831. * Pulls payments from payment DB for further SMS notifications processing
  832. *
  833. * @throws Exception
  834. *
  835. * @return void
  836. */
  837. public function pullNotysPayments() {
  838. $paymentsFound = array();
  839. $paymentsFoundCnt = 0;
  840. $tabPayments = new NyanORM('payments');
  841. $tabNotifications = new NyanORM('op_sms_notifications');
  842. if ($this->smsDebugON) {
  843. $tabPayments->setDebug(true, true);
  844. $tabNotifications->setDebug(true, true);
  845. }
  846. // trying to get timestamp of the very last pulled payment
  847. // if nothing was pulled yet - current datetime used
  848. $tabNotifications->selectable('MAX(date) AS max_date');
  849. $pullDateTimeLast = $tabNotifications->getAll();
  850. if (!empty($pullDateTimeLast[0]['max_date'])) {
  851. $pullDateTimeLast = $pullDateTimeLast[0]['max_date'];
  852. } else {
  853. $pullDateTimeLast = curdatetime();
  854. }
  855. $pullDateTimeFrom = date('Y:m:d H:i:s', strtotime($pullDateTimeLast . '-' . $this->smsNotysPullInterval . 'min'));
  856. $tabPayments->where('date', '>=', $pullDateTimeFrom);
  857. $tabPayments->where('admin', '=', 'openpayz');
  858. $paymentsFound = $tabPayments->getAll('id');
  859. if (!empty($paymentsFound)) {
  860. // get the payments IDs
  861. $tmpPaymIDs = array_keys($paymentsFound);
  862. $tmpPaymIDs = implode(',', $tmpPaymIDs);
  863. if ($this->smsDebugON) {
  864. log_register('OPAYZ SMS NOTIFY: found payments IDs: ' . $tmpPaymIDs);
  865. }
  866. // try to select those IDs from 'op_sms_notifications'
  867. $tabNotifications->whereRaw(' `payment_id` IN (' . $tmpPaymIDs . ') ');
  868. $tabNotifications->selectable(array('payment_id'));
  869. $tmpNotysFound = $tabNotifications->getAll('payment_id');
  870. // exclude found payments IDs
  871. if (!empty($tmpNotysFound)) {
  872. $paymentsFound = array_diff_key($paymentsFound, $tmpNotysFound);
  873. if ($this->smsDebugON) {
  874. log_register('OPAYZ SMS NOTIFY: found payments IDs with already sent notifications: ' . print_r($tmpNotysFound, true));
  875. log_register('OPAYZ SMS NOTIFY: found payments IDs after exclusion of IDs with already sent notifications: ' . print_r($paymentsFound, true));
  876. }
  877. }
  878. if (!empty($paymentsFound)) {
  879. foreach ($paymentsFound as $eachID => $eachRec) {
  880. $tmpLogin = $eachRec['login'];
  881. // check logins for REMINDER_TAGID presence if $this->smsRespectReminderTagID is true
  882. if ($this->smsRespectReminderTagID and !empty($this->allUsersTags)) {
  883. // skip this payment if login doesn't have REMINDER_TAGID assigned
  884. if (empty($this->allUsersTags[$tmpLogin][$this->smsReminderTagID])) {
  885. if ($this->smsDebugON) {
  886. log_register('OPAYZ SMS NOTIFY: skipping payment with ID: ' . $eachID . ' for login: (' . $tmpLogin . ') as it doesn\'t have REMINDER_TAGID [' . $this->smsReminderTagID . '] assigned');
  887. }
  888. continue;
  889. }
  890. }
  891. $tmpRec = array(
  892. 'payment_id' => $eachID,
  893. 'date' => $eachRec['date'],
  894. 'login' => $tmpLogin,
  895. 'balance' => $eachRec['balance'] + $eachRec['summ'],
  896. 'summ' => $eachRec['summ']
  897. );
  898. $tabNotifications->dataArr($tmpRec);
  899. $tabNotifications->create();
  900. $paymentsFoundCnt++;
  901. }
  902. }
  903. }
  904. if (!empty($paymentsFoundCnt) or $this->smsDebugON) {
  905. log_register('OPAYZ SMS NOTIFY: pulled ' . $paymentsFoundCnt . ' payment records, starting from: ' . $pullDateTimeFrom);
  906. }
  907. }
  908. /**
  909. * Handles notifications processing for collected payments
  910. *
  911. * @throws Exception
  912. *
  913. * @return void
  914. */
  915. public function processNotys() {
  916. $sentCount = 0;
  917. $tabNotifications = new NyanORM('op_sms_notifications');
  918. if ($this->smsDebugON) {
  919. $tabNotifications->setDebug(true, true);
  920. }
  921. $tabNotifications->where('processed', '=', '0');
  922. $notysToPush = $tabNotifications->getAll('id');
  923. if (!empty($notysToPush)) {
  924. $ubSMS = new UbillingSMS();
  925. $allPhones = zb_GetAllAllPhonesCache();
  926. $this->initFundsFlow();
  927. // init SMS directions cache
  928. if ($this->ubConfig->getAlterParam('SMS_SERVICES_ADVANCED_ENABLED')) {
  929. $smsDirections = new SMSDirections();
  930. }
  931. foreach ($notysToPush as $eachID => $eachRec) {
  932. $login = $eachRec['login'];
  933. $noMobilesfound = false;
  934. if ($this->smsDebugON) {
  935. log_register('OPAYZ SMS NOTIFY: sending message for payment: ' . print_r($eachRec, true));
  936. }
  937. if (isset($allPhones[$login])) {
  938. $usrMobiles = array($allPhones[$login]['mobile']);
  939. if ($this->smsUseExtMobiles) {
  940. $usrMobiles = array_merge($usrMobiles, $allPhones[$login]['mobiles']);
  941. }
  942. if (!empty($usrMobiles)) {
  943. if ($this->smsDebugON) {
  944. log_register('OPAYZ SMS NOTIFY: found cell numbers: ' . implode(',', $usrMobiles) . ' for user (' . $login . ')');
  945. }
  946. $msgText = $this->smsNotysText;
  947. $msgText = str_ireplace('{LOGIN}', $login, $msgText);
  948. $msgText = str_ireplace('{USERONLINELEFTDAY}', $this->getUserOnlineLeftDayCount($login), $msgText);
  949. $msgText = str_ireplace('{USERONLINETODATE}', $this->getUserOnlineToDate($login), $msgText);
  950. $msgText = str_ireplace('{ROUNDBALANCE}', round($eachRec['balance'], 2), $msgText);
  951. $msgText = str_ireplace('{ROUNDPAYMENTAMOUNT}', round($eachRec['summ'], 2), $msgText);
  952. foreach ($usrMobiles as $mobile) {
  953. $mobile = zb_CleanMobileNumber($mobile);
  954. $queueFile = $ubSMS->sendSMS($mobile, $msgText, $this->smsForceTranslit, 'OPENPAYZ');
  955. $ubSMS->setDirection($queueFile, 'user_login', $login);
  956. if ($this->smsDebugON) {
  957. log_register('OPAYZ SMS NOTIFY: sent message for user (' . $login . ') to ' . $mobile);
  958. }
  959. }
  960. $tabNotifications->where('id', '=', $eachID);
  961. $tabNotifications->data('processed', '1');
  962. $tabNotifications->save();
  963. $sentCount++;
  964. } else {
  965. $noMobilesfound = true;
  966. }
  967. } else {
  968. $noMobilesfound = true;
  969. }
  970. if ($this->smsDebugON and $noMobilesfound) {
  971. log_register('OPAYZ SMS NOTIFY: unable to send message for user (' . $login . ') - no assigned cell phone numbers found');
  972. }
  973. }
  974. }
  975. if ($sentCount > 0 or $this->smsDebugON) {
  976. log_register('OPAYZ SMS NOTIFY: sent ' . $sentCount . ' messages');
  977. }
  978. }
  979. }