V2ApiBaseController.php 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852
  1. <?php
  2. /**
  3. * V2ApiBaseController.php UTF-8
  4. * V2版本接口校验
  5. *
  6. * @date : 2018/1/15 21:35
  7. *
  8. * @license 这不是一个自由软件,未经授权不许任何使用和传播。
  9. * @author : wuyonghong <wyh@huosdk.com>
  10. * @version : HUOSDK 8.0
  11. */
  12. namespace mini\common\controller;
  13. use huo\controller\common\CommonFunc;
  14. use huo\controller\common\HuoSession;
  15. use huo\controller\game\GameCache;
  16. use huo\controller\member\Member;
  17. use huo\controller\member\MemCache;
  18. use huo\controller\request\Channel;
  19. use huo\controller\request\Crash;
  20. use huo\controller\request\Device;
  21. use huo\controller\request\Event;
  22. use huo\controller\request\Game;
  23. use huo\controller\request\Mem;
  24. use huo\controller\request\Order;
  25. use huo\controller\request\Role;
  26. use huo\logic\game\GameLogic;
  27. use huo\model\game\GameModel;
  28. use huoCheck\HuoApiV2;
  29. use huolib\constant\CommonConst;
  30. use huolib\constant\DeviceTypeConst;
  31. use huolib\constant\FormatConst;
  32. use huolib\constant\GameConst;
  33. use huolib\status\CommonStatus;
  34. use huolib\status\MemberStatus;
  35. use huolib\status\OrderStatus;
  36. use huomp\controller\member\MemberOut;
  37. use think\Config;
  38. use think\Controller;
  39. use think\Db;
  40. use think\exception\HttpResponseException;
  41. use think\exception\ValidateException;
  42. use think\Loader;
  43. use think\Response;
  44. class V2ApiBaseController extends Controller {
  45. //token
  46. protected $token = '';
  47. //设备类型
  48. protected $device_type = '';
  49. //用户 id
  50. protected $mem_id = 0;
  51. // 语言
  52. protected $lang = 'en';
  53. //用户
  54. protected $user;
  55. /* 返回类型 */
  56. protected $response_type = 'json';
  57. //用户类型
  58. protected $user_type;
  59. protected $allowed_device_types = ['mobile', 'android', 'iphone', 'ipad', 'web', 'pc', 'mac', 'wxapp', 'wxmini'];
  60. /**
  61. * @var \think\Request Request实例
  62. */
  63. protected $request;
  64. protected $agent_site; /* 渠道专属链接 */
  65. // 验证失败是否抛出异常
  66. protected $fail_exception = false;
  67. // 是否批量验证
  68. protected $batch_validate = false;
  69. protected $rq_data = [];
  70. protected $sess_config
  71. = [
  72. 'id' => '',
  73. 'prefix' => '',
  74. 'type' => '',
  75. 'expire' => CommonConst::CONST_DAY_SECONDS
  76. ];
  77. /**
  78. * 前置操作方法列表
  79. *
  80. * @var array $before_action_list
  81. * @access protected
  82. */
  83. protected $before_action_list = [];
  84. // 初始化
  85. private function _initLang() {
  86. $_lang = $this->request->header('HS-Lang/s', 'en-us');
  87. $this->lang = $_lang;
  88. config('default_lang', $this->lang);
  89. }
  90. /**
  91. * 获取设备类型
  92. *
  93. * @return string
  94. */
  95. public function getDeviceType() {
  96. if ($this->request->isWeixin()) {
  97. return DeviceTypeConst::DEVICE_TYPE_WEIXIN;
  98. }
  99. if ($this->request->isMobile()) {
  100. return DeviceTypeConst::DEVICE_TYPE_WAP;
  101. }
  102. return DeviceTypeConst::DEVICE_TYPE_PC;
  103. }
  104. /**
  105. *
  106. */
  107. private function _initUser() {
  108. // $_token = HuoCookie::getMemToken();
  109. if (empty($_token)) {
  110. $_token = $this->request->param('token/s', '');
  111. }
  112. $_game_data = get_val($this->rq_data, 'game', []);
  113. $_device_type = get_val($_game_data, 'mp_id');
  114. $_wx_param['wx_app_id'] = $this->request->param('wx_app_id/s', '');
  115. if (!empty($_wx_param['wx_app_id'])) {
  116. $this->device_type = $_wx_param['wx_app_id'];
  117. } elseif (!empty($_device_type)) {
  118. $this->device_type = $_device_type;
  119. } else {
  120. $this->device_type = DeviceTypeConst::DEVICE_TYPE_MP;
  121. }
  122. $_mem_id = $this->getMemIdByToken($_token, $this->device_type);
  123. if (!empty($_mem_id)) {
  124. $this->mem_id = $_mem_id;
  125. }
  126. if (APP_DEBUG) {
  127. /* 调试环境直接登陆 */
  128. $_mem_id = $this->request->param('debug_mem_id/s', 0);
  129. if (!empty($_mem_id)) {
  130. $this->mem_id = $_mem_id;
  131. // Session::clear();
  132. // HuoSession::setMemId($_mem_id);
  133. }
  134. }
  135. }
  136. protected function _initialize() {
  137. $this->response_type = $this->request->param('format/s', FormatConst::FORMAT_HTML);
  138. $_token = $this->request->param('token/s', '');
  139. if (!empty($_token)) {
  140. $this->token = $_token;
  141. }
  142. Config::set('default_return_type', $this->response_type);
  143. $this->_initLang();
  144. $this->checkParam();
  145. // 用户验证初始化
  146. $this->_initUser();
  147. /* 记录请求数据 */
  148. if ($this->request->isOptions()) {
  149. $this->success();
  150. }
  151. }
  152. /**
  153. * 前置操作
  154. *
  155. * @access protected
  156. *
  157. * @param string $method 前置操作方法名
  158. * @param array $options 调用参数 ['only'=>[...]] 或者['except'=>[...]]
  159. */
  160. protected function beforeAction($method, $options = []) {
  161. if (isset($options['only'])) {
  162. if (is_string($options['only'])) {
  163. $options['only'] = explode(',', $options['only']);
  164. }
  165. if (!in_array($this->request->action(), $options['only'])) {
  166. return;
  167. }
  168. } elseif (isset($options['except'])) {
  169. if (is_string($options['except'])) {
  170. $options['except'] = explode(',', $options['except']);
  171. }
  172. if (in_array($this->request->action(), $options['except'])) {
  173. return;
  174. }
  175. }
  176. call_user_func([$this, $method]);
  177. }
  178. /**
  179. * @param $token
  180. * @param $device_type
  181. *
  182. * @return array|bool|false|\PDOStatement|string|\think\Model
  183. */
  184. public function getMemIdByToken($token, $device_type) {
  185. if (empty($token)) {
  186. return 0;
  187. }
  188. $_path = 'mp/wx/login';
  189. $_is_up = $_path == request()->path() ? true : false;
  190. $_mem_id = (new Member())->getMemIdByToken($token, $device_type, $_is_up);
  191. if (empty($_mem_id)) {
  192. return 0;
  193. }
  194. return $_mem_id;
  195. }
  196. /**
  197. * 返回数据
  198. *
  199. * @param array $data
  200. */
  201. protected function returnData($data = []) {
  202. $_msg = $data['msg'];
  203. $_code = $data['code'];
  204. $_data = $data['data'];
  205. if (CommonStatus::NO_ERROR != $_code) {
  206. $this->error($_msg, $_data, $_code);
  207. }
  208. $this->success($_msg, $_data, $_code);
  209. }
  210. /**
  211. * 操作错误跳转的快捷方法
  212. *
  213. * @access protected
  214. *
  215. * @param mixed $msg 提示信息,若要指定错误码,可以传数组,格式为['code'=>您的错误码,'msg'=>'您的错误消息']
  216. * @param mixed $data 返回的数据
  217. * @param int $code
  218. *
  219. * @param array $header 发送的Header信息
  220. *
  221. * @param null $url
  222. * @param int $wait
  223. *
  224. * @return void
  225. */
  226. protected function error($msg = '', $data = '', $code = 400, array $header = [], $url = null, $wait = 3) {
  227. $type = $this->getResponseType();
  228. if ('html' == $type) {
  229. parent::error($msg, $data, $code, $header, $url, $wait);
  230. }
  231. if (empty($data)) {
  232. $data = null;
  233. }
  234. $result = [
  235. 'code' => $code,
  236. 'msg' => $msg,
  237. 'data' => $data,
  238. ];
  239. \think\Log::write($result, 'debug', true);
  240. $header['Access-Control-Allow-Origin'] = '*';
  241. $header['Access-Control-Allow-Headers'] = 'X-Requested-With,Content-Type,HS-Device-Type,HS-Token,HS-Lang';
  242. $header['Access-Control-Allow-Methods'] = 'GET,POST,PATCH,PUT,DELETE,OPTIONS';
  243. $response = Response::create($result, $type)->header($header);
  244. throw new HttpResponseException($response);
  245. }
  246. /**
  247. * 获取当前的response 输出类型
  248. *
  249. * @access protected
  250. * @return string
  251. */
  252. protected function getResponseType() {
  253. return $this->response_type;
  254. }
  255. /**
  256. * 获取当前登录用户的id
  257. *
  258. * @return int
  259. */
  260. public function getMemId() {
  261. if (empty($this->mem_id)) {
  262. $this->error(lang('NO_LOGIN'), '', 1002);
  263. }
  264. // $this->mem_id = rand(1, 10);
  265. return $this->mem_id;
  266. }
  267. /**
  268. * 设置验证失败后是否抛出异常
  269. *
  270. * @access protected
  271. *
  272. * @param bool $fail 是否抛出异常
  273. *
  274. * @return $this
  275. */
  276. protected function validateFailException($fail = true) {
  277. $this->fail_exception = $fail;
  278. return $this;
  279. }
  280. /**
  281. * 验证数据
  282. *
  283. * @access protected
  284. *
  285. * @param array $data 数据
  286. * @param string|array $validate 验证器名或者验证规则数组
  287. * @param array $message 提示信息
  288. * @param bool $batch 是否批量验证
  289. * @param mixed $callback 回调方法(闭包)
  290. *
  291. * @return array|string|true
  292. * @throws ValidateException
  293. */
  294. protected function validate($data, $validate, $message = [], $batch = false, $callback = null) {
  295. if (is_array($validate)) {
  296. $_valid_class = Loader::validate();
  297. $_valid_class->rule($validate);
  298. } else {
  299. if (strpos($validate, '.')) {
  300. // 支持场景
  301. list($validate, $scene) = explode('.', $validate);
  302. }
  303. $_valid_class = Loader::validate($validate);
  304. if (!empty($scene)) {
  305. $_valid_class->scene($scene);
  306. }
  307. }
  308. // 是否批量验证
  309. if ($batch || $this->batch_validate) {
  310. $_valid_class->batch(true);
  311. }
  312. if (is_array($message)) {
  313. $_valid_class->message($message);
  314. }
  315. if ($callback && is_callable($callback)) {
  316. call_user_func_array($callback, [$_valid_class, &$data]);
  317. }
  318. if (!$_valid_class->check($data)) {
  319. if ($this->fail_exception) {
  320. throw new ValidateException($_valid_class->getError());
  321. } else {
  322. return $_valid_class->getError();
  323. }
  324. } else {
  325. return true;
  326. }
  327. }
  328. /**
  329. * 操作成功跳转的快捷方法
  330. *
  331. * @access protected
  332. *
  333. * @param mixed $msg 提示信息
  334. * @param mixed $data 返回的数据
  335. * @param array $header 发送的Header信息
  336. *
  337. * @param int $code 返回码
  338. *
  339. * @return void
  340. */
  341. protected function success($msg = '', $data = '', $code = 200, array $header = [], $url = null, $wait = 3) {
  342. $type = $this->getResponseType();
  343. if ('html' == $type) {
  344. parent::success($msg, $data, $code, $header, $url, $wait);
  345. }
  346. if (empty($data)) {
  347. $data = null;
  348. }
  349. $result = [
  350. 'code' => $code,
  351. 'msg' => $msg,
  352. 'data' => $data,
  353. ];
  354. $header['Access-Control-Allow-Origin'] = '*';
  355. $header['Access-Control-Allow-Headers'] = 'X-Requested-With,Content-Type,HS-Device-Type,HS-Token,HS-Lang';
  356. $header['Access-Control-Allow-Methods'] = 'GET,POST,PATCH,PUT,DELETE,OPTIONS';
  357. $response = Response::create($result, $type)->header($header);
  358. throw new HttpResponseException($response);
  359. }
  360. protected function checkParam() {
  361. $_is_json = false;
  362. $_params = $_REQUEST;
  363. $this->rq_data = $this->getParam($_params, $_is_json);
  364. if (empty($this->rq_data)) {
  365. $this->rq_data = [];
  366. }
  367. // $this->checkSign();
  368. // $this->checkTime();
  369. }
  370. /**
  371. * 获取请求参数
  372. *
  373. * @param mixed $param
  374. * @param bool $is_json
  375. *
  376. * @return bool|mixed|string
  377. */
  378. public function getParam($param, $is_json = false) {
  379. if (empty($param)) {
  380. return '';
  381. }
  382. if ($is_json) {
  383. $_param = json_decode($param, true);
  384. if (JSON_ERROR_NONE != json_last_error()) {
  385. return false;
  386. }
  387. } else {
  388. foreach ($param as $_k => $_v) {
  389. if (strpos($_k, '-')) {
  390. list($_k1, $_k2) = explode('-', $_k);
  391. if (is_array($_k2)) {
  392. return false;
  393. }
  394. $_param[$_k1][$_k2] = $_v;
  395. } else {
  396. $_param[$_k] = $_v;
  397. }
  398. }
  399. }
  400. if (empty($_param)) {
  401. return false;
  402. }
  403. return $_param;
  404. }
  405. /**
  406. * @return bool|string
  407. */
  408. protected function getKey() {
  409. switch ($this->device_type) {
  410. case DeviceTypeConst::DEVICE_TYPE_IOSSDK:
  411. case DeviceTypeConst::DEVICE_TYPE_ANDSDK:
  412. case DeviceTypeConst::DEVICE_TYPE_IOSAPP:
  413. case DeviceTypeConst::DEVICE_TYPE_IOSH5APP:
  414. case DeviceTypeConst::DEVICE_TYPE_ANDAPP:
  415. case DeviceTypeConst::DEVICE_TYPE_ANDH5APP:
  416. $_key = $this->getAppKey();
  417. break;
  418. case DeviceTypeConst::DEVICE_TYPE_IOSAPPLESDK:
  419. $_key = $this->getAppKey(true);
  420. break;
  421. default:
  422. $_key = $this->token;
  423. }
  424. return $_key;
  425. }
  426. protected function getAppKey($is_iosapplesdk = false) {
  427. $_gl_class = new GameLogic();
  428. $_app_id = get_val($this->rq_data, 'app_id');
  429. if (empty($_app_id) && false == $is_iosapplesdk) {
  430. return false;
  431. }
  432. $_client_id = get_val($this->rq_data, 'client_id');
  433. if (empty($_client_id) && false == $is_iosapplesdk) {
  434. return false;
  435. }
  436. $_client_key = $_gl_class->getVersionKey($_app_id, $_client_id);
  437. if (empty($_client_key) && false == $is_iosapplesdk) {
  438. return false;
  439. }
  440. $_public_key_file = GLOBAL_CONF_PATH.'extra/key/rsa_public_key.pem';
  441. if (!file_exists($_public_key_file)) {
  442. return false;
  443. } else {
  444. $_key_content = file_get_contents($_public_key_file);
  445. }
  446. // 以下为了初始化公钥,保证公钥不管是带格式还是不带格式都可以通过验证。
  447. $_key_content = str_replace("-----BEGIN PUBLIC KEY-----", "", $_key_content);
  448. $_key_content = str_replace("-----END PUBLIC KEY-----", "", $_key_content);
  449. $_key_content = str_replace("\r\n", "", $_key_content);
  450. $_key_content = str_replace("\n", "", $_key_content);
  451. // Log::error('------pubic_key-----'.$_key_content);
  452. if (empty($_key_content)) {
  453. return false;
  454. }
  455. if (true == $is_iosapplesdk) {
  456. return $_key_content;
  457. }
  458. return $_client_key.'&'.$_key_content;
  459. }
  460. /**
  461. * 校验签名
  462. */
  463. protected function checkSign() {
  464. $_ignore_sign = [ //忽略签名的接口数组
  465. 'v8/app/getPluginList'
  466. ];
  467. $_path = $this->request->path();
  468. if (in_array($_path, $_ignore_sign)) {
  469. return true;
  470. }
  471. if (empty($this->device_type) || FormatConst::FORMAT_HTML == $this->response_type) {
  472. return true;
  473. }
  474. $_haV2 = new HuoApiV2();
  475. //获取client_key
  476. $_key = $this->getKey();
  477. $_haV2->setKey($_key);
  478. $_rs = $_haV2->check($_path, $this->rq_data, $this->request->method());
  479. if (true != $_rs) {
  480. $this->error(OrderStatus::getMsg(OrderStatus::SIGN_ERROR), '', OrderStatus::SIGN_ERROR);
  481. }
  482. }
  483. /**
  484. * 校验请求事件
  485. */
  486. protected function checkTime() {
  487. $_ts = get_val($this->rq_data, 'ts', 0);
  488. if (abs($_ts - time()) < 5) {
  489. $this->error('time is error');
  490. }
  491. }
  492. /**
  493. * 设置玩家入参
  494. *
  495. * @param bool $is_reg
  496. *
  497. * @return Mem
  498. */
  499. public function setMemData($is_reg = false) {
  500. $_mem = new Mem();
  501. $_mem->setData(get_val($this->rq_data, 'mem'));
  502. $_app_id = get_val($this->rq_data, 'app_id', 0);
  503. //$_mg_mem_id = (new HuoSession($this->mem_id, $_app_id))->getMgMemId();
  504. $_mg_mem_id = (new MemberOut())->getMgMemId($_app_id, $this->mem_id);
  505. if (false == $is_reg) {
  506. $_mem_id = $this->mem_id;
  507. if (!empty($_mem_id)) {
  508. $_mem->setMemId($_mem_id);
  509. $_mem->setMgMemId($_mg_mem_id);
  510. $_mem_data = MemCache::ins()->getInfoById($_mem_id);
  511. $_mem->setAgentId($_mem_data['agent_id']);
  512. }
  513. }
  514. return $_mem;
  515. }
  516. /**
  517. * @return Order
  518. */
  519. public function setOrderData() {
  520. $_order = new Order();
  521. $_order->setData(get_val($this->rq_data, 'order', []));
  522. return $_order;
  523. }
  524. /**
  525. * @return Role
  526. */
  527. public function setRoleData() {
  528. $_role = new Role();
  529. $_role->setData(get_val($this->rq_data, 'role', []));
  530. return $_role;
  531. }
  532. /**
  533. * @return Crash
  534. */
  535. public function setCrashData() {
  536. $_crash = new Crash();
  537. $_crash->setData(get_val($this->rq_data, 'crash', []));
  538. return $_crash;
  539. }
  540. /**
  541. * @return Device
  542. */
  543. public function setDeviceData() {
  544. $_device = new Device();
  545. $_device->setData(get_val($this->rq_data, 'device', []));
  546. $_device->setDeviceType($this->device_type);
  547. $_device->setIp($this->request->ip());
  548. if (isset($this->rq_data['open_cnt'])) {
  549. $_device->setOpenCnt($this->rq_data['open_cnt']);
  550. // Session::set('open_cnt', $this->rq_data['open_cnt'], 'device');
  551. } else {
  552. // $_open_cnt = Session::get('open_cnt', 'device');
  553. if (empty($_open_cnt)) {
  554. $_open_cnt = 0;
  555. }
  556. $_device->setOpenCnt($_open_cnt);
  557. }
  558. $_device->setFromDevice($this->device_type);
  559. switch ($this->device_type) {
  560. case DeviceTypeConst::DEVICE_TYPE_IOSSDK:
  561. case DeviceTypeConst::DEVICE_TYPE_IOSAPP:
  562. case DeviceTypeConst::DEVICE_TYPE_IOSH5APP:
  563. $_device->setFrom(GameConst::GAME_IOS);
  564. break;
  565. case DeviceTypeConst::DEVICE_TYPE_IOSAPPLESDK:
  566. $_device->setFrom(GameConst::GAME_IOS_SWITCH);
  567. break;
  568. case DeviceTypeConst::DEVICE_TYPE_ANDSDK:
  569. case DeviceTypeConst::DEVICE_TYPE_ANDAPP:
  570. case DeviceTypeConst::DEVICE_TYPE_ANDH5APP:
  571. $_device->setFrom(GameConst::GAME_ANDROID);
  572. break;
  573. case DeviceTypeConst::DEVICE_TYPE_SAFARI:
  574. case DeviceTypeConst::DEVICE_TYPE_ANDBROWSER:
  575. case DeviceTypeConst::DEVICE_TYPE_WEIXIN:
  576. case DeviceTypeConst::DEVICE_TYPE_PC:
  577. case DeviceTypeConst::DEVICE_TYPE_WAP:
  578. $_device->setFrom(GameConst::GAME_H5);
  579. break;
  580. default:
  581. $_device->setFrom(GameConst::GAME_MP);
  582. }
  583. return $_device;
  584. }
  585. /**
  586. * @return Game
  587. */
  588. public function setGameData() {
  589. $_game = new Game();
  590. $_game->setData(get_val($this->rq_data, 'game', []));
  591. switch ($this->device_type) {
  592. case DeviceTypeConst::DEVICE_TYPE_IOSAPPLESDK:
  593. $_game->setAppleId(get_val($this->rq_data, 'apple_id', 0));
  594. $_app_id = (new GameModel())->getAppIdByAppleId($_game->getAppleId());
  595. if (empty($_app_id)) {
  596. $this->error('AppleId 错误');
  597. }
  598. $_game->setHAppId($_app_id);
  599. $this->rq_data['app_id'] = $_app_id;
  600. break;
  601. case DeviceTypeConst::DEVICE_TYPE_IOSSDK:
  602. break;
  603. case DeviceTypeConst::DEVICE_TYPE_IOSAPP:
  604. case DeviceTypeConst::DEVICE_TYPE_IOSH5APP:
  605. case DeviceTypeConst::DEVICE_TYPE_SAFARI:
  606. default:
  607. $_game->setHAppId(get_val($this->rq_data, 'app_id', 0));
  608. }
  609. if ($_game->getHAppId() !== 0) {
  610. $_game_data = (new GameCache())->getInfoByAppId($_game->getHAppId());
  611. if (empty($_game_data)) {
  612. $this->error('游戏参数错误');
  613. }
  614. }
  615. return $_game;
  616. }
  617. /**
  618. * @return Channel
  619. *
  620. */
  621. public function setChannelData() {
  622. $_channel = new Channel();
  623. $_channel->setData(get_val($this->rq_data, 'agent', []));
  624. $_device_data = get_val($this->rq_data, 'device', []);
  625. $_device_id = get_val($_device_data, 'device_id', '');
  626. /* 计算AgentId */
  627. $_agent_id = Commonfunc::getAgentId(
  628. 0,
  629. $_channel->getAgentGame(),
  630. $_channel->getAgentId(),
  631. $_device_id
  632. );
  633. $_channel->setAgentId($_agent_id);
  634. return $_channel;
  635. }
  636. /**
  637. * @return Event
  638. */
  639. public function setEventData() {
  640. $_event = new Event();
  641. $_event->setData(get_val($this->rq_data, 'event', []));
  642. return $_event;
  643. }
  644. public function _initializeView() {
  645. $cmfThemePath = config('cmf_theme_path');
  646. $cmfDefaultTheme = cmf_get_current_theme();
  647. $themePath = "{$cmfThemePath}{$cmfDefaultTheme}";
  648. $root = cmf_get_root();
  649. //使cdn设置生效
  650. $cdnSettings = cmf_get_option('cdn_settings');
  651. if (empty($cdnSettings['cdn_static_root'])) {
  652. $viewReplaceStr = [
  653. '__ROOT__' => $root,
  654. '__TMPL__' => "{$root}/{$themePath}",
  655. '__STATIC__' => "{$root}/static",
  656. '__WEB_ROOT__' => $root
  657. ];
  658. } else {
  659. $cdnStaticRoot = rtrim($cdnSettings['cdn_static_root'], '/');
  660. $viewReplaceStr = [
  661. '__ROOT__' => $root,
  662. '__TMPL__' => "{$cdnStaticRoot}/{$themePath}",
  663. '__STATIC__' => "{$cdnStaticRoot}/static",
  664. '__WEB_ROOT__' => $cdnStaticRoot
  665. ];
  666. }
  667. $viewReplaceStr = array_merge(config('view_replace_str'), $viewReplaceStr);
  668. config('template.view_base', "{$themePath}/");
  669. config('view_replace_str', $viewReplaceStr);
  670. $themeErrorTmpl = "{$themePath}/error.html";
  671. if (file_exists_case($themeErrorTmpl)) {
  672. config('dispatch_error_tmpl', $themeErrorTmpl);
  673. }
  674. $themeSuccessTmpl = "{$themePath}/success.html";
  675. if (file_exists_case($themeSuccessTmpl)) {
  676. config('dispatch_success_tmpl', $themeSuccessTmpl);
  677. }
  678. }
  679. /**
  680. * 加载模板输出
  681. *
  682. * @access protected
  683. *
  684. * @param string $template 模板文件名
  685. * @param array $vars 模板输出变量
  686. * @param array $replace 模板替换
  687. * @param array $config 模板参数
  688. *
  689. * @return mixed
  690. */
  691. protected function fetch($template = '', $vars = [], $replace = [], $config = []) {
  692. $template = $this->parseTemplate($template);
  693. $more = $this->getThemeFileMore($template);
  694. $this->assign('theme_vars', $more['vars']);
  695. $this->assign('theme_widgets', $more['widgets']);
  696. return parent::fetch($template, $vars, $replace, $config);
  697. }
  698. /**
  699. * 自动定位模板文件
  700. *
  701. * @access private
  702. *
  703. * @param string $template 模板文件规则
  704. *
  705. * @return string
  706. */
  707. private function parseTemplate($template) {
  708. // 分析模板文件规则
  709. $request = $this->request;
  710. // 获取视图根目录
  711. if (strpos($template, '@')) {
  712. // 跨模块调用
  713. list($module, $template) = explode('@', $template);
  714. }
  715. $viewBase = config('template.view_base');
  716. if ($viewBase) {
  717. // 基础视图目录
  718. $module = isset($module) ? $module : $request->module();
  719. $path = $viewBase.($module ? $module.DS : '');
  720. } else {
  721. $path = isset($module) ? APP_PATH.$module.DS.'view'.DS : config('template.view_path');
  722. }
  723. $depr = config('template.view_depr');
  724. if (0 !== strpos($template, '/')) {
  725. $template = str_replace(['/', ':'], $depr, $template);
  726. $controller = cmf_parse_name($request->controller());
  727. if ($controller) {
  728. if ('' == $template) {
  729. // 如果模板文件名为空 按照默认规则定位
  730. $template = str_replace('.', DS, $controller).$depr.$request->action();
  731. } elseif (false === strpos($template, $depr)) {
  732. $template = str_replace('.', DS, $controller).$depr.$template;
  733. }
  734. }
  735. } else {
  736. $template = str_replace(['/', ':'], $depr, substr($template, 1));
  737. }
  738. return $path.ltrim($template, '/').'.'.ltrim(config('template.view_suffix'), '.');
  739. }
  740. /**
  741. * 获取模板文件变量
  742. *
  743. * @param string $file
  744. * @param string $theme
  745. *
  746. * @return array
  747. */
  748. private function getThemeFileMore($file, $theme = "") {
  749. //TODO 增加缓存
  750. $theme = empty($theme) ? cmf_get_current_theme() : $theme;
  751. $themePath = config('cmf_theme_path');
  752. $file = str_replace('\\', '/', $file);
  753. $file = str_replace('//', '/', $file);
  754. $file = str_replace(['.html', '.php', $themePath.$theme."/"], '', $file);
  755. $files = Db::name('theme_file')->field('more')->where(['theme' => $theme])->where(
  756. function ($query) use ($file) {
  757. $query->where(['is_public' => 1])->whereOr(['file' => $file]);
  758. }
  759. )->select();
  760. $vars = [];
  761. $widgets = [];
  762. foreach ($files as $file) {
  763. $oldMore = json_decode($file['more'], true);
  764. if (!empty($oldMore['vars'])) {
  765. foreach ($oldMore['vars'] as $varName => $var) {
  766. $vars[$varName] = $var['value'];
  767. }
  768. }
  769. if (!empty($oldMore['widgets'])) {
  770. foreach ($oldMore['widgets'] as $widgetName => $widget) {
  771. $widgetVars = [];
  772. if (!empty($widget['vars'])) {
  773. foreach ($widget['vars'] as $varName => $var) {
  774. $widgetVars[$varName] = $var['value'];
  775. }
  776. }
  777. $widget['vars'] = $widgetVars;
  778. $widgets[$widgetName] = $widget;
  779. }
  780. }
  781. }
  782. return ['vars' => $vars, 'widgets' => $widgets];
  783. }
  784. /**
  785. * 检查是否登陆
  786. *
  787. * @param int $mem_id
  788. */
  789. public function checkLogin($mem_id = 0) {
  790. $_mem_id = $mem_id;
  791. if (empty($_mem_id)) {
  792. $_mem_id = $this->mem_id;
  793. }
  794. if (empty($_mem_id)) {
  795. $_code = MemberStatus::LOGIN_IS_OUT;
  796. $this->error(lang(MemberStatus::getMsg($_code)), [], $_code);
  797. }
  798. }
  799. }