| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793 | <?php/** * V2BaseController.php UTF-8 * V2版本基类 * * @date    : 2018/1/15 21:35 * * @license 这不是一个自由软件,未经授权不许任何使用和传播。 * @author  : wuyonghong <wyh@huosdk.com> * @version : HUOSDK 8.0 */namespace box\common\controller;use huo\controller\common\CommonFunc;use huo\controller\common\HuoCookie;use huo\controller\common\HuoSession;use huo\controller\member\Member;use huo\controller\member\MemCache;use huo\controller\request\Channel;use huo\controller\request\Crash;use huo\controller\request\Device;use huo\controller\request\Event;use huo\controller\request\Game;use huo\controller\request\Mem;use huo\controller\request\Order;use huo\controller\request\Role;use huo\logic\game\GameLogic;use huoCheck\HuoApiV2;use huolib\constant\CommonConst;use huolib\constant\DeviceTypeConst;use huolib\constant\FormatConst;use huolib\constant\FromConst;use huolib\status\CommonStatus;use huolib\tool\StrUtils;use think\Config;use think\Controller;use think\Db;use think\exception\HttpResponseException;use think\exception\ValidateException;use think\Loader;use think\Response;class V2BaseController extends Controller {    //token    protected $token = '';    //设备类型    protected $device_type = '';    //用户 id    protected $mem_id = 0;    // 语言    protected $lang = 'en';    //用户    protected $user;    /* 返回类型 */    protected $response_type = 'html';    //用户类型    protected $user_type;    protected $allowed_device_types = ['mobile', 'android', 'iphone', 'ipad', 'web', 'pc', 'mac', 'wxapp'];    /**     * @var \think\Request Request实例     */    protected $request;    protected $agent_site; /* 渠道专属链接 */    // 验证失败是否抛出异常    protected $fail_exception = false;    // 是否批量验证    protected $batch_validate = false;    protected $rq_data        = [];    protected $sess_config                              = [            'id'     => '',            'prefix' => '',            'type'   => '',            'expire' => CommonConst::CONST_DAY_SECONDS        ];    /**     * 前置操作方法列表     *     * @var array $before_action_list     * @access protected     */    protected $before_action_list = [];    // 初始化    private function _initLang() {        $_lang = $this->request->header('HS-Lang/s', 'en-us');        $this->lang = $_lang;        config('default_lang', $this->lang);    }    /**     * 获取设备类型     *     * @return string     */    public function getDeviceType() {        if ($this->request->isWeixin()) {            return DeviceTypeConst::DEVICE_TYPE_WEIXIN;        }        if ($this->request->isMobile()) {            return DeviceTypeConst::DEVICE_TYPE_WAP;        }        return DeviceTypeConst::DEVICE_TYPE_PC;    }    /**     *     */    private function _initUser() {        $_token = HuoCookie::getMemToken();        if (empty($_token)) {            $_token = $this->request->param('token/s', '');        }        $_game_data = get_val($this->rq_data, 'game', []);        $_device_type = get_val($_game_data, 'mp_id');        $_wx_param['wx_app_id'] = $this->request->param('wx_app_id/s', '');        if (!empty($_wx_param['wx_app_id'])) {            $this->device_type = $_wx_param['wx_app_id'];        } elseif (!empty($_device_type)) {            $this->device_type = $_device_type;        } else {            $this->device_type = DeviceTypeConst::DEVICE_TYPE_MP;        }        if ($this->request->isWeixin()) {            $this->device_type = DeviceTypeConst::DEVICE_TYPE_WEIXIN;        }        $_mem_id = $this->getMemIdByToken($_token, $this->device_type);        if (!empty($_mem_id)) {            $this->mem_id = $_mem_id;        }        if (APP_DEBUG) {            /* 调试环境直接登陆 */            $_mem_id = $this->request->param('debug_mem_id/s', 0);            if (!empty($_mem_id)) {                $this->mem_id = $_mem_id;            }        }        if (empty($this->mem_id)) {            $_wx_param['url'] = $this->request->domain().$this->request->url();            if ($this->request->isWeixin()) {                /* 微信内 判断是否登陆 没有登录 调用微信登陆 */                $_wx_param['type'] = FromConst::FROM_WEIXIN;                //$_wx_login_url = MPBOXSITE.'/box/oauth/index?'.StrUtils::createLinkString($_wx_param);                $_wx_login_url = H5ISITE.'/api/oauth/index?'.StrUtils::createLinkString($_wx_param);                $this->redirect($_wx_login_url);            }        }    }    protected function _initialize() {        $this->response_type = $this->request->param('format/s', FormatConst::FORMAT_HTML);        $_token = $this->request->param('token');        if (!empty($_token)) {            $this->token = $_token;            Config::set('session.id', $this->token);        }        Config::set('default_return_type', $this->response_type);        $this->_initLang();        $this->checkParam();        // 用户验证初始化        $this->_initUser();        if ($this->request->isOptions()) {            $this->success();        }    }    /**     * 前置操作     *     * @access protected     *     * @param string $method  前置操作方法名     * @param array  $options 调用参数 ['only'=>[...]] 或者['except'=>[...]]     */    protected function beforeAction($method, $options = []) {        if (isset($options['only'])) {            if (is_string($options['only'])) {                $options['only'] = explode(',', $options['only']);            }            if (!in_array($this->request->action(), $options['only'])) {                return;            }        } elseif (isset($options['except'])) {            if (is_string($options['except'])) {                $options['except'] = explode(',', $options['except']);            }            if (in_array($this->request->action(), $options['except'])) {                return;            }        }        call_user_func([$this, $method]);    }    /**     * @param $token     * @param $device_type     *     * @return array|bool|false|\PDOStatement|string|\think\Model     */    public function getMemIdByToken($token, $device_type) {        if (empty($token)) {            return 0;        }        $_path = 'mp/wx/login';        $_is_up = $_path == request()->path() ? true : false;        $_mem_id = (new Member())->getMemIdByToken($token, $device_type, $_is_up);        if (empty($_mem_id)) {            return 0;        }        return $_mem_id;    }    /**     * 返回数据     *     * @param array $data     */    protected function returnData($data = []) {        $_msg = $data['msg'];        $_code = $data['code'];        $_data = $data['data'];        if (CommonStatus::NO_ERROR != $_code) {            $this->error($_msg, $_data, $_code);        }        $this->success($_msg, $_data, $_code);    }    /**     * 操作错误跳转的快捷方法     *     * @access protected     *     * @param mixed $msg    提示信息,若要指定错误码,可以传数组,格式为['code'=>您的错误码,'msg'=>'您的错误消息']     * @param mixed $data   返回的数据     * @param int   $code     *     * @param array $header 发送的Header信息     *     * @param null  $url     * @param int   $wait     *     * @return void     */    protected function error($msg = '', $data = '', $code = 400, array $header = [], $url = null, $wait = 3) {        $type = $this->getResponseType();        if ('html' == $type) {            parent::error($msg, $data, $code, $header, $url, $wait);        }        if (empty($data)) {            $data = null;        }        $result = [            'code' => $code,            'msg'  => $msg,            'data' => $data,        ];        $header['Access-Control-Allow-Origin'] = '*';        $header['Access-Control-Allow-Headers'] = 'X-Requested-With,Content-Type,HS-Device-Type,HS-Token,HS-Lang';        $header['Access-Control-Allow-Methods'] = 'GET,POST,PATCH,PUT,DELETE,OPTIONS';        $response = Response::create($result, $type)->header($header);        throw new HttpResponseException($response);    }    /**     * 获取当前的response 输出类型     *     * @access protected     * @return string     */    protected function getResponseType() {        return $this->response_type;    }    /**     * 获取当前登录用户的id     *     * @return int     */    public function getMemId() {        if (empty($this->mem_id)) {            $this->error(lang('NO_LOGIN'), '', 1002);        }//        $this->mem_id = rand(1, 10);        return $this->mem_id;    }    /**     * 设置验证失败后是否抛出异常     *     * @access protected     *     * @param bool $fail 是否抛出异常     *     * @return $this     */    protected function validateFailException($fail = true) {        $this->fail_exception = $fail;        return $this;    }    /**     * 验证数据     *     * @access protected     *     * @param array        $data     数据     * @param string|array $validate 验证器名或者验证规则数组     * @param array        $message  提示信息     * @param bool         $batch    是否批量验证     * @param mixed        $callback 回调方法(闭包)     *     * @return array|string|true     * @throws ValidateException     */    protected function validate($data, $validate, $message = [], $batch = false, $callback = null) {        if (is_array($validate)) {            $_valid_class = Loader::validate();            $_valid_class->rule($validate);        } else {            if (strpos($validate, '.')) {                // 支持场景                list($validate, $scene) = explode('.', $validate);            }            $_valid_class = Loader::validate($validate);            if (!empty($scene)) {                $_valid_class->scene($scene);            }        }        // 是否批量验证        if ($batch || $this->batch_validate) {            $_valid_class->batch(true);        }        if (is_array($message)) {            $_valid_class->message($message);        }        if ($callback && is_callable($callback)) {            call_user_func_array($callback, [$_valid_class, &$data]);        }        if (!$_valid_class->check($data)) {            if ($this->fail_exception) {                throw new ValidateException($_valid_class->getError());            } else {                return $_valid_class->getError();            }        } else {            return true;        }    }    /**     * 操作成功跳转的快捷方法     *     * @access protected     *     * @param mixed $msg    提示信息     * @param mixed $data   返回的数据     * @param array $header 发送的Header信息     *     * @param int   $code   返回码     *     * @return void     */    protected function success($msg = '', $data = '', $code = 200, array $header = [], $url = null, $wait = 3) {        $type = $this->getResponseType();        if ('html' == $type) {            parent::success($msg, $data, $code, $header, $url, $wait);        }        if (empty($data)) {            $data = null;        }        $result = [            'code' => $code,            'msg'  => $msg,            'data' => $data,        ];        $header['Access-Control-Allow-Origin'] = '*';        $header['Access-Control-Allow-Headers'] = 'X-Requested-With,Content-Type,HS-Device-Type,HS-Token,HS-Lang';        $header['Access-Control-Allow-Methods'] = 'GET,POST,PATCH,PUT,DELETE,OPTIONS';        $response = Response::create($result, $type)->header($header);        throw new HttpResponseException($response);    }    protected function checkParam() {        $_is_json = false;        $_params = $_REQUEST;        $this->rq_data = $this->getParam($_params, $_is_json);        if (empty($this->rq_data)) {            $this->rq_data = [];        }//        $this->checkSign();        $this->checkTime();    }    /**     * 获取请求参数     *     * @param mixed $param     * @param bool  $is_json     *     * @return bool|mixed|string     */    public function getParam($param, $is_json = false) {        if (empty($param)) {            return '';        }        if ($is_json) {            $_param = json_decode($param, true);            if (JSON_ERROR_NONE != json_last_error()) {                return false;            }        } else {            foreach ($param as $_k => $_v) {                if (strpos($_k, '-')) {                    list($_k1, $_k2) = explode('-', $_k);                    if (is_array($_k2)) {                        return false;                    }                    $_param[$_k1][$_k2] = $_v;                } else {                    $_param[$_k] = $_v;                }            }        }        if (empty($_param)) {            return false;        }        return $_param;    }    /**     * @return bool|string     */    protected function getKey() {        $_key = $this->token;        if (in_array($this->device_type, ['android', 'iphone', 'ipad'])) {            $_key = $this->getAppKey();        }        return $_key;    }    protected function getAppKey() {        $_gl_class = new GameLogic();        $_app_id = get_val($this->rq_data, 'app_id');        if (empty($this->rq_data['game'])) {            return false;        }        $_client_id = get_val($this->rq_data['game'], 'h_ver');        if (empty($_client_id)) {            return false;        }        $_client_key = $_gl_class->getVersionKey($_app_id, $_client_id);        if (empty($_client_key)) {            return false;        }        $_public_key_file = GLOBAL_CONF_PATH.'extra/key/rsa_public_key.pem';        if (!file_exists($_public_key_file)) {            return false;        } else {            $_key_content = file_get_contents($_public_key_file);        }        // 以下为了初始化公钥,保证公钥不管是带格式还是不带格式都可以通过验证。        $_key_content = str_replace("-----BEGIN PUBLIC KEY-----", "", $_key_content);        $_key_content = str_replace("-----END PUBLIC KEY-----", "", $_key_content);        $_key_content = str_replace("\r\n", "", $_key_content);        $_key_content = str_replace("\n", "", $_key_content);        if (empty($_key_content)) {            return false;        }        return $_client_key.'&'.$_key_content;    }    /**     * 校验签名     */    protected function checkSign() {        if (empty($this->device_type) || FormatConst::FORMAT_HTML == $this->response_type) {            return true;        }        $_haV2 = new HuoApiV2();        //获取client_key        $_key = $this->getKey();        $_haV2->setKey($_key);        $_rs = $_haV2->check('api/'.$this->request->path(), $this->rq_data, $this->request->method());        if (true != $_rs) {//            $this->error(OrderStatus::getMsg(OrderStatus::SIGN_ERROR), '', OrderStatus::SIGN_ERROR);        }    }    /**     * 校验请求事件     */    protected function checkTime() {        $_ts = get_val($this->rq_data, 'ts', 0);        if (abs($_ts - time()) < 5) {            $this->error('time is error');        }    }    /**     * 设置玩家入参     *     * @param bool $is_reg     *     * @return Mem     */    public function setMemData($is_reg = false) {        $_mem = new Mem();        $_mem->setData(get_val($this->rq_data, 'mem'));        $_app_id = get_val($this->rq_data, 'app_id', 0);        $_mg_mem_id = (new HuoSession($this->mem_id, $_app_id))->getMgMemId($_app_id);        if (false == $is_reg) {            $_mem_id = $this->mem_id;            if (!empty($_mem_id)) {                $_mem->setMemId($_mem_id);                $_mem->setMgMemId($_mg_mem_id);                $_mem_data = MemCache::ins()->getInfoById($_mem_id);                $_mem->setAgentId($_mem_data['agent_id']);            }        }        return $_mem;    }    /**     * @return Order     */    public function setOrderData() {        $_order = new Order();        $_order->setData(get_val($this->rq_data, 'order', []));        return $_order;    }    /**     * @return Role     */    public function setRoleData() {        $_role = new Role();        $_role->setData(get_val($this->rq_data, 'role', []));        return $_role;    }    /**     * @return Crash     */    public function setCrashData() {        $_crash = new Crash();        $_crash->setData(get_val($this->rq_data, 'crash', []));        return $_crash;    }    /**     * @return Device     */    public function setDeviceData() {        $_device = new Device();        $_device->setData(get_val($this->rq_data, 'device', []));        $_device->setDeviceType($this->device_type);        $_device->setIp($this->request->ip());        if (isset($this->rq_data['open_cnt'])) {            $_device->setOpenCnt($this->rq_data['open_cnt']);//            Session::set('open_cnt', $this->rq_data['open_cnt'], 'device');        } else {//            $_open_cnt = Session::get('open_cnt', 'device');            if (empty($_open_cnt)) {                $_open_cnt = 0;            }            $_device->setOpenCnt($_open_cnt);        }        $_device->setFromDevice($this->device_type);        if (in_array($this->device_type, ['ipad', 'iphone'])) {            $_device->setFrom(4);        } else if ($this->device_type == 'android') {            $_device->setFrom(3);        }        return $_device;    }    /**     * @return Game     */    public function setGameData() {        $_game = new Game();        $_game->setData(get_val($this->rq_data, 'game', []));        $_game->setHAppId(get_val($this->rq_data, 'app_id', 0));        return $_game;    }    /**     * @return Channel     *     */    public function setChannelData() {        $_channel = new Channel();        $_channel->setData(get_val($this->rq_data, 'agent', []));        $_device_data = get_val($this->rq_data, 'device', []);        $_device_id = get_val($_device_data, 'device_id', '');        /* 计算AgentId */        $_agent_id = Commonfunc::getAgentId(            0,            $_channel->getAgentGame(),            $_channel->getAgentId(),            $_device_id        );        $_channel->setAgentId($_agent_id);        return $_channel;    }    /**     * @return Event     */    public function setEventData() {        $_event = new Event();        $_event->setData(get_val($this->rq_data, 'event', []));        return $_event;    }    public function _initializeView() {        $cmfThemePath = config('cmf_theme_path');        $cmfDefaultTheme = cmf_get_current_theme();        $themePath = "{$cmfThemePath}{$cmfDefaultTheme}";        $root = cmf_get_root();        //使cdn设置生效        $cdnSettings = cmf_get_option('cdn_settings');        if (empty($cdnSettings['cdn_static_root'])) {            $viewReplaceStr = [                '__ROOT__'     => $root,                '__TMPL__'     => "{$root}/{$themePath}",                '__STATIC__'   => "{$root}/static",                '__WEB_ROOT__' => $root            ];        } else {            $cdnStaticRoot = rtrim($cdnSettings['cdn_static_root'], '/');            $viewReplaceStr = [                '__ROOT__'     => $root,                '__TMPL__'     => "{$cdnStaticRoot}/{$themePath}",                '__STATIC__'   => "{$cdnStaticRoot}/static",                '__WEB_ROOT__' => $cdnStaticRoot            ];        }        $viewReplaceStr = array_merge(config('view_replace_str'), $viewReplaceStr);        config('template.view_base', "{$themePath}/");        config('view_replace_str', $viewReplaceStr);        $themeErrorTmpl = "{$themePath}/error.html";        if (file_exists_case($themeErrorTmpl)) {            config('dispatch_error_tmpl', $themeErrorTmpl);        }        $themeSuccessTmpl = "{$themePath}/success.html";        if (file_exists_case($themeSuccessTmpl)) {            config('dispatch_success_tmpl', $themeSuccessTmpl);        }    }    /**     * 加载模板输出     *     * @access protected     *     * @param string $template 模板文件名     * @param array  $vars     模板输出变量     * @param array  $replace  模板替换     * @param array  $config   模板参数     *     * @return mixed     */    protected function fetch($template = '', $vars = [], $replace = [], $config = []) {        $template = $this->parseTemplate($template);        $more = $this->getThemeFileMore($template);        $this->assign('theme_vars', $more['vars']);        $this->assign('theme_widgets', $more['widgets']);        return parent::fetch($template, $vars, $replace, $config);    }    /**     * 自动定位模板文件     *     * @access private     *     * @param string $template 模板文件规则     *     * @return string     */    private function parseTemplate($template) {        // 分析模板文件规则        $request = $this->request;        // 获取视图根目录        if (strpos($template, '@')) {            // 跨模块调用            list($module, $template) = explode('@', $template);        }        $viewBase = config('template.view_base');        if ($viewBase) {            // 基础视图目录            $module = isset($module) ? $module : $request->module();            $path = $viewBase.($module ? $module.DS : '');        } else {            $path = isset($module) ? APP_PATH.$module.DS.'view'.DS : config('template.view_path');        }        $depr = config('template.view_depr');        if (0 !== strpos($template, '/')) {            $template = str_replace(['/', ':'], $depr, $template);            $controller = cmf_parse_name($request->controller());            if ($controller) {                if ('' == $template) {                    // 如果模板文件名为空 按照默认规则定位                    $template = str_replace('.', DS, $controller).$depr.$request->action();                } elseif (false === strpos($template, $depr)) {                    $template = str_replace('.', DS, $controller).$depr.$template;                }            }        } else {            $template = str_replace(['/', ':'], $depr, substr($template, 1));        }        return $path.ltrim($template, '/').'.'.ltrim(config('template.view_suffix'), '.');    }    /**     * 获取模板文件变量     *     * @param string $file     * @param string $theme     *     * @return array     */    private function getThemeFileMore($file, $theme = "") {        //TODO 增加缓存        $theme = empty($theme) ? cmf_get_current_theme() : $theme;        $themePath = config('cmf_theme_path');        $file = str_replace('\\', '/', $file);        $file = str_replace('//', '/', $file);        $file = str_replace(['.html', '.php', $themePath.$theme."/"], '', $file);        $files = Db::name('theme_file')->field('more')->where(['theme' => $theme])->where(            function ($query) use ($file) {                $query->where(['is_public' => 1])->whereOr(['file' => $file]);            }        )->select();        $vars = [];        $widgets = [];        foreach ($files as $file) {            $oldMore = json_decode($file['more'], true);            if (!empty($oldMore['vars'])) {                foreach ($oldMore['vars'] as $varName => $var) {                    $vars[$varName] = $var['value'];                }            }            if (!empty($oldMore['widgets'])) {                foreach ($oldMore['widgets'] as $widgetName => $widget) {                    $widgetVars = [];                    if (!empty($widget['vars'])) {                        foreach ($widget['vars'] as $varName => $var) {                            $widgetVars[$varName] = $var['value'];                        }                    }                    $widget['vars'] = $widgetVars;                    $widgets[$widgetName] = $widget;                }            }        }        return ['vars' => $vars, 'widgets' => $widgets];    }    /**     * 检查是否登陆     *     * @param int $mem_id     */    public function checkLogin($mem_id = 0) {        $_mem_id = $mem_id;        if (empty($_mem_id)) {            $_mem_id = $this->mem_id;        }        if (empty($_mem_id)) {            $this->error('未登录');        }    }}
 |