* @version : HUOSDK 8.0 */ namespace huo\controller\member; use huo\controller\request\Channel; use huo\controller\request\Device; use huo\controller\request\Game; use huo\controller\request\Mem; use huo\model\member\MemoauthModel; use huolib\constant\FromConst; use huolib\constant\MemConst; use huolib\constant\OauthConst; use huolib\oauth\OAuth as OAuthLib; use huolib\status\MemberStatus; use huolib\tool\StrUtils; use huomp\controller\game\GameMini; use huomp\model\weixin\MpConfModel; use think\Db; use think\Exception; use think\Log; class Oauth extends Member { protected $domain = MPAPISITE; protected $oauth_data = [ 'openid' => '',/* openid */ 'unionid' => '',/* 用户ID */ 'channel' => '',/* 通道 qq*/ 'nickname' => '', /* 昵称 */ 'gender' => '3',/* 性别 */ 'avatar' => ''/* 头像 */ ]; /** * 获取配置文件 */ public function getOauthConf() { $_data_wx = [ 'type' => 2, 'app_id' => '', 'app_secret' => '', 'redirect_url' => '' ]; $_rdata[] = $_data_wx; return $_rdata; } /** * @param string $type 第三方登陆类型 * @param string $from * * @param string $url 需要跳转回的地址 * * @param string $wx_app_id * * @return mixed */ public function getRequestCodeUrl($type, $from = 'pc', $url = '', $wx_app_id = '') { $_check_type = $this->checkType($type); if (MemberStatus::NO_ERROR != $_check_type) { return $this->retErrMsg($_check_type); } try { $_type = $type; if (FromConst::FROM_WEIXIN != $from && OauthConst::OAUTH_WEIXIN == $type) { $_type = OauthConst::OAUTH_WXQRCODE; } $_config = []; $_wx_app_secret = (new MpConfModel())->getSecretByMpId($wx_app_id); if (!empty($_wx_app_secret)) { $_config['APP_KEY'] = $wx_app_id; $_config['APP_SECRET'] = $_wx_app_secret; $_config['CALLBACK'] = ''; } $_oauth_class = OAuthLib::ins($_type, $_config); $_back_url = $this->getCallbackUrl($type); if (!empty($wx_app_id)) { $_back_url .= '/'.$wx_app_id; } $_callback = StrUtils::getUrl($_back_url); $_callback .= 'back_url='.urlencode($url).'&token='.session_id(); $_oauth_class->setCallback($_callback); $_oauth_class->setState(); $_url = $_oauth_class->getRequestCodeUrl($from); $_rdata['url'] = $_url; return $this->retSucMsg(MemberStatus::NO_ERROR, $_rdata); } catch (Exception $_e) { $_err_msg = 'func='.__FUNCTION__.'&class='.__CLASS__.'&type='.$type .'&from='.$from.'&url'.$url.'&wx_app_id='.$wx_app_id.'&Exception' .$_e->getMessage(); Log::write($_err_msg, Log::ERROR); return $this->retErrMsg(MemberStatus::UNKNOWN_ERROR); } } /** * @param $type * * @return bool */ public function checkType($type) { switch ($type) { case OauthConst::OAUTH_QQ: case OauthConst::OAUTH_WEIBO: case OauthConst::OAUTH_WEIXIN: return MemberStatus::NO_ERROR; default: return MemberStatus::OAUTH_TYPE_ERROR; } } /** * @param $type * * @return string */ public function getCallbackUrl($type) { switch ($type) { case OauthConst::OAUTH_QQ: $_cb_url = url('sdk/Oauth/callbackQq', '', false, $this->domain); break; case OauthConst::OAUTH_WEIBO: $_cb_url = url('sdk/Oauth/callbackWeibo', '', false, $this->domain); break; case OauthConst::OAUTH_WEIXIN: $_cb_url = url('sdk/Oauth/callbackWeixin', '', false, $this->domain); break; default: $_cb_url = url('sdk/Oauth/callbackWeixin', '', false, $this->domain); } return $_cb_url; } /** * 通过code获取登陆信息 * * @param $type * @param $code * @param $from * @param Game $game_rq * @param Channel $channel * @param Device $device * @param Mem $member * * @param array $_conf * * @return array|mixed */ public function oauthLoginByCode( $type, $code, $from, Game $game_rq, Channel $channel, Device $device, Mem $member, $_conf = [] ) { $_oauth_data = $this->getOauthDataByCode($type, $code, $from, $game_rq->getHAppId(), $_conf); if (is_numeric($_oauth_data)) { $_mem_id = $_oauth_data; $_mo_model = new MemoauthModel(); $_mo_data = $_mo_model->getInfoByOpenId($type, $this->oauth_data['openid']); if (empty($_mo_data)) { $this->addOauth($_mem_id, $type, $this->oauth_data, $game_rq->getHAppId(), $_conf); } /* 登陆成功 */ $_mem_data = MemCache::ins()->getInfoById($_mem_id); $_mem_data['guided_agent_id'] = $channel->getAgentId(); $_rdata = $this->getReturnData($_mem_data, $game_rq->getHAppId(), $device->getDeviceType()); $this->insertLoginLog($game_rq, $channel, $device, $member, $_rdata); return $this->retSucMsg(MemberStatus::NO_ERROR, $_rdata); } elseif (is_array($_oauth_data)) { /* 用户信息 查询openid是否对应玩家ID */ $_mo_model = new MemoauthModel(); $_mo_data = $_mo_model->getInfoByOpenId($type, $_oauth_data['openid']); $_mem_id = isset($_mo_data['mem_id']) ? $_mo_data['mem_id'] : 0; if (empty($_mo_data['id']) && empty($_mem_id)) { /* 玩家注册 */ $_mem_data = $this->oAuthReg($type, $_oauth_data, $game_rq, $channel, $device, $member, $_conf); $member->setIsReg(MemConst::MEM_IS_REG); $_mem_data['is_reg'] = MemConst::MEM_IS_REG; /* LTV统计 */ $_ltv_class = new \ltv\Ltv(); $_ltv_class->reg($_mem_data['app_id'], $_mem_data['agent_id'], $_mem_data['create_time']); /* 生成支付小程序码 */ } elseif (empty($_mo_data['id']) && !empty($_mem_id)) { /* 登陆成功 */ $this->addOauth($_mem_id, $type, $_oauth_data, $game_rq->getHAppId(), $_conf); $_mem_data = MemCache::ins()->getInfoById($_mem_id); } else { /* 有第三方信息 未绑定玩家 */ $_mem_id = $this->memReg($type, $_oauth_data, $game_rq, $channel, $device, $member); $_mo_data['mem_id'] = $_mem_id; $_mo_model->updateOauth($type, $_oauth_data['openid'], $_mo_data); $_mem_data = MemCache::ins()->getInfoById($_mem_id); } $_mem_data['guided_agent_id'] = $channel->getAgentId(); $_rdata = $this->getReturnData($_mem_data, $game_rq->getHAppId(), $device->getDeviceType()); $this->insertLoginLog($game_rq, $channel, $device, $member, $_rdata); return $this->retSucMsg(MemberStatus::NO_ERROR, $_rdata); } $_err_msg = 'func='.__FUNCTION__.'&class='.__CLASS__.'&oauth_data=' .json_encode($_oauth_data).'&data='.json_encode( array($type, $code, $from, $game_rq->getHAppId(), $_conf) ); Log::write($_err_msg, Log::ERROR); return $this->retErrMsg(MemberStatus::UNKNOWN_ERROR); } /** * @param string $type 登陆类型 * @param string $code * @param string $from * * @param int $app_id * * @param array $_conf * * @return array|bool|string array 表示用户所有信息 false 表示获取失败 string 为玩家ID */ public function getOauthDataByCode($type, $code, $from, $app_id = 0, $_conf = []) { //Log::error('$type$type$type'.json_encode($type)); try { if (OauthConst::OAUTH_MP == $type) { $_conf = (new GameMini())->getLoginConf($app_id); if (empty($_conf)) { return false; } } $_oauth_class = OAuthLib::ins($type, $_conf); $_oauth_class->setCallback($this->getCallbackUrl($type)); $_token = $_oauth_class->getAccessToken($code, $from); /* Session 设置 设置第三方登陆Session */ // (new HuoSession())->setOauthSession($_token); $_open_id = $_token['openid']; $_oauth_data = $_oauth_class->getUserInfo(); $this->oauth_data = $_oauth_data; //Log::error('$_oauth_data111'.json_encode($_oauth_data)); $_mo_model = new MemoauthModel(); $_mo_data = $_mo_model->getInfoByOpenId($type, $_open_id); if (!empty($_mo_data['id'])) { // 老玩家 $_mem_id = $_mo_data['mem_id']; /* 更新信息 */ if (($_mo_data['unionid'] == $_mo_data['openid'] && $_oauth_data['unionid'] != $_oauth_data['openid']) || 0 == $_mem_id) { $_mem_id = $this->getMemIdByUnionId($type, $_oauth_data['unionid']); /* 插入更多信息 */ $_mo_data['unionid'] = $_oauth_data['unionid']; $_mo_data['nickname'] = $_oauth_data['nickname']; $_mo_data['gender'] = $_oauth_data['gender']; $_mo_data['avatar'] = $_oauth_data['avatar']; $_mo_data['status'] = MemConst::STATUS_NORMAL; $_mo_data['expires_in'] = $_token['expires_in']; $_mo_data['mem_id'] = $_mem_id; $_mo_data['last_login_ip'] = get_client_ip(0, true); $_mem_data['avatar'] = $_mo_data['avatar']; $_mem_data['nickname'] = $_mo_data['nickname']; $_mem_data['status'] = MemConst::STATUS_NORMAL; MemCache::ins()->updateMem($_mem_id, $_mem_data); } $_mo_data['access_token'] = $_token['access_token']; $_mo_data['expires_in'] = $_token['expires_in']; $_mo_data['last_login_ip'] = get_client_ip(0, true); $_mo_data['last_login_time'] = time(); if(empty($_mo_data['conf_id'])){ if (!empty($app_id)) { $_mp_id = (new GameMini())->getMiniIdByAppId($app_id); $_mo_data['conf_id'] = (new MpConfModel())->getIdByMpId($_mp_id); } } $_mo_model->updateOauth($type, $_open_id, $_mo_data); if (empty($_mem_id)) { return $_oauth_data; } return $_mem_id; } return $_oauth_data; } catch (Exception $_e) { $_err_msg = 'func='.__FUNCTION__.'&class='.__CLASS__.'&Exception' .$_e->getMessage().'&code'.$_e->getCode(); Log::write($_err_msg, Log::ERROR); return false; } } /** * @param $type * @param $oauth_data * @param Game $game_rq * @param Channel $channel * @param Device $device * @param Mem $member * @param array $conf * * @return array|bool|mixed */ public function oAuthReg( $type, $oauth_data, Game $game_rq, Channel $channel, Device $device, Mem $member, $conf = [] ) { $_mem_id = $this->memReg($type, $oauth_data, $game_rq, $channel, $device, $member); $_rs = $this->addOauth($_mem_id, $type, $oauth_data, $game_rq->getHAppId(), $conf); if (false != $_rs) { return MemCache::ins()->getInfoById($_mem_id); } return false; } /** * 玩家主表注册 * * @param $type * @param $oauth_data * @param Game $game_rq * @param Channel $channel * @param Device $device * @param Mem $member * * @return string */ public function memReg($type, $oauth_data, Game $game_rq, Channel $channel, Device $device, Mem $member) { $_username = $this->genUsername($type); $_password = StrUtils::getRandChars(8); $member->setUsername($_username); $member->setPassword($_password); $member->setAvatar($oauth_data['avatar']); $member->setNickname($oauth_data['nickname']); /* Modified by ouzhongfu BEGIN 2020/4/9 ISSUES:11805 第三方注册设置为试玩账号,修改密码时不需输入原密码 */ /*if (empty($oauth_data['nickname'])) { $member->setStatus(MemConst::STATUS_TRY); }*/ $member->setStatus(MemConst::STATUS_TRY); /* END 2020/4/9 ISSUES:11805 */ $_mem_id = $this->getMemIdByUnionId($type, $oauth_data['unionid']); if (empty($_mem_id)) { $_mem_data = (new Register())->reg($game_rq, $channel, $device, $member); $_mem_id = $_mem_data['id']; } return $_mem_id; } private function addOauth($_mem_id, $type, $oauth_data, $app_id = 0, $conf = []) { $_data['openid'] = $oauth_data['openid']; $_data['from'] = $type; $_data['access_token'] = $oauth_data['token']['access_token']; $_data['unionid'] = $oauth_data['unionid']; $_data['nickname'] = $oauth_data['nickname']; $_data['country'] = !empty($oauth_data['country']) ? $oauth_data['country'] : ''; $_data['province'] = !empty($oauth_data['province']) ? $oauth_data['province'] : ''; $_data['city'] = !empty($oauth_data['city']) ? $oauth_data['city'] : ''; $_data['gender'] = $oauth_data['gender']; $_data['avatar'] = $oauth_data['avatar']; $_data['mem_id'] = $_mem_id; $_data['status'] = empty($oauth_data['nickname']) ? MemConst::STATUS_TRY : MemConst::STATUS_NORMAL; $_data['expires_in'] = $oauth_data['token']['expires_in']; if (!empty($app_id)) { $_mp_id = (new GameMini())->getMiniIdByAppId($app_id); $_data['conf_id'] = (new MpConfModel())->getIdByMpId($_mp_id); } if (OauthConst::OAUTH_WEIXIN == $type) { //微信 $_conf_id = get_val($conf, 'APP_KEY', ''); if (empty($_conf_id)) { $_conf_id = get_val($oauth_data, 'app_key', ''); } $_data['conf_id'] = (new MpConfModel())->getIdByMpId($_conf_id); } //扩展信息 $_more = [ 'refresh_token' => !empty($oauth_data['token']['refresh_token']) ? $oauth_data['token']['refresh_token'] : '', ]; $_data['more'] = json_encode($_more); $_rs = (new MemoauthModel())->addOauth($_data); if (false === $_rs) { return false; } return MemCache::ins()->saveOpenIdCache($type, $_data['openid'], $_mem_id); } /** * 通过OpenId 获取玩家ID * * * @param string $type * @param string $union_id * * @return string */ public function getMemIdByUnionId($type, $union_id) { $_mem_id = (new MemoauthModel())->getMemIdByUnionId($type, $union_id); return $_mem_id; } /** * 通过Token获取第三方信息 * * @param $type * @param $openid * @param $access_token * * @return bool */ public function getOauthDataByToken($type, $openid, $access_token) { try { $token['openid'] = $openid; $token['access_token'] = $access_token; $_oauth_class = OAuthLib::ins($type, [], $token); return $_oauth_class->getUserInfo(); } catch (Exception $_e) { $_err_msg = 'func='.__FUNCTION__.'&class='.__CLASS__.'&Exception' .$_e->getMessage().'&code'.$_e->getCode(); Log::write($_err_msg, Log::ERROR); return false; } } /** * @param string $domain */ public function setDomain($domain) { $this->domain = $domain; } /** * 通过code获取登陆信息 * * @param $type * @param $access_token * @param $openid * @param $from * @param Game $game_rq * @param Channel $channel * @param Device $device * @param Mem $member * * @param array $_conf * @param $oauth_app_key * * @return array|mixed */ public function oauthLoginByAccessToken( $type, $access_token, $openid, $from, Game $game_rq, Channel $channel, Device $device, Mem $member, $_conf = [], $oauth_app_key = '' ) { $_oauth_data = $this->getOauthDataByAccessToken( $type, $access_token, $openid, $from, $game_rq->getHAppId(), $_conf, $oauth_app_key ); if (is_numeric($_oauth_data)) { $_mem_id = $_oauth_data; /* 登陆成功 */ $_mem_data = MemCache::ins()->getInfoById($_mem_id); $_rdata = $this->getReturnData($_mem_data, $game_rq->getHAppId(), $device->getDeviceType()); $this->insertLoginLog($game_rq, $channel, $device, $member, $_rdata); return $this->retSucMsg(MemberStatus::NO_ERROR, $_rdata); } elseif (is_array($_oauth_data)) { /* 用户信息 查询openid是否对应玩家ID */ $_mo_model = new MemoauthModel(); $_mo_data = $_mo_model->getInfoByOpenId($type, $_oauth_data['openid']); $_mem_id = isset($_mo_data['mem_id']) ? $_mo_data['mem_id'] : 0; if (empty($_mo_data['id']) && empty($_mem_id)) { /* 玩家注册 */ $_mem_data = $this->oAuthReg($type, $_oauth_data, $game_rq, $channel, $device, $member, $_conf); $member->setIsReg(MemConst::MEM_IS_REG); $_mem_data['is_reg'] = MemConst::MEM_IS_REG; /* 生成支付小程序码 */ } elseif (empty($_mo_data['id']) && !empty($_mem_id)) { /* 登陆成功 */ $this->addOauth($_mem_id, $type, $_oauth_data, $game_rq->getHAppId(), $_conf); $_mem_data = MemCache::ins()->getInfoById($_mem_id); } else { /* 有第三方信息 未绑定玩家 */ $_mem_id = $this->memReg($type, $_oauth_data, $game_rq, $channel, $device, $member); $_mo_data['mem_id'] = $_mem_id; $_mo_model->updateOauth($type, $_oauth_data['openid'], $_mo_data); $_mem_data = MemCache::ins()->getInfoById($_mem_id); } $_rdata = $this->getReturnData($_mem_data, $game_rq->getHAppId(), $device->getDeviceType()); $this->insertLoginLog($game_rq, $channel, $device, $member, $_rdata); return $this->retSucMsg(MemberStatus::NO_ERROR, $_rdata); } $_err_msg = 'func='.__FUNCTION__.'&class='.__CLASS__.'&oauth_data=' .json_encode($_oauth_data).'&data='.json_encode( array($type, $access_token, $openid, $from, $game_rq->getHAppId(), $_conf) ); Log::write($_err_msg, Log::ERROR); return $this->retErrMsg(MemberStatus::UNKNOWN_ERROR); } /**通过accesstoken获取信息 * * @param $type * @param $access_token * @param $openid * @param $from * @param int $app_id * @param array $_conf * @param $oauth_app_key * * @return bool|string */ public function getOauthDataByAccessToken($type, $access_token, $openid, $from, $app_id = 0, $_conf = [], $oauth_app_key = '') { try { if (OauthConst::OAUTH_MP == $type) { $_conf = (new GameMini())->getLoginConf($app_id); if (empty($_conf)) { return false; } } $_token = [ 'access_token' => $access_token, 'openid' => $openid, 'oauth_app_key'=> $oauth_app_key, 'expires_in' => '7200' ]; $_oauth_class = OAuthLib::ins($type, $_conf, $_token); $_oauth_class->setCallback($this->getCallbackUrl($type)); /* Session 设置 设置第三方登陆Session */ $_open_id = $openid; $_oauth_data = $_oauth_class->getUserInfo(); $_mo_model = new MemoauthModel(); $_mo_data = $_mo_model->getInfoByOpenId($type, $_open_id); if (!empty($_mo_data['id'])) { $_mem_id = $_mo_data['mem_id']; /* 更新信息 */ if (($_mo_data['unionid'] == $_mo_data['openid'] && $_oauth_data['unionid'] != $_oauth_data['openid']) || 0 == $_mem_id) { $_mem_id = $this->getMemIdByUnionId($type, $_oauth_data['unionid']); /* 插入更多信息 */ $_mo_data['unionid'] = $_oauth_data['unionid']; $_mo_data['nickname'] = $_oauth_data['nickname']; $_mo_data['gender'] = $_oauth_data['gender']; $_mo_data['avatar'] = $_oauth_data['avatar']; $_mo_data['status'] = MemConst::STATUS_NORMAL; $_mo_data['expires_in'] = $_token['expires_in']; $_mo_data['mem_id'] = $_mem_id; $_mo_data['last_login_ip'] = get_client_ip(0, true); $_mem_data['avatar'] = $_mo_data['avatar']; $_mem_data['nickname'] = $_mo_data['nickname']; $_mem_data['status'] = MemConst::STATUS_NORMAL; MemCache::ins()->updateMem($_mem_id, $_mem_data); } $_mo_data['access_token'] = $_token['access_token']; $_mo_data['expires_in'] = $_token['expires_in']; $_mo_data['last_login_ip'] = get_client_ip(0, true); $_mo_data['last_login_time'] = time(); $_mo_model->updateOauth($type, $_open_id, $_mo_data); if (empty($_mem_id)) { return $_oauth_data; } return $_mem_id; } return $_oauth_data; } catch (Exception $_e) { $_err_msg = 'func='.__FUNCTION__.'&class='.__CLASS__.'&Exception' .$_e->getMessage().'&code'.$_e->getCode(); Log::write($_err_msg, Log::ERROR); return false; } } }