util.php 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695
  1. <?php
  2. namespace refill;
  3. require_once(BASE_HELPER_PATH . '/mtopcard/mtopcard.php');
  4. require_once(BASE_HELPER_PATH . '/queue/rdispatcher.php');
  5. require_once(BASE_HELPER_PATH . '/refill/policy/rlock.php');
  6. use queue;
  7. use mtopcard;
  8. use Log;
  9. use Exception;
  10. use Cache;
  11. use QueueClient;
  12. use refill;
  13. class util
  14. {
  15. const ThirdRefillAmount = 100;
  16. static function make_mobile()
  17. {
  18. static $prefix = ["139", "138", "137", "136", "135", "134", "159", "158", "157", "150", "151", "152",
  19. "188", "187", "182", "183", "184", "178", "130", "131", "132", "156", "155", "186", "185",
  20. "176", "133", "153", "189", "180", "181", "177"];
  21. $pos = mt_rand(0, count($prefix) - 1);
  22. $no = "{$prefix[$pos]}" . mt_rand(10000000, 99999999);
  23. return $no;
  24. }
  25. public static function can_refill($card_no, $card_type)
  26. {
  27. if ($card_type == mtopcard\SinopecCard || $card_type == mtopcard\PetroChinaCard) {
  28. $result = rcache('card_expired', '', "{$card_no}");
  29. if (empty($result)) {
  30. wcache("card_expired", [$card_no => time()], '');
  31. return [true, 0];
  32. } else {
  33. $latest = current($result);
  34. $cur = time();
  35. $success = ($cur - $latest) > 2;
  36. if ($success) {
  37. wcache("card_expired", [$card_no => time()], '');
  38. }
  39. return [$success, $latest + 2 - $cur];
  40. }
  41. } else {
  42. return [true, 0];
  43. }
  44. }
  45. public static function can_commit($card_no, $card_type)
  46. {
  47. if ($card_type == mtopcard\SinopecCard || $card_type == mtopcard\PetroChinaCard)
  48. {
  49. $result = rcache('card_expired', '', "{$card_no}");
  50. if (empty($result)) {
  51. wcache("card_expired", [$card_no => time()], '');
  52. return [true, 0];
  53. }
  54. else
  55. {
  56. $latest = current($result);
  57. $cur = time();
  58. $lowest = 30;
  59. if ($cur > $latest && ($cur - $latest) >= $lowest) {
  60. wcache("card_expired", [$card_no => time()], '');
  61. return [true, 0];
  62. } else {
  63. wcache("card_expired", [$card_no => $latest + $lowest], '');
  64. return [false, $latest + $lowest - $cur];
  65. }
  66. }
  67. }
  68. else {
  69. return [true, 0];
  70. }
  71. }
  72. static function read_card($card_no, $card_type = 0)
  73. {
  74. if (empty($card_no)) return false;
  75. $data = rcache($card_no, 'cardrefill-');
  76. if (empty($data)) {
  77. $mod_topcard = Model('topcard');
  78. $ret = $mod_topcard->get_card($card_no);
  79. if (empty($ret)) {
  80. if ($card_type === 0) {
  81. $card_type = mtopcard\card_type($card_no,$regin_no);
  82. }
  83. $bind_phone = util::make_mobile();
  84. $mod_topcard->add($card_no, $card_type, time(), $bind_phone);
  85. $data['bind_phone'] = $bind_phone;
  86. $data['refill_time'] = time();
  87. $data['times'] = 0;
  88. $data['black_card'] = 0;
  89. wcache($card_no, $data, 'cardrefill-');
  90. } else {
  91. $val = $ret[0];
  92. $data['bind_phone'] = $val['bind_phone'];
  93. $data['black_card'] = $val['black_card'];
  94. $data['refill_time'] = time();
  95. $data['times'] = 0;
  96. }
  97. }
  98. //之前没加black_card处理,这个字段不存在.
  99. if (!array_key_exists('black_card', $data)) {
  100. $data['black_card'] = 0;
  101. }
  102. return $data;
  103. }
  104. static function inc_card($card_no, $card_info)
  105. {
  106. $card_info['times'] += 1;
  107. $card_info['refill_time'] = time();
  108. wcache($card_no, $card_info, 'cardrefill-');
  109. }
  110. public static function del_card($card_no)
  111. {
  112. dcache($card_no, 'cardrefill-');
  113. }
  114. public static function set_black($card_no)
  115. {
  116. if (empty($card_no)) return false;
  117. $card_info = util::read_card($card_no);
  118. if (!empty($card_info)) {
  119. $card_info['black_card'] = 1;
  120. $mod_topcard = Model('topcard');
  121. $mod_topcard->table('topcard')->where(['card_no' => $card_no])->update(['black_card' => 1]);
  122. wcache($card_no, $card_info, 'cardrefill-');
  123. return true;
  124. } else {
  125. return false;
  126. }
  127. }
  128. private static function black_order($order_sn, $msg)
  129. {
  130. static $errMsgs = ["只能给主卡且卡状态正常的加油卡充值", "加油卡卡号错误或不支持"];
  131. if (empty($msg)) return false;
  132. if (in_array($msg, $errMsgs)) {
  133. $refill = Model('refill_order');
  134. $order = $refill->getOrderInfo(['order_sn' => $order_sn]);
  135. if (empty($order)) return false;
  136. $card_no = $order['card_no'];
  137. return util::set_black($card_no);
  138. }
  139. }
  140. public static function black_from_log($file_name)
  141. {
  142. $fn = fopen($file_name, "r");
  143. if (empty($fn)) {
  144. Log::record("Open File {$file_name} error.", Log::ERR);
  145. return false;
  146. } else {
  147. Log::record("{$file_name} start woring", Log::DEBUG);
  148. }
  149. $errs = [];
  150. while (!feof($fn)) {
  151. $line = trim(fgets($fn));
  152. $ret = preg_match('/[\w\W]+"channelOrderNumber":"(?P<order_sn>[^"]+)"[\w\W]+"message":"(?P<message>[\x{4e00}-\x{9fa5}]+)"[\w\W]+"status":109/u', $line, $matches);
  153. if ($ret) {
  154. $order_sn = $matches['order_sn'];
  155. $message = $matches['message'];
  156. self::black_order($order_sn, $message);
  157. $errs[$message] = empty($errs[$message]) ? 1 : $errs[$message] + 1;
  158. }
  159. }
  160. foreach ($errs as $msg => $count) {
  161. Log::record("msg:{$msg} count:{$count}", Log::DEBUG);
  162. }
  163. fclose($fn);
  164. return true;
  165. }
  166. public static function async_add($params, $period = 10)
  167. {
  168. try {
  169. QueueClient::async_push("AysncAddDispatcher", ['method' => 'add', 'params' => $params], $period);
  170. return true;
  171. } catch (Exception $ex) {
  172. return false;
  173. }
  174. }
  175. public static function async_notify($chname,$data, $period)
  176. {
  177. try {
  178. QueueClient::async_push("AysncAddDispatcher", ['method' => 'notify', 'params' => ['channel' => $chname, 'params' => $data]], $period);
  179. return true;
  180. } catch (Exception $ex) {
  181. return false;
  182. }
  183. }
  184. public static function push_add($params)
  185. {
  186. try
  187. {
  188. $ret = self::push_queue('add', $params);
  189. return $ret !== false;
  190. }
  191. catch (Exception $ex) {
  192. return false;
  193. }
  194. }
  195. public static function push_add_zero($params)
  196. {
  197. try
  198. {
  199. $ret = self::push_queue('add_zero', $params);
  200. return $ret !== false;
  201. }
  202. catch (Exception $ex) {
  203. return false;
  204. }
  205. }
  206. public static function push_addthird($params)
  207. {
  208. try
  209. {
  210. $ret = self::push_queue('addthird', $params);
  211. return $ret !== false;
  212. }
  213. catch (Exception $ex) {
  214. return false;
  215. }
  216. }
  217. public static function push_notify($chname, $params)
  218. {
  219. try
  220. {
  221. $ret = self::push_queue('notify', ['channel' => $chname, 'params' => $params]);
  222. return $ret !== false;
  223. }
  224. catch (Exception $ex) {
  225. return false;
  226. }
  227. }
  228. public static function push_notify_merchant($order_id, $manual)
  229. {
  230. try
  231. {
  232. $ret = self::push_queue('notify_mechant', ['order_id' => $order_id, 'manual' => $manual]);
  233. return $ret !== false;
  234. }
  235. catch (Exception $ex) {
  236. return false;
  237. }
  238. }
  239. public static function push_query($order_id)
  240. {
  241. try
  242. {
  243. $ret = self::push_queue('query', ['order_id' => $order_id]);
  244. return $ret !== false;
  245. }
  246. catch (Exception $ex) {
  247. return false;
  248. }
  249. }
  250. public static function push_query_net($order_id)
  251. {
  252. try {
  253. $ret = self::push_queue('query_net', ['order_id' => $order_id]);
  254. return $ret !== false;
  255. }
  256. catch (Exception $ex) {
  257. return false;
  258. }
  259. }
  260. public static function manual_success($order_id)
  261. {
  262. try
  263. {
  264. $ret = self::push_queue('manual_success', ['order_id' => $order_id]);
  265. return $ret !== false;
  266. }
  267. catch (Exception $ex) {
  268. return false;
  269. }
  270. }
  271. public static function manual_cancel($order_id)
  272. {
  273. try
  274. {
  275. $ret = self::push_queue('manual_cancel', ['order_id' => $order_id]);
  276. return $ret !== false;
  277. }
  278. catch (Exception $ex) {
  279. return false;
  280. }
  281. }
  282. public static function push_queue($method, $value)
  283. {
  284. if (defined('USE_COROUTINE') && USE_COROUTINE && defined('COROUTINE_HOOK_TCP') && COROUTINE_HOOK_TCP) {
  285. $queue_name = 'QUEUE_DISPATCHER_CO';
  286. $ins = Cache::getInstance('cacheredis');
  287. return $ins->lpush($queue_name, serialize([$method => $value]));
  288. }
  289. else {
  290. return queue\DispatcherClient::instance()->push($method,$value);
  291. }
  292. }
  293. public static function dispatcher_queue_length()
  294. {
  295. $ins = Cache::getInstance('cacheredis');
  296. return $ins->lLen('QUEUE_DISPATCHER_CO');
  297. }
  298. //统计提交订单数据
  299. public static function incr_commit_pre($chname, $card_type, $spec, $quality)
  300. {
  301. $ins = Cache::getInstance('cacheredis');
  302. $name = 'commit_speed_monitor';
  303. $sec = time();
  304. $key_sec = "{$chname}-{$quality}-{$card_type}-{$spec}-{$sec}";
  305. $ins->hIncrBy($name, $key_sec, 1);
  306. }
  307. public static function hget_commit_pre_sec($chname, $card_type, $spec, $quality, $time_stamp)
  308. {
  309. $ins = Cache::getInstance('cacheredis');
  310. $name = 'commit_speed_monitor';
  311. $key_sec = "{$chname}-{$quality}-{$card_type}-{$spec}-{$time_stamp}";
  312. $value = $ins->hget($name, '', $key_sec);
  313. return intval($value);
  314. }
  315. //统计用户提交数据
  316. public static function incr_user_commit($mchid,$card_type, $spec,$quality)
  317. {
  318. $ins = Cache::getInstance('cacheredis');
  319. $name = 'user_monitor_commit';
  320. $sec = time();
  321. $key_sec = "{$mchid}-{$quality}-{$card_type}-{$spec}-{$sec}";
  322. $ins->hIncrBy($name, $key_sec, 1);
  323. }
  324. public static function incr_user_success($mchid,$card_type, $spec,$quality)
  325. {
  326. $ins = Cache::getInstance('cacheredis');
  327. $name = 'user_monitor_success';
  328. $sec = time();
  329. $key_sec = "{$mchid}-{$quality}-{$card_type}-{$spec}-{$sec}";
  330. $ins->hIncrBy($name, $key_sec, 1);
  331. }
  332. public static function incr_user_fail($mchid,$card_type, $spec,$quality)
  333. {
  334. $ins = Cache::getInstance('cacheredis');
  335. $name = 'user_monitor_fail';
  336. $sec = time();
  337. $key_sec = "{$mchid}-{$quality}-{$card_type}-{$spec}-{$sec}";
  338. $ins->hIncrBy($name, $key_sec, 1);
  339. }
  340. public static function incr_commit($chname, $card_type, $spec, $quality, $fsuccess = true)
  341. {
  342. $ins = Cache::getInstance('cacheredis');
  343. $name = 'channel_monitor_commit';
  344. $sec = time();
  345. if ($fsuccess) {
  346. $key_sec = "succ-{$chname}-{$quality}-{$card_type}-{$spec}-{$sec}";
  347. } else {
  348. $key_sec = "fail-{$chname}-{$quality}-{$card_type}-{$spec}-{$sec}";
  349. }
  350. $ins->hIncrBy($name, $key_sec, 1);
  351. }
  352. public static function hget_commit_sec($chname, $card_type, $spec, $quality, $time_stamp, $fsuccess = true)
  353. {
  354. $ins = Cache::getInstance('cacheredis');
  355. $name = 'channel_monitor_commit';
  356. if ($fsuccess) {
  357. $key_sec = "succ-{$chname}-{$quality}-{$card_type}-{$spec}-{$time_stamp}";
  358. } else {
  359. $key_sec = "fail-{$chname}-{$quality}-{$card_type}-{$spec}-{$time_stamp}";
  360. }
  361. $value = $ins->hget($name, '', $key_sec);
  362. return intval($value);
  363. }
  364. //统计回调通知数据
  365. public static function incr_notify($chname, $card_type, $spec, $quality, $fsuccess = true)
  366. {
  367. $ins = Cache::getInstance('cacheredis');
  368. $name = 'channel_monitor_notify';
  369. $sec = time();
  370. if ($fsuccess) {
  371. $key_sec = "succ-{$chname}-{$quality}-{$card_type}-{$spec}-{$sec}";
  372. } else {
  373. $key_sec = "fail-{$chname}-{$quality}-{$card_type}-{$spec}-{$sec}";
  374. }
  375. $ins->hIncrBy($name, $key_sec, 1);
  376. }
  377. public static function hget_notify_sec($chname, $card_type, $spec, $quality, $time_stamp, $fsuccess = true)
  378. {
  379. $ins = Cache::getInstance('cacheredis');
  380. $name = 'channel_monitor_notify';
  381. if ($fsuccess) {
  382. $key_sec = "succ-{$chname}-{$quality}-{$card_type}-{$spec}-{$time_stamp}";
  383. } else {
  384. $key_sec = "fail-{$chname}-{$quality}-{$card_type}-{$spec}-{$time_stamp}";
  385. }
  386. $value = $ins->hget($name, '', $key_sec);
  387. return intval($value);
  388. }
  389. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  390. public static function incr_amount_lock($mchid, $card_type, $spec)
  391. {
  392. if ($card_type == mtopcard\SinopecCard || $card_type == mtopcard\PetroChinaCard) {
  393. refill\rlock::incr_sys_storage($card_type,$spec,1);
  394. refill\rlock::incr_mch_total_storage($mchid,$card_type,$spec);
  395. refill\rlock::incr_mch_storage($mchid,$card_type,$spec,1);
  396. }
  397. }
  398. public static function decr_amount_lock($mchid, $card_type, $spec)
  399. {
  400. if ($card_type == mtopcard\SinopecCard || $card_type == mtopcard\PetroChinaCard) {
  401. refill\rlock::decr_sys_storage($card_type,$spec,1);
  402. refill\rlock::decr_mch_total_storage($mchid,$card_type,$spec);
  403. refill\rlock::decr_mch_storage($mchid,$card_type,$spec,1);
  404. }
  405. }
  406. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  407. public static function set_order_channels($mchid,$mchorder,$datas)
  408. {
  409. $ins = Cache::getInstance('cacheredis');
  410. $name = 'order_channels';
  411. $key = "{$mchid}-{$mchorder}";
  412. $ins->hset($name, '', [$key => serialize($datas)]);
  413. }
  414. public static function get_order_channels($mchid, $mchorder)
  415. {
  416. //old-name oil_exclude_channels
  417. $ins = Cache::getInstance('cacheredis');
  418. $name = 'order_channels';
  419. $key = "{$mchid}-{$mchorder}";
  420. $chnames = $ins->hget($name, '', $key);
  421. $chnames = unserialize($chnames);
  422. if(is_array($chnames)) {
  423. return $chnames;
  424. } else {
  425. return [];
  426. }
  427. }
  428. public static function del_order_channels($mchid, $mchorder)
  429. {
  430. $ins = Cache::getInstance('cacheredis');
  431. $name = 'order_channels';
  432. $key = "{$mchid}-{$mchorder}";
  433. $ins->hdel($name, '', $key);
  434. }
  435. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  436. public static function set_cancel_order($mchid,$mch_order)
  437. {
  438. $ins = Cache::getInstance('cacheredis');
  439. $name = 'order_cancel_hash';
  440. $key = "{$mchid}-{$mch_order}";
  441. $ins->hset($name, '', [$key=> 1]);
  442. }
  443. public static function query_cancel_order($mchid,$mch_order)
  444. {
  445. $ins = Cache::getInstance('cacheredis');
  446. $name = 'order_cancel_hash';
  447. $key = "{$mchid}-{$mch_order}";
  448. $value = $ins->hget($name,'',$key);
  449. return $value;
  450. }
  451. public static function del_cancel_order($mchid,$mch_order)
  452. {
  453. $ins = Cache::getInstance('cacheredis');
  454. $name = 'order_cancel_hash';
  455. $key = "{$mchid}-{$mch_order}";
  456. $ins->hdel($name, $key);
  457. }
  458. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  459. public static function push_queue_order($mchid,$mch_order,$order_state)
  460. {
  461. if(empty($mch_order)) return;
  462. $ins = Cache::getInstance('cacheredis');
  463. $name = 'merchant_order_query';
  464. $key = "{$mchid}-{$mch_order}";
  465. $ins->hset($name, '', [$key => $order_state]);
  466. }
  467. public static function del_queue_order($mchid,$mch_order)
  468. {
  469. if(empty($mch_order)) return;
  470. $ins = Cache::getInstance('cacheredis');
  471. $name = 'merchant_order_query';
  472. $key = "{$mchid}-{$mch_order}";
  473. $ret = $ins->hdel($name, '', $key);
  474. }
  475. public static function pop_queue_order($mchid,$mch_order)
  476. {
  477. util::del_order_channels($mchid,$mch_order);
  478. Model('refill_order')->edit_detail($mchid,$mch_order,['order_state' => ORDER_STATE_HANDLED]);
  479. $ins = Cache::getInstance('cacheredis');
  480. $name = 'merchant_order_query';
  481. $key = "{$mchid}-{$mch_order}";
  482. $ret = $ins->hdel($name, '', $key);
  483. }
  484. public static function query_queue_order($mchid,$mch_order)
  485. {
  486. $ins = Cache::getInstance('cacheredis');
  487. $name = 'merchant_order_query';
  488. $key = "{$mchid}-{$mch_order}";
  489. $value = $ins->hget($name,'',$key);
  490. return $value;
  491. }
  492. public static function need_check($net_errno)
  493. {
  494. if(empty($net_errno)) return false;
  495. [$type,$code] = explode('-',$net_errno);
  496. $code = intval($code);
  497. if($type == "CURL") {
  498. static $errors = [CURLE_GOT_NOTHING,CURLE_RECV_ERROR];
  499. return in_array($code,$errors);
  500. } elseif($type == "HTTP") {
  501. static $excludes = [404];
  502. return !in_array($code,$excludes);
  503. } else {
  504. return false;
  505. }
  506. }
  507. public static function onOrderSuccess($refill_info,$order_info)
  508. {
  509. $data = store_member::instance()->get_member($order_info['store_id']);
  510. if(empty($data)) {
  511. Log::record("cannot find member when store_id={$order_info['store_id']}",Log::ERR);
  512. return false;
  513. }
  514. $data['order_sn'] = $refill_info['order_sn'];
  515. $data['amount'] = $refill_info['channel_amount'];
  516. $model_pd = Model('predeposit');
  517. $model_pd->changePd('order_pay',$data,true);
  518. return true;
  519. }
  520. public static function getProvider($name,$type = 'RefillPhone')
  521. {
  522. $file = BASE_HELPER_RAPI_PATH . "/$name/{$type}.php";
  523. if(!file_exists($file)){
  524. Log::record("provider api file={$file} not exist.",Log::DEBUG);
  525. return false;
  526. } else {
  527. require_once($file);
  528. Log::record("file={$file} load success.",Log::DEBUG);
  529. }
  530. $class_name = "refill\\{$name}\\{$type}";
  531. if (class_exists($class_name, false)) {
  532. $caller = new $class_name([]);
  533. return $caller;
  534. } else {
  535. $error = "Base Error: class {$class_name} isn't exists!";
  536. Log::record($error, Log::ERR);
  537. return false;
  538. }
  539. }
  540. //for tester
  541. public static function send_normal($order_sn)
  542. {
  543. $status = mt_rand(1,100);
  544. if($status > 97) {
  545. $status = 1;
  546. } else {
  547. $status = 0;
  548. }
  549. $url = BASE_SITE_URL . "/mobile/callback/refill_baidu.php";
  550. go(function () use ($url, $status,$order_sn) {
  551. sleep(3);
  552. while (true)
  553. {
  554. $resp = http_request($url,['status' => $status,'order_sn' => $order_sn],'GET', false, [], $net_errno);
  555. if($resp == 'SUCCESS') {
  556. break;
  557. }
  558. }
  559. Log::record("resp = {$resp}",Log::DEBUG);
  560. });
  561. }
  562. public static function send_quick($order_sn)
  563. {
  564. $status = mt_rand(1,10);
  565. if($status > 3) {
  566. $status = 1;
  567. } else {
  568. $status = 0;
  569. }
  570. $url = BASE_SITE_URL . "/mobile/callback/refill_baidu.php";
  571. go(function () use ($url, $status,$order_sn) {
  572. sleep(3);
  573. while (true)
  574. {
  575. $resp = http_request($url,['status' => $status,'order_sn' => $order_sn],'GET', false, [], $net_errno);
  576. if($resp == 'SUCCESS') {
  577. break;
  578. }
  579. }
  580. Log::record("resp = {$resp}",Log::DEBUG);
  581. });
  582. }
  583. }