PaySwitch.php 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519
  1. <?php
  2. /**
  3. * PaySwitch.php UTF-8
  4. * 支付切换判断
  5. *
  6. * @date : 2018/6/8 17:32
  7. *
  8. * @license 这不是一个自由软件,未经授权不许任何使用和传播。
  9. * @author : wuyonghong <wyh@huosdk.com>
  10. * @version : HUOSDK 8.0
  11. */
  12. namespace huo\controller\pay;
  13. use huo\controller\common\Base;
  14. use huo\controller\game\Game;
  15. use huo\controller\game\GamePaySwitchCache;
  16. use huo\controller\member\MemCache;
  17. use huo\controller\request\Channel;
  18. use huo\controller\request\Device;
  19. use huo\controller\request\Game as GameRq;
  20. use huo\controller\request\Mem;
  21. use huo\controller\request\Order as OrderRq;
  22. use huo\controller\request\Role;
  23. use huo\logic\order\OrderLogic;
  24. use huo\model\game\GameServerSwitchModel;
  25. use huo\model\game\PsMemWhiteModel;
  26. use huo\model\member\MgRoleModel;
  27. use huolib\constant\GameConst;
  28. use huolib\constant\OrderConst;
  29. use huolib\tool\Ip;
  30. class PaySwitch extends Base {
  31. /**
  32. * 判断支付切换
  33. *
  34. * @param OrderRq $order
  35. * @param Role $role
  36. * @param Mem $mem
  37. * @param GameRq $game_rq
  38. * @param Channel $channel
  39. * @param Device $device
  40. *
  41. * @return int PAY_SWITCH_YES 1 切换 PAY_SWITCH_NO 2 不切换
  42. */
  43. public function getPaySwitch(OrderRq $order, Role $role, Mem $mem, GameRq $game_rq, Channel $channel, Device $device
  44. ) {
  45. $_from = $device->getFrom();
  46. $_vb_id = $game_rq->getVbId();
  47. if (GameConst::GAME_IOS_SWITCH != $_from && GameConst::GAME_MP != $_from && empty($_vb_id)) {
  48. return OrderConst::PAY_SWITCH_NO;
  49. }
  50. /* 查询游戏是否是切换 */
  51. $_app_id = $game_rq->getHAppId();
  52. $_switch_rule_app_id = $_app_id;
  53. $_game_class = new Game();
  54. /* 使用马甲包的规则 */
  55. if (!empty($_vb_id)) {
  56. $_switch_rule_app_id = $_vb_id;
  57. }
  58. $_pay_switch = $_game_class->getPaySwitchStatus($_switch_rule_app_id);
  59. if (OrderConst::PAY_SWITCH_NO == $_pay_switch) {
  60. return OrderConst::PAY_SWITCH_NO;
  61. }
  62. /* 获取切换规则 */
  63. $_switch_rule = GamePaySwitchCache::ins()->getInfoByAppId($_switch_rule_app_id);
  64. if (empty($_switch_rule)) {
  65. /* 规则为空时直接返回切换状态 */
  66. return $_pay_switch;
  67. }
  68. /* 判断玩家是否在白名单 */
  69. $_rs = $this->inMemWhite($_switch_rule_app_id, $mem->getMemId());
  70. if (true == $_rs) {
  71. /* IP白名单内的直接返回切换状态 */
  72. return $_pay_switch;
  73. }
  74. /* 判断IP是否在白名单 */
  75. $_rs = $this->inIpWhite($device->getIp(), $_switch_rule['ip_white']);
  76. if (true == $_rs) {
  77. /* IP白名单内的直接返回切换状态 */
  78. return $_pay_switch;
  79. }
  80. /* 判断城市是否切换 */
  81. $_rs = $this->inArea($device->getIp(), $_switch_rule['area']);
  82. if (OrderConst::PAY_SWITCH_NO == $_rs) {
  83. $_mem_ext_info = MemCache::ins()->getMeInfoById($mem->getMemId());
  84. /* 已充值6元以上的用户不受地区切换限制 */
  85. if (empty($_mem_ext_info['sum_money']) || 6 >= $_mem_ext_info['sum_money']) {
  86. return OrderConst::PAY_SWITCH_NO;
  87. }
  88. }
  89. $_client_id = $game_rq->getHVer();
  90. /* 判断版本是否切换 */
  91. $_rs = $this->switchVersion($_client_id, $_switch_rule['no_switch_version']);
  92. if (OrderConst::PAY_SWITCH_NO == $_rs) {
  93. return OrderConst::PAY_SWITCH_NO;
  94. }
  95. /* 根据时间判断是否是否切换 */
  96. $_rs = $this->switchTime($_switch_rule['start_time'], $_switch_rule['end_time']);
  97. if (OrderConst::PAY_SWITCH_NO == $_rs) {
  98. return OrderConst::PAY_SWITCH_NO;
  99. }
  100. /* 根据IP段判断是否切换 */
  101. $_rs = $this->switchIp($device->getIp(), $_switch_rule['is_domestic'], $_switch_rule['is_overseas']);
  102. if (OrderConst::PAY_SWITCH_NO == $_rs) {
  103. return OrderConst::PAY_SWITCH_NO;
  104. }
  105. /* Modified by chenbingling BEGIN 2020/12/30 ISSUES:#13939 产品需求 IOS不判断首充 */
  106. $_os = $device->getOs();
  107. if (false !== strpos(strtolower($_os), 'android')) {
  108. /* 根据首充是否切换 */
  109. $_rs = $this->switchFirst($mem->getMemId(), $_app_id, $_switch_rule['is_first']);
  110. if (OrderConst::PAY_SWITCH_NO == $_rs) {
  111. return OrderConst::PAY_SWITCH_NO;
  112. }
  113. }
  114. /* END 2020/12/30 ISSUES:#13939 */
  115. /* 根据金额是否切换 */
  116. $_rs = $this->switchMoney($order->getProductRealPrice(), $_switch_rule['price']);
  117. if (OrderConst::PAY_SWITCH_NO == $_rs) {
  118. return OrderConst::PAY_SWITCH_NO;
  119. }
  120. /* 判断版本是否切换 */
  121. $_rs = $this->switchOs($_os, $_switch_rule['system']);
  122. if (OrderConst::PAY_SWITCH_NO == $_rs) {
  123. return OrderConst::PAY_SWITCH_NO;
  124. }
  125. /* 判断区服是否切换 */
  126. $_rs = $this->switchSever($_app_id, $role->getServerId());
  127. if (OrderConst::PAY_SWITCH_NO == $_rs) {
  128. return OrderConst::PAY_SWITCH_NO;
  129. }
  130. /* 判断战力是否切换 */
  131. if (empty($_switch_rule['combat_num_mini']) && empty($_switch_rule['combat_num_max'])) {
  132. /* 未填写表示不启用功能,返回切换 */
  133. return OrderConst::PAY_SWITCH_YES;
  134. }
  135. $_combat_num = $role->getCombatNum();
  136. if (empty($_combat_num)) {
  137. $_data = (new MgRoleModel())->getDetailByMemGameServerRole(
  138. $mem->getMgMemId(), $_app_id, $role->getServerId(), $role->getRoleId()
  139. );
  140. $_combat_num = empty($_data['combat_num']) ? 0 : $_data['combat_num'];
  141. }
  142. $_rs = $this->switchCombat($_combat_num, $_switch_rule['combat_num_mini'], $_switch_rule['combat_num_max']);
  143. if (OrderConst::PAY_SWITCH_NO == $_rs) {
  144. return OrderConst::PAY_SWITCH_NO;
  145. }
  146. return OrderConst::PAY_SWITCH_YES;
  147. }
  148. /**
  149. * 判断切换
  150. *
  151. * @param GameRq $game_rq
  152. * @param Device $device
  153. *
  154. * @return int PAY_SWITCH_YES 1 切换 PAY_SWITCH_NO 2 不切换
  155. */
  156. public function getSwitch(GameRq $game_rq, Device $device) {
  157. /* 查询游戏是否是切换 */
  158. $_app_id = $game_rq->getHAppId();
  159. $_pay_switch = (new Game())->getPaySwitchStatus($_app_id);
  160. if (OrderConst::PAY_SWITCH_NO == $_pay_switch) {
  161. return OrderConst::PAY_SWITCH_NO;
  162. }
  163. /* 获取切换规则 */
  164. $_switch_rule = GamePaySwitchCache::ins()->getInfoByAppId($_app_id);
  165. if (empty($_switch_rule)) {
  166. /* 规则为空时直接返回切换状态 */
  167. return $_pay_switch;
  168. }
  169. /* 判断IP是否在白名单 */
  170. $_rs = $this->inIpWhite($device->getIp(), $_switch_rule['ip_white']);
  171. if (true == $_rs) {
  172. /* IP白名单内的直接返回切换状态 */
  173. return $_pay_switch;
  174. }
  175. /* 判断城市是否切换 */
  176. $_rs = $this->inArea($device->getIp(), $_switch_rule['area']);
  177. if (OrderConst::PAY_SWITCH_NO == $_rs) {
  178. return OrderConst::PAY_SWITCH_NO;
  179. }
  180. $_client_id = $game_rq->getHVer();
  181. /* 判断版本是否切换 */
  182. $_rs = $this->switchVersion($_client_id, $_switch_rule['no_switch_version']);
  183. if (OrderConst::PAY_SWITCH_NO == $_rs) {
  184. return OrderConst::PAY_SWITCH_NO;
  185. }
  186. /* 根据时间判断是否是否切换 */
  187. $_rs = $this->switchTime($_switch_rule['start_time'], $_switch_rule['end_time']);
  188. if (OrderConst::PAY_SWITCH_NO == $_rs) {
  189. return OrderConst::PAY_SWITCH_NO;
  190. }
  191. /* 根据IP段判断是否切换 */
  192. $_rs = $this->switchIp($device->getIp(), $_switch_rule['is_domestic'], $_switch_rule['is_overseas']);
  193. if (OrderConst::PAY_SWITCH_NO == $_rs) {
  194. return OrderConst::PAY_SWITCH_NO;
  195. }
  196. $_os = $device->getOs();
  197. /* 判断版本是否切换 */
  198. $_rs = $this->switchOs($_os, $_switch_rule['system']);
  199. if (OrderConst::PAY_SWITCH_NO == $_rs) {
  200. return OrderConst::PAY_SWITCH_NO;
  201. }
  202. return OrderConst::PAY_SWITCH_YES;
  203. }
  204. /**
  205. * 判断是否在IP白名单
  206. *
  207. * @param string $ip 当前ip
  208. * @param string $area 不切换的城市名
  209. *
  210. * @return int
  211. */
  212. public function inArea($ip, $area) {
  213. if (empty($area)) {
  214. /* 没城市则返回切换 */
  215. return OrderConst::PAY_SWITCH_YES;
  216. }
  217. $_area_array = explode('|', $area);
  218. if (empty($_area_array)) {
  219. return OrderConst::PAY_SWITCH_YES;
  220. }
  221. $_ip_arr = Ip::find($ip);
  222. if (empty($_ip_arr)) {
  223. /* 未知IP不切换 */
  224. return OrderConst::PAY_SWITCH_NO;
  225. }
  226. if (in_array($_ip_arr[2], $_area_array)) {
  227. /* 如果城市名在不切换城市 */
  228. return OrderConst::PAY_SWITCH_NO;
  229. }
  230. return OrderConst::PAY_SWITCH_YES;
  231. }
  232. /**
  233. * 判断是否在玩家白名单
  234. *
  235. * @param int $app_id 游戏id
  236. * @param int $mem_id 当前mem_id
  237. *
  238. * @return bool
  239. */
  240. public function inMemWhite($app_id, $mem_id) {
  241. $_data = (new PsMemWhiteModel())->getInfo($app_id, $mem_id);
  242. if (!empty($_data)) {
  243. return true;
  244. }
  245. return false;
  246. }
  247. /**
  248. * 判断是否在IP白名单
  249. *
  250. * @param string $ip 当前ip
  251. * @param string $ip_white ip白名单字符串
  252. *
  253. * @return bool
  254. */
  255. public function inIpWhite($ip, $ip_white) {
  256. if (empty($ip_white)) {
  257. /* 没白名单则返回跳过 */
  258. return false;
  259. }
  260. $_ip_array = explode('|', $ip_white);
  261. if (empty($_ip_array)) {
  262. return false;
  263. }
  264. if (in_array($ip, $_ip_array)) {
  265. return true;
  266. }
  267. return false;
  268. }
  269. /**
  270. * 判断战力是否切换
  271. *
  272. * @param int $combat_num 角色战力
  273. * @param int $combat_num_mini 战力区间小值
  274. * @param int $combat_num_max 战力区间大值
  275. *
  276. * @return int
  277. */
  278. public function switchCombat($combat_num, $combat_num_mini, $combat_num_max) {
  279. if (empty($combat_num)) {
  280. /* 没有战力表示 不切换 */
  281. return OrderConst::PAY_SWITCH_NO;
  282. }
  283. if ($combat_num_mini < $combat_num && $combat_num < $combat_num_max) {
  284. /* 战力区间内表示切换*/
  285. return OrderConst::PAY_SWITCH_YES;
  286. }
  287. return OrderConst::PAY_SWITCH_NO;
  288. }
  289. /**
  290. * 判断区服是否切换
  291. *
  292. * @param int $app_id 游戏id
  293. * @param int $sever_id 区服id
  294. *
  295. * @return int
  296. */
  297. public function switchSever($app_id, $sever_id) {
  298. /* 传入空值则全部切换 */
  299. if (empty($app_id) || empty($sever_id)) {
  300. return OrderConst::PAY_SWITCH_YES;
  301. }
  302. $_data = (new GameServerSwitchModel())->getInfo($app_id, $sever_id);
  303. if (empty($_data)) {
  304. /* 不存在区服信息则不切换 */
  305. return OrderConst::PAY_SWITCH_YES;
  306. }
  307. return $_data['is_switch'];
  308. }
  309. /**
  310. * 判断版本号是否切换
  311. *
  312. * @param int $client_id 版本ID
  313. * @param string $rule_clients 不切换的版本
  314. *
  315. * @return int PAY_SWITCH_YES 1 切换 PAY_SWITCH_NO 2 不切换
  316. */
  317. public function switchVersion($client_id = 0, $rule_clients = '') {
  318. if (empty($rule_clients) || empty($client_id)) {
  319. /* 没有设置不切换版本 全部切换 */
  320. return OrderConst::PAY_SWITCH_YES;
  321. }
  322. $_rule_clients = trim($rule_clients, ',');
  323. if ($client_id == $_rule_clients) {
  324. /* 当前版本等于不切换版本 不切换 */
  325. return OrderConst::PAY_SWITCH_NO;
  326. }
  327. if (false == strpos($rule_clients, ',')) {
  328. $_rule_clients_arr = explode(',', $_rule_clients);
  329. if (is_array($_rule_clients_arr) && in_array($client_id, $_rule_clients_arr)) {
  330. /* 当前版本在不切换版本内 不切换 */
  331. return OrderConst::PAY_SWITCH_NO;
  332. }
  333. }
  334. return OrderConst::PAY_SWITCH_YES;
  335. }
  336. /**
  337. * 判断操作系统是否切换
  338. *
  339. * @param string $os 操作系统
  340. * @param string $rule_os 切换的操作系统
  341. *
  342. * @return int PAY_SWITCH_YES 1 切换 PAY_SWITCH_NO 2 不切换 PAY_SWITCH_IOS_NO 3 IOS不切换关闭
  343. */
  344. public function switchOs($os = '', $rule_os = '') {
  345. if (empty($rule_os) || empty($os)) {
  346. /* 没有设置不切换版本 全部切换 */
  347. return OrderConst::PAY_SWITCH_YES;
  348. }
  349. if (false !== strpos(strtolower($os), 'ios')
  350. && false !== strpos($rule_os, strval(GameConst::GAME_IOS))) {
  351. /* 设置切换IOS */
  352. return OrderConst::PAY_SWITCH_YES;
  353. } elseif (false !== strpos(strtolower($os), 'android')
  354. && false !== strpos($rule_os, strval(GameConst::GAME_ANDROID))) {
  355. /* 设置切换安卓 */
  356. return OrderConst::PAY_SWITCH_YES;
  357. }
  358. /* IOS 不切换 关闭支付 米大师目前不支持IOS支付,故关闭,后续开发需删除当前代码 chenbingling 20181207 _start*/
  359. if (false !== strpos(strtolower($os), 'ios')) {
  360. return OrderConst::PAY_SWITCH_IOS_NO;
  361. }
  362. /* IOS 不切换 关闭支付 米大师目前不支持IOS支付,故关闭,后续开发需删除当前代码 chenbingling 20181207 _end*/
  363. return OrderConst::PAY_SWITCH_NO;
  364. }
  365. /**
  366. * 判断是否在时间范围内
  367. *
  368. * @param String $start_time
  369. * @param INT $end_time
  370. *
  371. * @return int PAY_SWITCH_YES 1 切换 PAY_SWITCH_NO 2 不切换
  372. */
  373. public function switchTime($start_time, $end_time) {
  374. if (empty($start_time)) {
  375. $start_time = '00:00:00';
  376. }
  377. if (empty($end_time)) {
  378. $end_time = '23:59:59';
  379. }
  380. if ($end_time == '00:00:00') {
  381. $end_time = '23:59:59';
  382. }
  383. if ($start_time == $end_time) {
  384. $start_time = '00:00:00';
  385. $end_time = '23:59:59';
  386. }
  387. $_time = time();
  388. $_start_time = strtotime(date('Y-m-d').' '.$start_time);
  389. $_end_time = strtotime(date('Y-m-d').' '.$end_time);
  390. if ($_time < $_start_time || $_time > $_end_time) {
  391. return OrderConst::PAY_SWITCH_NO;
  392. }
  393. return OrderConst::PAY_SWITCH_YES;
  394. }
  395. /**
  396. * 判断IP是否是国内IP
  397. *
  398. * @param string $ip IP地址
  399. * @param int $is_domestic 国内是否切换 1切换 2不切换
  400. * @param int $is_overseas 国外是否切换 1切换 2不切换
  401. *
  402. * @return int PAY_SWITCH_YES 1 切换 PAY_SWITCH_NO 2 不切换
  403. */
  404. public function switchIp($ip, $is_domestic, $is_overseas) {
  405. if (empty($is_domestic) && empty($is_overseas)) {
  406. return OrderConst::PAY_SWITCH_YES;
  407. }
  408. if (OrderConst::PAY_SWITCH_YES == $is_domestic && OrderConst::PAY_SWITCH_YES == $is_overseas) {
  409. return OrderConst::PAY_SWITCH_YES;
  410. }
  411. $_ip_arr = Ip::find($ip);
  412. if (empty($_ip_arr)) {
  413. /* 未知IP不切换 */
  414. return OrderConst::PAY_SWITCH_NO;
  415. }
  416. /* 根据统计需要,港澳台地区放入海外处理 */
  417. $_domestic_except = array('台湾', '香港', '澳门');
  418. $_ip_is_domestic = false;
  419. if (is_array($_ip_arr) && '中国' == $_ip_arr[0]) {
  420. $_ip_is_domestic = true;
  421. if (!empty($_ip_arr[1]) && in_array($_ip_arr[1], $_domestic_except)) {
  422. $_ip_is_domestic = false;
  423. }
  424. }
  425. if (true == $_ip_is_domestic && OrderConst::PAY_SWITCH_NO == $is_domestic) {
  426. return OrderConst::PAY_SWITCH_NO;
  427. }
  428. if (false == $_ip_is_domestic && OrderConst::PAY_SWITCH_NO == $is_overseas) {
  429. return OrderConst::PAY_SWITCH_NO;
  430. }
  431. return OrderConst::PAY_SWITCH_YES;
  432. }
  433. /**
  434. * 判断首充是否切换
  435. *
  436. * @param INT $mem_id 玩家ID
  437. * @param INT $app_id 游戏ID
  438. * @param INT $is_first 是否首冲不切换 1切换 2不切换
  439. *
  440. * @return int PAY_SWITCH_YES 1 切换 PAY_SWITCH_NO 2 不切换
  441. */
  442. public function switchFirst($mem_id, $app_id, $is_first) {
  443. if (OrderConst::PAY_IS_FIRST != $is_first) {
  444. return OrderConst::PAY_SWITCH_YES;
  445. }
  446. $_map = [
  447. 'app_id' => $app_id,
  448. 'mem_id' => $mem_id,
  449. 'status' => OrderConst::PAY_STATUS_SUC
  450. ];
  451. $_rs = (new OrderLogic())->isFirstCharge($_map);
  452. if (true == $_rs) {
  453. /* 首充 不切换 */
  454. return OrderConst::PAY_SWITCH_NO;
  455. }
  456. return OrderConst::PAY_SWITCH_YES;
  457. }
  458. /**
  459. * 判断首充是否切换
  460. *
  461. * @param float $amount 订单金额
  462. * @param float $rule_money 规则金额
  463. *
  464. * @return int PAY_SWITCH_YES 1 切换 PAY_SWITCH_NO 2 不切换
  465. */
  466. public function switchMoney($amount, $rule_money = 0.00) {
  467. if (empty($rule_money)) {
  468. /* 没有设置金额 全部切换 */
  469. return OrderConst::PAY_SWITCH_YES;
  470. }
  471. if ($amount < $rule_money) {
  472. /* 金额小于设置金额 不切换 */
  473. return OrderConst::PAY_SWITCH_NO;
  474. }
  475. return OrderConst::PAY_SWITCH_YES;
  476. }
  477. public function checkShowPay($pay_check, Device $device_rq) {
  478. $_pay_check = $pay_check;
  479. if (OrderConst::PAY_SWITCH_NO == $_pay_check) {
  480. //IOS 不切换 关闭支付 米大师目前不支持IOS支付,故关闭,后续开发需删除当前代码 chenbingling 20181207 _start
  481. $_os = $device_rq->getOs();
  482. if (false !== strpos(strtolower($_os), 'ios')) {
  483. $_pay_check = OrderConst::PAY_SWITCH_IOS_NO;
  484. }
  485. }
  486. return $_pay_check;
  487. }
  488. }