| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439 |
- <?php
- /**
- * 聚合渠道登录控制器
- */
- namespace app\api\controller\v1;
- use app\api\controller\Api;
- use app\common\library\RsaSign;
- use app\common\model\ComplexLoginlog;
- use app\common\model\ComplexChannelModel;
- use app\common\model\ComplexMembers;
- use app\common\logic\Complex;
- use app\common\library\JwtToken;
- use think\Db;
- use think\Cache;
- use think\Exception;
- use think\Config;
- use app\common\model\PolychannelGame;
- use think\Env;
- use think\Request;
- class ComplexLogin extends Api
- {
- protected $noNeedLogin = ['index'];
- // ## TODO:每次新渠道,当前两个必须要添加
- // 需要进行登录验证的渠道标识
- protected $_neekCheckChannel = ['mw', 'tss', 'wanxiong', 'haofan', 'haipai', 'jiuqu', 'haofanceshi', 'onesixnn', 'ailequ', 'jiuquxin', 'jiandao', 'fiveseven', 'xingmai', 'haiquyou', 'naozhewan', 'lizi', 'zhaosy', 'yehua', 'shenqi', 'aiyou', 'qilin', 'yiyou', 'jule', 'yueyou', 'xinyou', 'simo', 'weilian', 'sanjiu', 'ledao', 'ledaoios', 'dangle', 'youxiyou', 'jlyx', 'tlyx', 'jcyx', 'test', 'kuaishou', 'pili', 'juheng', 'quchen', 'twothreethree', 'rrtv', 'simoh5', 'gyln', 'youchen', 'congyu', 'bhy', 'kshy', 'yinhu', 'peiqi', 'jywan', 'jywanh5'];
- // H5渠道游戏使用渠道逻辑处理
- protected $h5_handle_channel = ['zhaosy'];
- // 扩展参数
- protected $_extparam = [];
- public function _initialize()
- {
- parent::_initialize();
- }
-
- // 渠道效验
- public function getSpecialParam()
- {
- $prefix = strtolower($this->input('channel_mark')); // 渠道标识
- $gameid = strtolower($this->input('gameid')); // 游戏id
-
- $channelModel = new ComplexChannelModel;
- if (!($channel_id = $channelModel->where(['status' => 1, 'mark' => $prefix])->value('id'))) {
- $this->jsonResult('', -201, '渠道信息不存在');
- }
- if (!$polyChannelGame = (new PolychannelGame())->alias('cpg')->join('cy_game cg', 'cpg.game_id=cg.id')->field('cpg.*, cg.type as game_type')->where(['cpg.channel_id' => $channel_id, 'cpg.game_id' => $gameid])->find()) {
- $this->jsonResult('', -202, '渠道游戏不存在.');
- }
- // 判断是否有做登录验证的渠道
- if (in_array($prefix, $this->_neekCheckChannel)) {
- try {
- $sentence = ucfirst($prefix);
- $className = 'app\api\complex\\' . $sentence;
- $model = new $className;
- // H5 渠道游戏,单独处理
- if(in_array($prefix, $this->h5_handle_channel) && $polyChannelGame['game_type'] == 3){
- $result = $model->getSpecialParamH5($this->input, $polyChannelGame);
- }else{
- $result = $model->getSpecialParam($this->input, $polyChannelGame);
- }
- if ($result) {
- // 渠道效验判断,针对部分渠道的后台配置qmKey需要
- if (!empty($polyChannelGame['param']) && $this->input('device') == '2') {
- if ($paramArr = json_decode($polyChannelGame['param'], true)) {
- $qmKey = $this->input('qmKey'); // 游戏id
- if (isset($paramArr['qmKey'])) {
- if ($paramArr['qmKey'] != $qmKey || empty($qmKey)) {
- curlDD("渠道 " . $sentence . '@用户账号: ' . $result . ' 破解Android加固!', Env::get('dingtalk.warning_url'));
- $this->jsonResult('', -221, '当前渠道不可用!');
- }
- }
- }
- }
- $this->jsonResult(['cuserid' => $result], 1, '获取成功');
- } else {
- $msg = "登陆失效或二次验证失败";
- // 优化提示判断
- if(!empty($result['code']) && $result['code'] < 0){
- $msg .= ", (c_err:{$result['code']})";
- }
- $this->jsonResult('', -222, $msg);
- }
- } catch (Exception $e) {
- log_message("渠道-" . $sentence . '-二次效验失败:' . $e->getCode() . ":" . $e->getMessage() . '; ' . $e->getFile() . ':' . $e->getLine(), 'error', LOG_PATH . "complexLoginlog/{$prefix}/");
- curlDD("渠道-" . $sentence . '-二次效验失败:'. $e->getCode() . ":" . $e->getMessage() . '; ' . $e->getFile() . ':' . $e->getLine(), Env::get('dingtalk.notic_url'));
- $this->jsonResult('', -233, '二次登录验证失败');
- }
- } else {
- $this->jsonResult('', 0, '渠道未开启效验');
- }
-
- }
- // 登录
- public function index()
- {
- $channelModel = new ComplexChannelModel;
- $complexMembersModel = new ComplexMembers;
- $complexLogic = new Complex;
- $prefix = strtolower($this->input('channel_mark')); // 渠道标识
- $complex_username = trim($this->input('username')); // 聚合用户名
- $imeil = $this->input('imeil'); // 手机imeil码
- $device = $this->input('device'); // 注册设备来源,1为PC,2为安卓,3为苹果
- $gameid = $this->input('gameid'); // 游戏ID
- // $channelToken = $this->input('channelToken');
- $userId = $this->input('user_id', ''); // 渠道效验接口 返回的ID
- if (!($channel_id = $channelModel->where(['status' => 1, 'mark' => $prefix])->value('id'))) {
- $this->jsonResult('', -120, '渠道信息不存在');
- }
- if (!$polyChannelGame = (new PolychannelGame())->alias('cpg')->join('cy_game cg', 'cpg.game_id=cg.id')->field('cpg.*, cg.type as game_type')->where(['cpg.channel_id' => $channel_id, 'cpg.game_id' => $gameid])->find()) {
- $this->jsonResult('', -121, '渠道游戏不存在.');
- }
- //游戏ID不能为空
- if (empty($gameid)) {
- $this->jsonResult('', -122, '游戏ID不能为空');
- }
- //游戏ID不能为空
- if (empty($device)) {
- $this->jsonResult('', -123, '设备类型不能为空');
- }
- // ## IOS 加固效验
- if (!empty($polyChannelGame['param']) && $this->input('device') == '3' && !empty($this->input('qmversion'))) {
- $param = json_decode($polyChannelGame['param'], true);
- if (!empty($param['jg_key'])) {
- $jg_key = $this->input('jg_key'); //IOS 加固参数
- if (empty($jg_key)) {
- $this->jsonResult('{}', 126, '当前渠道不可用!');
- }
- $username = $this->input('username'); // username
- $rsa_res = (new RsaSign())->openssl_private_decrypt($jg_key);
- $ios_sign_key = $param['jg_key'] . $userId;
- if ($ios_sign_key !== $rsa_res) {
- curlDD("渠道 " . $prefix . '@聚合账户: ' . $username . ' 破解IOS加固!', Env::get('dingtalk.warning_url'));
- $this->jsonResult('{}', 126, '当前渠道不可用!');
- }
- }
- }
- // ## 渠道登录效验
- $result = [];
- if (in_array($prefix, $this->_neekCheckChannel)) {
- // $paramArr = [
- // 'username' => trim($this->input('username')) ,
- // 'imeil' => $this->input('imeil') ,
- // 'device' => $this->input('device') ,
- // 'gameid' => $this->input('gameid') ,
- // 'channel_mark' => strtolower($this->input('channel_mark')) ,
- // 'channelToken' => $this->input('channelToken') ,
- // ];
- try {
- $sentence = ucfirst($prefix);
- $className = 'app\api\complex\\' . $sentence;
- $model = new $className;
- // H5 渠道游戏,单独处理
- if(in_array($prefix, $this->h5_handle_channel) && $polyChannelGame['game_type'] == 3){
- $result = $model->checkLoginH5($this->input, $polyChannelGame);
- }else{
- $result = $model->checkLogin($this->input, $polyChannelGame);
- }
- // 默认判断
- if (!$result) {
- $this->jsonResult('', -131, "登录验证失败");
- }
- // 优化提示判断
- if(!empty($result['code']) && $result['code'] < 0){
- $msg = "登录验证失败, (c_err:{$result['code']})";
- $this->jsonResult('', -132, $msg);
- }
- // 检查是否有 setParam 方法
- if (method_exists($model, 'setParam')) {
- $this->_extparam = $model->setParam($this->input);
- }
- } catch (Exception $e) {
- log_message("渠道-" . $sentence . '-登陆效验失败:' . $e->getCode() . ":" . $e->getMessage() . '; ' . $e->getFile() . ':' . $e->getLine(), 'error', LOG_PATH . "complexLoginlog/{$prefix}/");
- curlDD("渠道-" . $sentence . '-登陆效验失败-渠道登录回调:msg=' . $e->getMessage() .' - input:'. json_encode($this->input), Env::get('dingtalk.notic_url'));
- $this->jsonResult('', -130, '登录验证异常.');
- }
- // $className = 'app\api\controller\complex\\' . $sentence.'Login';
- // $model_c = new $className;
- // $model_c->setParam($paramArr);
- // $resArr = $model_c->indexcheck();
- // log_message('xmw--get_http_response()--7-END--'.json_encode($resArr),'log',LOG_PATH . 'complexLoginlog/');
- // // 判断是否验证成功
- // if (!$resArr['code']){
- // $this->jsonResult('',0,$resArr['msg']);
- // }
- // $this->_extparam = $resArr['extparam'];
- // // 参数重置
- // log_message('xmw--get_http_response()--7.5-END--'.count($resArr['data']),'log',LOG_PATH . 'complexLoginlog/');
- // if (count($resArr['data'])){
- // log_message('xmw--get_http_response()--8-END--'.count($resArr['data']),'log',LOG_PATH . 'complexLoginlog/');
- // foreach ($resArr['data'] as $k=>$v){
- // log_message('xmw--get_http_response()--9-END--'.$k.'----'.$v,'log',LOG_PATH . 'complexLoginlog/');
- // $this->setInput($k,$v);
- // }
- // unset($v);
- // }
- }
- if (empty($complex_username)) {
- $this->jsonResult('', -140, '用户名不能为空');
- }
- if (empty($imeil)) {
- $this->jsonResult('', -141, '设备imeil异常');
- }
- if (empty($prefix)) {
- $this->jsonResult('', -142, '渠道标识不能为空');
- }
- if ($complexLogic->isFrozen($channel_id, $gameid, 'login')) {
- //根据预付款进行登录冻结判断还未加
- $this->jsonResult('', -143, '您所在渠道已经被禁止登录此游戏');
- } elseif (in_array($prefix, Config::get('complex_disable_login')['channel_mark']) && in_array($gameid, Config::get('complex_disable_login')['game_id'])) {
- //特殊的渠道和游戏禁止登录
- $this->jsonResult('', -144, '您所在渠道已经被禁止登录此游戏');
- }
- // 启动事务
- Db::startTrans();
- try {
- //nw_complex_members表中用户信息
- $userinfo = $complexMembersModel->where(['complex_username' => $complex_username, 'channel_id' => $channel_id, 'gameid' => $gameid])->find();
- //用户信息已存在,登录
- if (!empty($userinfo)) {
- $loginInfo = $this->loginProcess($userinfo, $gameid, $imeil, $device, $channel_id);
- $memberSaveData = ['login_time' => NOW_TIMESTAMP];
- if ($userId) {
- $memberSaveData['complex_id'] = $userId;
- }
- if (!empty($this->_extparam)) {
- $memberSaveData['extparam'] = json_encode($this->_extparam);
- }
- //更新最后登录时间
- $complexMembersModel->update($memberSaveData, ['id' => $userinfo['id']]);
- $mg_username = $userinfo['mg_username']; // 我方用户名
-
- } //用户信息不存在,注册
- else {
- //根据预付款进行注册冻结判断还未加
- if ($complexLogic->isFrozen($channel_id, $gameid, 'register')) {
- throw new Exception("您所在渠道已经被禁止注册此游戏");
- }
- $memberData = [
- 'complex_username' => $complex_username,
- 'device' => $device,
- 'gameid' => $gameid,
- 'imei' => $imeil,
- 'channel_id' => $channel_id,
- 'reg_time' => NOW_TIMESTAMP,
- 'login_time' => NOW_TIMESTAMP,
- 'ip' => request()->ip()
- ];
- if ($userId) {
- $memberData['complex_id'] = $userId;
- }
- if (!empty($this->_extparam)) {
- $memberData['extparam'] = json_encode($this->_extparam);
- }
- $userinfo = $complexMembersModel->create($memberData);
- // ## 游戏支持双端互通
- $pre_uid = $userinfo['id'];
- if(!empty($result['user_id'])){
- $pre_uid = $result['user_id'];
- }
- $mg_username = $prefix . '___' . $pre_uid . 'z'; // 我方用户名
- $complexMembersModel->update(['mg_username' => $mg_username], ['id' => $userinfo['id']]);
- $memberData['id'] = $userinfo['id'];
- $memberData['mg_username'] = $mg_username;
-
- $loginInfo = $this->loginProcess($memberData, $gameid, $imeil, $device, $channel_id);
- }
- $sign_str = "username={$mg_username}&appkey=" . $this->appInfo['appkey'] . "&logintime=" . NOW_TIMESTAMP;
- $sign = md5($sign_str); //这个暂时好像没什么用,只是参考旧SDK的
- // 提交事务
- Db::commit();
- } catch (\Exception $e) {
- // 回滚事务
- Db::rollback();
- $this->jsonResult('', -110, '登录失败! ' . $e->getMessage());
- }
- $result = [
- 'user_id' => (string)$userinfo['id'],
- 'username' => $mg_username,
- 'token' => $loginInfo['token'],
- 'logintime' => NOW_TIMESTAMP,
- 'sign' => $sign,
- 'extparam' => $this->_extparam
- ];
- if (isset($loginInfo['jwt_token'])) {
- $result['jwt_token'] = $loginInfo['jwt_token'];
- }
- $this->jsonResult($result, 1, '登录成功');
- exit;
- }
- /**
- * 用户登录公共部分处理
- *
- * @param $userinfo : array 用户信息数组
- * @param $gameid : int 游戏ID
- * @param $imeil : string 手机imei码
- * @param $device : int 注册设备来源
- * @param $channelId : int 当前登录的渠道ID
- *
- * @return $token: string 用户登录token
- */
- private function loginProcess($userinfo, $gameid, $imeil, $device, $channelId)
- {
- $loginlogModel = new ComplexLoginlog();
- $logData['userid'] = $userinfo['id'];
- $logData['gameid'] = $gameid;
- $logData['imei'] = $imeil;
- $logData['channel_id'] = $channelId;
- $logData['login_time'] = NOW_TIMESTAMP;
- $logData['ip'] = request()->ip();
- $loginlogModel->insert($logData);
- //token的随机码
- $token_random = random(8);
- $loginFailureTime = 60 * 60 * 24 * 30;
- // 登录态 token 为登录标识
- $token = auth_code($userinfo['id'] . '|' . $userinfo['mg_username'] . '|' . $gameid . '|' . $userinfo['mg_username'] . '|' . $token_random . '|cm', "ENCODE", Env::get('auth_key'));
- // $imeil 做为唯一登录标识
- Cache::store('default')->set($token, $imeil, $loginFailureTime);
- //redis中玩家登录安全控制的随机码
- Cache::store('default')->set('token|cm|' . $userinfo['id'] . '|' . $gameid, $token_random, $loginFailureTime);
- $returnData = ['token' => $token];
- // ## JWT:仅版本号大于 v3.6.8 的客户端返回 ##
- if (!empty($this->version) && version_compare($this->version, '3.6.8', '>')) {
- $jwtKey = trim((string) Env::get('jwt.jwt_key', ''));
- $jwtExpTime = (int) $loginFailureTime;
- $returnData['jwt_token'] = '';
- if ($jwtKey === '' || $jwtExpTime <= 0) {
- trace('JWT配置缺失或错误,请检查jwt.jwt_key', 'error');
- } else {
- $jwtIssuedAt = time();
- $jwtUserData = [
- 'member_id' => $userinfo['id'],
- 'mg_username' => $userinfo['mg_username'],
- 'game_id' => $gameid,
- 'complex_id' => $channelId,
- 'iat' => $jwtIssuedAt,
- 'exp' => $jwtIssuedAt + $jwtExpTime,
- ];
- $returnData['jwt_token'] = JwtToken::encode($jwtUserData, $jwtKey);
- }
- }
- return $returnData;
- }
- /**
- * 获取游戏配置参数(有些游戏有多个参数时需要特殊处理)
- * @param $game_id 游戏id
- * @param $channel_mark 渠道标识
- * @param string $data 返回的数据
- * @param string $code 返回的code
- * @param string $msg 返回的msg
- * @return mixed
- */
- // public function getGameParam($game_id,$channel_mark,$data='',$code='0',$msg='该游戏的验签参数还未设置'){
- // $polyChannelGameModel = new PolychannelGame;
- // $param = $polyChannelGameModel->alias('a')
- // ->join('nw_channel b','b.id = a.channel_id')
- // ->where(['a.game_id'=>$game_id,'b.mark'=>$channel_mark])
- // ->value('a.param');
- //
- // if(empty($param)){
- // log_message('后台渠道游戏中,用于该游戏的验签参数还未设置,game_id='.$game_id.',渠道标识='.$channel_mark,'error',LOG_PATH . '../complexPaylog/');
- //
- // $this->jsonResult($data,$code,$msg);
- // }
- //
- // $param = unserialize($param);
- // return $param;
- // }
- /**
- * 获取游戏指定的用户名连接符
- *
- * @param int $gameid 游戏ID
- * @return string
- */
- // public function get_username_connector($gameid) {
- // $specify = ['116','173','201'];
- //
- // if ( in_array($gameid, $specify) ) {
- // return '#';
- // } else {
- // return '___';
- // }
- // }
- }
|