policy.php 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722
  1. <?php
  2. namespace refill;
  3. use scope_trace;
  4. use Log;
  5. use rbridge\RBridgeFactory;
  6. use StatesHelper;
  7. use mtopcard;
  8. class policy extends ProviderManager implements IPolicy
  9. {
  10. protected $mChannelControl;
  11. protected $mChSpeed;
  12. protected $mQuality;
  13. protected $mPrices;
  14. protected $mAmountLockTurn;
  15. protected $mStorageLocker;
  16. protected $mGroupCtl;
  17. protected $mRatioCtl;
  18. protected $mGlobalInterceptor;
  19. protected $mMChannels;
  20. protected $mThirdHelper;
  21. protected $mChTimes;
  22. public function __construct()
  23. {
  24. parent::__construct();
  25. $this->mChannelControl = new chctlex();
  26. $this->mQuality = new quality_ploy();
  27. $this->mPrices = new merchant_price();
  28. $this->mStorageLocker = new rstorage();
  29. $this->mGroupCtl = new rgroup_ctl();
  30. $this->mRatioCtl = new mratio_controlex();
  31. $this->mQuality->setRatioCtl($this->mRatioCtl);
  32. $this->mGlobalInterceptor = new interceptor();
  33. $this->mMChannels = new mchannel();
  34. $this->mThirdHelper = new third_helper();
  35. $this->mChTimes = new ch_times();
  36. $this->mChSpeed = new chspeed();
  37. }
  38. public function load()
  39. {
  40. parent::load();
  41. $opened_names = $this->mOpenedProviderNames;
  42. sort($opened_names);
  43. $opened_merchants = $this->opened_merchants();
  44. $this->mChannelControl->load($opened_names);
  45. $this->mChannelControl->update_price($this);
  46. $this->mQuality->load();
  47. $this->mPrices->load($opened_merchants);
  48. $turn_name = 'oil_amount_lock_turn';
  49. $this->mAmountLockTurn = rkcache($turn_name);
  50. Log::record("AmountLockTurn = {$this->mAmountLockTurn}",Log::DEBUG);
  51. $this->mStorageLocker->load();
  52. $this->mGroupCtl->load($opened_names,$opened_merchants);
  53. $this->mRatioCtl->load();
  54. $this->mGlobalInterceptor->load();
  55. $this->mMChannels->load();
  56. $this->mThirdHelper->load();
  57. $this->init_mavg_price();
  58. $this->mChTimes->load();
  59. $this->mChSpeed->load();
  60. }
  61. public function get_times()
  62. {
  63. return $this->mChTimes;
  64. }
  65. private function init_mavg_price()
  66. {
  67. $specs_merger = function ($qspecs)
  68. {
  69. $q_keys = [];
  70. foreach ($qspecs as $quality => $specs)
  71. {
  72. foreach ($specs as $item) {
  73. [$card_type, $spec] = $item;
  74. $q_keys[$quality][] = "{$card_type}-{$spec}";
  75. }
  76. }
  77. $sspecs = [];
  78. $first = true;
  79. foreach ($q_keys as $quality => $specs)
  80. {
  81. if ($first) {
  82. $sspecs = $specs;
  83. $first = false;
  84. } else {
  85. $sspecs = array_intersect($sspecs, $specs);
  86. }
  87. }
  88. $result = [];
  89. foreach ($sspecs as $item) {
  90. [$card_type, $spec] = explode('-',$item);
  91. $result[] = [intval($card_type), intval($spec)];
  92. }
  93. return $result;
  94. };
  95. $pQuality = $this->mQuality;
  96. $mchids = $pQuality->mechants_quality();
  97. foreach ($mchids as $mchid => $mixed_quality)
  98. {
  99. $qualities = $pQuality->qualities($mixed_quality);
  100. $specs = [];
  101. foreach ($qualities as $quality) {
  102. $item = $this->mPrices->merchant_specs($mchid, $quality);
  103. if (empty($item)) continue;
  104. $specs[$quality] = $item;
  105. }
  106. $specs = $specs_merger($specs);
  107. foreach ($specs as $item)
  108. {
  109. [$card_type, $spec] = $item;
  110. if (!in_array($card_type, [4, 5, 6])) continue;
  111. $prices = [];
  112. $sale_price = $this->mPrices->price($mchid,$card_type,$spec,$mixed_quality,'');
  113. $prices[$mixed_quality] = round($sale_price,4);
  114. foreach ($qualities as $quality) {
  115. $inprice = $this->calc_maxprice($mchid, $quality, $card_type, $spec);
  116. $prices[$quality] = round($inprice,4);
  117. }
  118. $this->mRatioCtl->setMixedPrice($mchid, $mixed_quality, $card_type, $spec, $prices);
  119. }
  120. }
  121. }
  122. protected function calc_avgprice($mchid,$quality,$card_type,$spec)
  123. {
  124. $providers = parent::get_providers($mchid,$spec,$card_type,$quality,-1);
  125. $names = [];
  126. foreach ($providers as $provider) {
  127. $names[] = $provider->name();
  128. }
  129. [$hasGroup,$can_others,$channels] = $this->mGroupCtl->find_providers($mchid, $spec, $card_type, $quality);
  130. if($hasGroup)
  131. {
  132. if(empty($channels))
  133. {
  134. if(!$can_others) {
  135. return false;
  136. }
  137. }
  138. else
  139. {
  140. $ret = array_intersect($names, $channels);
  141. if (empty($ret)) {
  142. return false;
  143. } else {
  144. $names = $ret;
  145. }
  146. }
  147. }
  148. $name_provider = [];
  149. foreach ($providers as $provider) {
  150. $name = $provider->name();
  151. $name_provider[$name] = $provider;
  152. }
  153. $total = 0.0;
  154. foreach ($names as $name) {
  155. $provider = $name_provider[$name];
  156. [$goods_id, $price] = $provider->goods($quality, $spec, $card_type, -1, []);
  157. $total += $price;
  158. }
  159. return $total / count($names);
  160. }
  161. protected function calc_maxprice($mchid,$quality,$card_type,$spec)
  162. {
  163. $providers = parent::get_providers($mchid,$spec,$card_type,$quality,-1);
  164. $names = [];
  165. foreach ($providers as $provider) {
  166. $names[] = $provider->name();
  167. }
  168. [$hasGroup,$can_others,$channels] = $this->mGroupCtl->find_providers($mchid, $spec, $card_type, $quality);
  169. if($hasGroup)
  170. {
  171. if(empty($channels))
  172. {
  173. if(!$can_others) {
  174. return false;
  175. }
  176. }
  177. else
  178. {
  179. $ret = array_intersect($names, $channels);
  180. if (empty($ret)) {
  181. return false;
  182. } else {
  183. $names = $ret;
  184. }
  185. }
  186. }
  187. $name_provider = [];
  188. foreach ($providers as $provider) {
  189. $name = $provider->name();
  190. $name_provider[$name] = $provider;
  191. }
  192. $max_price = 0.0;
  193. foreach ($names as $name) {
  194. $provider = $name_provider[$name];
  195. [$goods_id, $price] = $provider->goods($quality, $spec, $card_type, -1, []);
  196. if($price > $max_price) $max_price = $price;
  197. }
  198. return $max_price;
  199. }
  200. private function opened_merchants()
  201. {
  202. $mchids = [];
  203. $i = 0;
  204. while (true)
  205. {
  206. $start = $i * 1000;
  207. $items = Model()->table('merchant')->field('*')->where(['merchant_state' => 1])->order('mchid asc')->limit("{$start},1000")->select();
  208. if(empty($items)) {
  209. break;
  210. }
  211. $i++;
  212. foreach ($items as $item) {
  213. $mchids[] = intval($item['mchid']);
  214. }
  215. }
  216. sort($mchids);
  217. return $mchids;
  218. }
  219. public function find_providers(order $order): array
  220. {
  221. $mchid = $order->mchid();
  222. $spec = $order->spec();
  223. $card_type = $order->card_type();
  224. $org_quality = $order->org_quality();
  225. $cur_quality = $order->cur_quality();
  226. $pcode = $order->pcode();
  227. $regin_no = $order->region_no();
  228. $order_time = $order->order_time();
  229. $providers = parent::get_providers($mchid,$spec,$card_type,$cur_quality,$regin_no);
  230. if(empty($providers)) {
  231. return [$providers,false];
  232. }
  233. $names = [];
  234. foreach ($providers as $provider) {
  235. $names[] = $provider->name();
  236. }
  237. Log::record("ProviderManager::get_providers result=" . implode(',',$names),Log::DEBUG);
  238. //机构和通道,交叉设置过滤
  239. [$card_paper, $channels] = $this->mMChannels->channels($mchid, $card_type, $cur_quality);
  240. if ($card_paper === mtopcard\OilCardPaper || $card_paper === mtopcard\PhoneCardPaper) {
  241. sort($names);
  242. $names = array_intersect($names, $channels);
  243. }
  244. Log::record("mchannel::channels result=" . implode(',',$names),Log::DEBUG);
  245. [$hasGroup,$can_others,$channels] = $this->mGroupCtl->find_providers($mchid, $spec, $card_type, $cur_quality);
  246. Log::record("GroupControl mchid={$mchid} spec={$spec} quality={$cur_quality} card_type={$card_type} first result=" . implode(',',$channels),Log::DEBUG);
  247. if($hasGroup)
  248. {
  249. if(empty($channels))
  250. {
  251. if(!$can_others) {
  252. return [[],false];
  253. }
  254. }
  255. else
  256. {
  257. $ret = array_intersect($names, $channels);
  258. if (empty($ret)) {
  259. return [[], false];
  260. } else {
  261. $names = $ret;
  262. }
  263. }
  264. }
  265. Log::record("GroupControl second result=" . implode(',',$names),Log::DEBUG);
  266. if(PolicyUtil::mixed_quality($org_quality)) {
  267. $mixedQuality = $org_quality;
  268. }
  269. else {
  270. $mixedQuality = $cur_quality;
  271. }
  272. $price = $this->mPrices->price($mchid,$card_type,$spec,$mixedQuality,$pcode);
  273. if($price === false) {
  274. return [[],false];
  275. }
  276. $extra_price = $this->mPrices->extra_price($mchid,$card_type,$spec,$mixedQuality,$pcode);
  277. $extra_price = $extra_price == false ? 0.00 : $extra_price;
  278. //以当前通道质量为准
  279. $max_inprice = $this->mPrices->max_inprice($mchid,$card_type,$spec,$cur_quality,$pcode);
  280. Log::record("max_price={$max_inprice}",Log::DEBUG);
  281. global $config;
  282. $auto_find = $config['auto_find_channels'];
  283. $mobile_types = [mtopcard\ChinaMobileCard, mtopcard\ChinaUnicomCard, mtopcard\ChinaTelecomCard];
  284. $qualities = [Quality::Normal, Quality::Quick, Quality::CardKey, Quality::ThirdShop];
  285. if ($auto_find && in_array($card_type, $mobile_types, true) && in_array($cur_quality, $qualities, true)) {
  286. $names = $this->mChannelControl->auto_match($names, $spec, $card_type, $cur_quality, $price - $extra_price, $max_inprice, time() - $order_time);
  287. Log::record("policy::find_providers ChannelControl auto_match quality={$cur_quality} spec={$spec} card_type={$card_type} result=" . implode(',', $names), Log::DEBUG);
  288. } else {
  289. $names = $this->mChannelControl->match($names, $spec, $card_type, $cur_quality, $max_inprice);
  290. Log::record("policy::find_providers ChannelControl match quality={$cur_quality} spec={$spec} card_type={$card_type} result=" . implode(',', $names), Log::DEBUG);
  291. }
  292. $name_provider = [];
  293. foreach ($providers as $provider) {
  294. $name = $provider->name();
  295. $name_provider[$name] = $provider;
  296. }
  297. $result = [];
  298. foreach ($names as $name)
  299. {
  300. if(array_key_exists($name,$name_provider)) {
  301. $result[] = $name_provider[$name];
  302. }
  303. }
  304. return [$result,false];
  305. }
  306. public function price($mchid,$spec,$card_type,$quality,$pcode)
  307. {
  308. return $this->mPrices->price($mchid,$card_type,$spec,$quality,$pcode);
  309. }
  310. public function max_inprice($mchid, $spec, $card_type, $quality, $pcode)
  311. {
  312. return $this->mPrices->max_inprice($mchid,$card_type,$spec,$quality,$pcode);
  313. }
  314. public function channeles(int $mchid, int $spec, int $card_type, int $quality, $regin_no)
  315. {
  316. $providers = parent::get_providers($mchid, $spec, $card_type, $quality, $regin_no);
  317. return count($providers);
  318. }
  319. public function find_quality(order $order, bool $skip_pre = false): array
  320. {
  321. $trace = new scope_trace(__METHOD__);
  322. $mchid = $order->mchid();
  323. $spec = $order->spec();
  324. $card_type = $order->card_type();
  325. $cur_quality = $order->cur_quality();
  326. $pcode = $order->pcode();
  327. $regin_no = $order->region_no();
  328. Log::record("spec=$spec,card_type=$card_type",Log::DEBUG);
  329. if($card_type == mtopcard\SinopecCard || $card_type == mtopcard\PetroChinaCard) {
  330. $caller = new times_caller($mchid,$spec,$card_type,-1,$this);
  331. } else {
  332. $caller = null;
  333. }
  334. [$org_quality, $qualities, $match] = $this->mQuality->find_quality($order, $caller);
  335. $order->set_match($match);
  336. if(empty($qualities)) {
  337. return [$org_quality,0];
  338. }
  339. $namer = function ($providers)
  340. {
  341. $result = [];
  342. foreach ($providers as $provider) {
  343. $result[] = $provider->name();
  344. }
  345. return $result;
  346. };
  347. Log::record("skip_pre = $skip_pre",Log::DEBUG);
  348. $start = false;
  349. foreach ($qualities as $quality)
  350. {
  351. if(!$start && $skip_pre)
  352. {
  353. if($quality == $cur_quality) {
  354. $start = true;
  355. continue;
  356. }
  357. }
  358. $price = $this->mPrices->price($mchid,$card_type,$spec,$quality,$pcode);
  359. if($price === false) {
  360. Log::record("$mchid 没有协商 quality = $quality 价格",Log::DEBUG);
  361. continue;
  362. }
  363. $max_inprice = $this->mPrices->max_inprice($mchid, $card_type, $spec, $quality, $pcode);
  364. Log::record("quality = $quality max_price=$max_inprice",Log::DEBUG);
  365. $providers = parent::get_providers($mchid, $spec, $card_type, $quality, $regin_no);
  366. if(empty($providers)) {
  367. continue;
  368. }
  369. $names = $namer($providers);
  370. //机构和通道,交叉设置过滤
  371. [$card_paper, $channels] = $this->mMChannels->channels($mchid, $card_type, $quality);
  372. if ($card_paper === mtopcard\OilCardPaper || $card_paper === mtopcard\PhoneCardPaper) {
  373. sort($names);
  374. $names = array_intersect($names, $channels);
  375. }
  376. Log::record(implode(',',$names),Log::DEBUG);
  377. $names = $this->mChannelControl->match($names, $spec, $card_type, $quality, $max_inprice);
  378. if (!empty($names)) {
  379. return [$org_quality, $quality];
  380. } else {
  381. Log::record("Policy::find_quality fail: mchid=$mchid $quality-$spec-$card_type", Log::DEBUG);
  382. }
  383. }
  384. Log::record("Policy::find_quality fail: mchid=$mchid $spec-$card_type", Log::DEBUG);
  385. return [$org_quality,0];
  386. }
  387. public function allow($mchid,$card_type,$amount,$quality) : bool
  388. {
  389. return $this->mStorageLocker->allow($mchid,$card_type,$amount);
  390. }
  391. private function allow_storge($mchid,$card_type,$amount,$quality)
  392. {
  393. $reader = function ()
  394. {
  395. $cache = rcache("refill_able",'merchant-');
  396. if(!empty($cache)) {
  397. $result = unserialize($cache['data']);
  398. }
  399. else {
  400. $result = [];
  401. }
  402. return $result;
  403. };
  404. if(defined('MOBILE_SERVER') && MOBILE_SERVER === true)
  405. {
  406. if(StatesHelper::fetch_state('merchant')) {
  407. $this->mLimits = $reader();
  408. }
  409. }
  410. else {
  411. $this->mLimits = $reader();
  412. }
  413. $key = "{$mchid}-{$card_type}-{$amount}";
  414. if(empty($this->mLimits)) {
  415. return true;
  416. }
  417. elseif(array_key_exists($key,$this->mLimits)) {
  418. return $this->mLimits[$key];
  419. }
  420. else {
  421. return true;
  422. }
  423. }
  424. public function notify($order_info, $refill_info) : bool
  425. {
  426. $order_state = $order_info['order_state'];
  427. if ($order_state == ORDER_STATE_CANCEL) {
  428. $state = "CANCEL";
  429. } else {
  430. $state = "SUCCESS";
  431. }
  432. $mchid = $refill_info['mchid'];
  433. $mch_info = Model('merchant')->getMerchantInfo(['mchid' => $mchid]);
  434. [$params, $sign] = $this->body($state, $refill_info, $mch_info);
  435. $params['sign'] = $sign;
  436. $notify_url = $refill_info['notify_url'];
  437. //如果http请求内部,又发出回调自己的请求,在处理进程非动态扩容的情况下,容易造成阻塞.
  438. if ($this->is_url($notify_url)) {
  439. $resp = http_request($notify_url, $params, 'POST');
  440. } else {
  441. $resp = RBridgeFactory::instance()->notify($notify_url, $params);
  442. }
  443. return $resp == "SUCCESS" || $resp == 'FAILED';
  444. }
  445. private function body($state, $refill_info, $mch_info)
  446. {
  447. if($state == 'SUCCESS') {
  448. $err_msg = '';
  449. } else {
  450. $err_msg = 'fail';
  451. }
  452. $ctls = ['osn' => true, 'sms' => false];
  453. util::onEventCallback($refill_info, $mch_info, $ctls);
  454. if($ctls['osn']) {
  455. $osn = $refill_info['official_sn'] ?? "";
  456. } else {
  457. $osn = "";
  458. }
  459. $params = [
  460. "mchid" => $refill_info['mchid'],
  461. "order_sn" => $refill_info['mch_order'],
  462. "amount" => $refill_info['refill_amount'],
  463. "sale_price" => ncPriceFormat($refill_info['mch_amount']),
  464. "cardno" => $refill_info['card_no'],
  465. "trade_no" => $refill_info['order_sn'],
  466. "idcard" => $refill_info['idcard'] ?? "",
  467. "card_name" => $refill_info['card_name'] ?? "",
  468. 'official_sn' => $osn,
  469. 'message' => $err_msg,
  470. "state" => $state];
  471. if($ctls['sms'])
  472. {
  473. [$has_sms,$sms] = $this->sms($refill_info);
  474. if($has_sms) {
  475. $params['sms'] = $sms;
  476. }
  477. }
  478. $secure_key = $mch_info['secure_key'];
  479. $sign = $this->sign($params, $secure_key);
  480. return [$params, $sign];
  481. }
  482. public function notify_success($order_info, $refill_info) : bool
  483. {
  484. $gen_body = function ($state, $refill_info, $mch_info)
  485. {
  486. $err_msg = '';
  487. $osn = "";
  488. $params = [
  489. "mchid" => $refill_info['mchid'],
  490. "order_sn" => $refill_info['mch_order'],
  491. "amount" => $refill_info['refill_amount'],
  492. "sale_price" => ncPriceFormat($refill_info['mch_amount']),
  493. "cardno" => $refill_info['card_no'],
  494. "trade_no" => $refill_info['order_sn'],
  495. "idcard" => $refill_info['idcard'] ?? "",
  496. "card_name" => $refill_info['card_name'] ?? "",
  497. 'official_sn' => $osn,
  498. 'message' => $err_msg,
  499. "state" => $state];
  500. $secure_key = $mch_info['secure_key'];
  501. $sign = $this->sign($params, $secure_key);
  502. return [$params, $sign];
  503. };
  504. $state = "SUCCESS";
  505. $mchid = $refill_info['mchid'];
  506. $mch_info = Model('merchant')->getMerchantInfo(['mchid' => $mchid]);
  507. [$params, $sign] = $gen_body($state, $refill_info, $mch_info);
  508. $params['sign'] = $sign;
  509. $notify_url = $refill_info['notify_url'];
  510. //如果http请求内部,又发出回调自己的请求,在处理进程非动态扩容的情况下,容易造成阻塞.
  511. if ($this->is_url($notify_url)) {
  512. $resp = http_request($notify_url, $params, 'POST');
  513. } else {
  514. $resp = RBridgeFactory::instance()->notify($notify_url, $params);
  515. }
  516. return $resp == "SUCCESS" || $resp == 'FAILED';
  517. }
  518. private function sms($refill_info)
  519. {
  520. $official_sn = $refill_info['official_sn'] ?? "";
  521. $card_type = $refill_info['card_type'];
  522. $card_no = $refill_info['card_no'];
  523. $amount = intval($refill_info['refill_amount']);
  524. if(!empty($official_sn) && $card_type == mtopcard\SinopecCard && !empty($card_no))
  525. {
  526. $short_no = substr($card_no,-6);
  527. $ret = preg_match('/\d{4}(?P<month>\d{2})(?P<day>\d{2})(?P<hour>\d{2})(?P<min>\d{2})\d{4}/u', $official_sn, $matches);
  528. if($ret > 0) {
  529. $sms = "【中国石化】您尾号为{$short_no}的加油卡于{$matches['month']}月{$matches['day']}日 {$matches['hour']}时{$matches['min']}分充值成功,金额{$amount}元,订单号:{$official_sn}";
  530. return [true,$sms];
  531. }
  532. }
  533. return [false,''];
  534. }
  535. private function sign($params, $key)
  536. {
  537. ksort($params);
  538. $body = "";
  539. $i = 0;
  540. foreach ($params as $k => $v) {
  541. if (false === $this->check_empty($v) && "@" != substr($v, 0, 1)) {
  542. if ($i == 0) {
  543. $body .= "$k" . "=" . urlencode($v);
  544. } else {
  545. $body .= "&" . "$k" . "=" . urlencode($v);
  546. }
  547. $i++;
  548. }
  549. }
  550. $body .= "&key=$key";
  551. Log::record("notify_body=$body", Log::DEBUG);
  552. return md5($body);
  553. }
  554. private function check_empty($value)
  555. {
  556. if (!isset($value))
  557. return true;
  558. if ($value === null)
  559. return true;
  560. if (trim($value) === "")
  561. return true;
  562. return false;
  563. }
  564. private function is_url($url)
  565. {
  566. $checker = function ($haystack, $needle) {
  567. $length = strlen($needle);
  568. return (substr($haystack, 0, $length) === $needle);
  569. };
  570. return $checker($url, "http://") || $checker($url, "https://");
  571. }
  572. public function need_intercept($mchid,$card_type,$card_state,$is_transfer,$card_no) : bool
  573. {
  574. return $this->mRatioCtl->need_intercept($mchid,$card_type,$card_state,$is_transfer,$card_no);
  575. }
  576. public function region_intercept($quality,$card_type,$region_no) : bool
  577. {
  578. return $this->mGlobalInterceptor->isIntercept($quality,$card_type,$region_no);
  579. }
  580. public function update_mchratios($gross,$detail,$types)
  581. {
  582. $this->mRatioCtl->update($gross,$detail,$types);
  583. }
  584. public function update_chctl($params)
  585. {
  586. $this->mChannelControl->update_chctl($params);
  587. }
  588. public function update_maxspeeds($speeds)
  589. {
  590. $this->mChannelControl->update_maxspeeds($speeds);
  591. }
  592. public function update_chspeeds($speeds)
  593. {
  594. $this->mChSpeed->update_cur($speeds);
  595. }
  596. public function is_over_chspeed($chname)
  597. {
  598. return $this->mChSpeed->is_over_chspeed($chname);
  599. }
  600. public function third_retry(order $order): array
  601. {
  602. return $this->mThirdHelper->third_retry($order);
  603. }
  604. public function third_mixed($mchid,$pcode): bool
  605. {
  606. return $this->mThirdHelper->mixed($mchid,$pcode);
  607. }
  608. }