util.php 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649
  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 = 'channel_monitor_commit';
  303. $sec = time();
  304. $key_sec = "pre-{$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 = 'channel_monitor_commit';
  311. $key_sec = "pre-{$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_commit($chname, $card_type, $spec, $quality, $fsuccess = true)
  333. {
  334. $ins = Cache::getInstance('cacheredis');
  335. $name = 'channel_monitor_commit';
  336. $sec = time();
  337. if ($fsuccess) {
  338. $key_sec = "succ-{$chname}-{$quality}-{$card_type}-{$spec}-{$sec}";
  339. } else {
  340. $key_sec = "fail-{$chname}-{$quality}-{$card_type}-{$spec}-{$sec}";
  341. }
  342. $ins->hIncrBy($name, $key_sec, 1);
  343. }
  344. public static function hget_commit_sec($chname, $card_type, $spec, $quality, $time_stamp, $fsuccess = true)
  345. {
  346. $ins = Cache::getInstance('cacheredis');
  347. $name = 'channel_monitor_commit';
  348. if ($fsuccess) {
  349. $key_sec = "succ-{$chname}-{$quality}-{$card_type}-{$spec}-{$time_stamp}";
  350. } else {
  351. $key_sec = "fail-{$chname}-{$quality}-{$card_type}-{$spec}-{$time_stamp}";
  352. }
  353. $value = $ins->hget($name, '', $key_sec);
  354. return intval($value);
  355. }
  356. //统计回调通知数据
  357. public static function incr_notify($chname, $card_type, $spec, $quality, $fsuccess = true)
  358. {
  359. $ins = Cache::getInstance('cacheredis');
  360. $name = 'channel_monitor_notify';
  361. $sec = time();
  362. if ($fsuccess) {
  363. $key_sec = "succ-{$chname}-{$quality}-{$card_type}-{$spec}-{$sec}";
  364. } else {
  365. $key_sec = "fail-{$chname}-{$quality}-{$card_type}-{$spec}-{$sec}";
  366. }
  367. $ins->hIncrBy($name, $key_sec, 1);
  368. }
  369. public static function hget_notify_sec($chname, $card_type, $spec, $quality, $time_stamp, $fsuccess = true)
  370. {
  371. $ins = Cache::getInstance('cacheredis');
  372. $name = 'channel_monitor_notify';
  373. if ($fsuccess) {
  374. $key_sec = "succ-{$chname}-{$quality}-{$card_type}-{$spec}-{$time_stamp}";
  375. } else {
  376. $key_sec = "fail-{$chname}-{$quality}-{$card_type}-{$spec}-{$time_stamp}";
  377. }
  378. $value = $ins->hget($name, '', $key_sec);
  379. return intval($value);
  380. }
  381. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  382. public static function incr_amount_lock($mchid, $card_type, $spec)
  383. {
  384. if ($card_type == mtopcard\SinopecCard || $card_type == mtopcard\PetroChinaCard) {
  385. refill\rlock::incr_sys_storage($card_type,$spec,1);
  386. refill\rlock::incr_mch_total_storage($mchid,$card_type,$spec);
  387. refill\rlock::incr_mch_storage($mchid,$card_type,$spec,1);
  388. }
  389. }
  390. public static function decr_amount_lock($mchid, $card_type, $spec)
  391. {
  392. if ($card_type == mtopcard\SinopecCard || $card_type == mtopcard\PetroChinaCard) {
  393. refill\rlock::decr_sys_storage($card_type,$spec,1);
  394. refill\rlock::decr_mch_total_storage($mchid,$card_type,$spec);
  395. refill\rlock::decr_mch_storage($mchid,$card_type,$spec,1);
  396. }
  397. }
  398. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  399. public static function set_order_channels($mchid,$mchorder,$datas)
  400. {
  401. $ins = Cache::getInstance('cacheredis');
  402. $name = 'order_channels_v2';
  403. $key = "{$mchid}-{$mchorder}";
  404. $ins->hset($name, '', [$key => serialize($datas)]);
  405. }
  406. public static function get_order_channels($mchid, $mchorder)
  407. {
  408. //old-name oil_exclude_channels
  409. $ins = Cache::getInstance('cacheredis');
  410. $name = 'order_channels_v2';
  411. $key = "{$mchid}-{$mchorder}";
  412. $chnames = $ins->hget($name, '', $key);
  413. $chnames = unserialize($chnames);
  414. if(is_array($chnames)) {
  415. return $chnames;
  416. } else {
  417. return [];
  418. }
  419. }
  420. public static function del_order_channels($mchid, $mchorder)
  421. {
  422. $ins = Cache::getInstance('cacheredis');
  423. $name = 'order_channels_v2';
  424. $key = "{$mchid}-{$mchorder}";
  425. $ins->hdel($name, '', $key);
  426. }
  427. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  428. public static function set_cancel_order($mchid,$mch_order)
  429. {
  430. $ins = Cache::getInstance('cacheredis');
  431. $name = 'order_cancel_hash';
  432. $key = "{$mchid}-{$mch_order}";
  433. $ins->hset($name, '', [$key=> 1]);
  434. }
  435. public static function query_cancel_order($mchid,$mch_order)
  436. {
  437. $ins = Cache::getInstance('cacheredis');
  438. $name = 'order_cancel_hash';
  439. $key = "{$mchid}-{$mch_order}";
  440. $value = $ins->hget($name,'',$key);
  441. return $value;
  442. }
  443. public static function del_cancel_order($mchid,$mch_order)
  444. {
  445. $ins = Cache::getInstance('cacheredis');
  446. $name = 'order_cancel_hash';
  447. $key = "{$mchid}-{$mch_order}";
  448. $ins->hdel($name, $key);
  449. }
  450. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  451. public static function push_queue_order($mchid,$mch_order,$order_state)
  452. {
  453. if(empty($mch_order)) return;
  454. $ins = Cache::getInstance('cacheredis');
  455. $name = 'merchant_order_query';
  456. $key = "{$mchid}-{$mch_order}";
  457. $ins->hset($name, '', [$key => $order_state]);
  458. }
  459. public static function del_queue_order($mchid,$mch_order)
  460. {
  461. if(empty($mch_order)) return;
  462. $ins = Cache::getInstance('cacheredis');
  463. $name = 'merchant_order_query';
  464. $key = "{$mchid}-{$mch_order}";
  465. $ret = $ins->hdel($name, '', $key);
  466. }
  467. public static function pop_queue_order($mchid,$mch_order)
  468. {
  469. util::del_order_channels($mchid,$mch_order);
  470. Model('refill_order')->edit_detail($mchid,$mch_order,['order_state' => ORDER_STATE_HANDLED]);
  471. $ins = Cache::getInstance('cacheredis');
  472. $name = 'merchant_order_query';
  473. $key = "{$mchid}-{$mch_order}";
  474. $ret = $ins->hdel($name, '', $key);
  475. }
  476. public static function query_queue_order($mchid,$mch_order)
  477. {
  478. $ins = Cache::getInstance('cacheredis');
  479. $name = 'merchant_order_query';
  480. $key = "{$mchid}-{$mch_order}";
  481. $value = $ins->hget($name,'',$key);
  482. return $value;
  483. }
  484. public static function need_check($net_errno)
  485. {
  486. if($net_errno == 0) return false;
  487. [$type,$code] = explode('-',$net_errno);
  488. $code = intval($code);
  489. if($type == "CURL") {
  490. static $errors = [CURLE_GOT_NOTHING,CURLE_RECV_ERROR];
  491. return in_array($code,$errors);
  492. } elseif($type == "HTTP") {
  493. static $excludes = [404];
  494. return !in_array($code,$excludes);
  495. } else {
  496. return false;
  497. }
  498. }
  499. public static function send_normal($order_sn)
  500. {
  501. sleep(1);
  502. $status = mt_rand(1,10);
  503. if($status > 9) {
  504. $status = 1;
  505. } else {
  506. $status = 0;
  507. }
  508. $url = BASE_SITE_URL . "/mobile/callback/refill_baidu.php";
  509. go(function () use ($url, $status,$order_sn) {
  510. sleep(120);
  511. while (true)
  512. {
  513. $resp = http_request($url,['status' => $status,'order_sn' => $order_sn],'GET', false, [], $net_errno);
  514. if($resp == 'SUCCESS') {
  515. break;
  516. }
  517. }
  518. Log::record("resp = {$resp}",Log::DEBUG);
  519. });
  520. }
  521. public static function send_quick($order_sn)
  522. {
  523. sleep(1);
  524. $status = mt_rand(1,10);
  525. if($status > 3) {
  526. $status = 1;
  527. } else {
  528. $status = 0;
  529. }
  530. $url = BASE_SITE_URL . "/mobile/callback/refill_baidu.php";
  531. go(function () use ($url, $status,$order_sn) {
  532. sleep(120);
  533. while (true)
  534. {
  535. $resp = http_request($url,['status' => $status,'order_sn' => $order_sn],'GET', false, [], $net_errno);
  536. if($resp == 'SUCCESS') {
  537. break;
  538. }
  539. }
  540. Log::record("resp = {$resp}",Log::DEBUG);
  541. });
  542. }
  543. }