getRunTimeObject()->user = $user; } /** * @return UserCollect */ public function getUserCollectModel() { return model('UserCollect'); } /** * @return UserRecentlyRead */ public function getUserRecentlyReadModel() { return model('UserRecentlyRead'); } /** * @return Sign */ public function getSignModel() { return model('Sign'); } /** * 更新用户操作时间 * @param $userId * @param string $event */ public function updateUserOperateTime($userId, $event = MessageConstants::MESSAGE_EVENT_UNSUBSCRIBE) { $time = Request::instance()->server('REQUEST_TIME'); if ($userId) { $update = ['operate_time' => $time]; if ($event != MessageConstants::MESSAGE_EVENT_UNSUBSCRIBE) { $user = UserService::instance()->getUserModel()->getUserInfo($userId); if (!empty($user) && isset($user['is_subscribe']) && $user['is_subscribe'] == UserConstants::USER_IS_SUBSCRIBE_NO) { $update['is_subscribe'] = UserConstants::USER_IS_SUBSCRIBE_YES; $update['subscribe_time'] = $time; } } $where = ['id' => $userId]; UserService::instance()->update($update, $where); } } /** * 处理前台用户登录 * @return \app\main\model\object\ReturnObject */ public function frontUserLogin() { try{ $response = false; if (Ua::isWeiXin()) {// 微信内 //检测是否需要验证登录 && 检测是否登录 if (!UrlService::instance()->checkActionMatch(OpenPlatformConstants::WEXIN_NEED_LOGIN) && !$this->isLogin()) { //登录 $response = $this->login(); } } else { // 其他(浏览器) if (UrlService::instance()->checkActionMatch(OpenPlatformConstants::BROWSER_NEED_LOGIN) && !$this->isLogin()) { //登录 $response = $this->login(); } } if ($response instanceof ReturnObject) { if ($response->code == ErrorCodeConstants::SUCCESS) { if (UserService::instance()->getRunTimeObject()->urlType == UrlConstants::REFERRAL_GROUND_PAGE_SPREAD) { UrlService::instance()->setUserAgentId((int)Request::instance()->get('agent_id')); UrlService::instance()->setUserReferralId((int)Request::instance()->get('referral_id')); } $result = UrlService::instance()->unlimitSecondaryDomain(); if ($result->code != ErrorCodeConstants::SUCCESS) { return $result; } Log::info('用户已登录-> user_id:' . Cookie::get('user_id') . ' openid:' . Cookie::get('openid')); } return $response; } return $this->getReturn(); }catch (\Exception $e){ if ($e instanceof HttpException) { LogService::info('HttpException:' . $e->getMessage()); throw $e; } else { return $this->getExceptionReturn($e); } } } /** * 获取用户id * @param $channel_id * @param $open_id * @return ReturnObject */ public function getCallbackUserId($channel_id, $open_id) { $user_id = OfficialAccountsService::instance()->getOpenidModel()->getUserId($channel_id, $open_id); if ($user_id) { return $this->setData($user_id)->getReturn(); } $user_id = Redis::instanceAuto()->incr('UID'); return $this->setData($user_id)->getReturn(); } /** * @param $channel_id * @param $open_id * @return ReturnObject */ public function weChatInsertUser($channel_id, $open_id) { try { //获取基本信息 $user_id = OfficialAccountsService::instance()->getOpenidModel()->getUserId($channel_id, $open_id); $user_info = null; if ($user_id) { $user_info = $this->getUserModel()->setConnect($user_id)->getUserInfo($user_id); } $time = time(); //Redis 加锁 $redis = Redis::instanceCache(); $nxKey = 'L:' . $channel_id . ':' . $open_id; if (!$user_id || !$user_info) { if (!$nxRes = $redis->setnx($nxKey, 0)) { //已经存在 return $this->setMsg('已存在')->getReturn(); } $redis->expire($nxKey, 20); //20秒过期 } //用户ID不存在时创建用户ID if (!$user_id) { if (!$user_id = $this->createUserID($channel_id, $open_id, $time)) { $redis->del($nxKey); return $this->setMsg('创建用户失败')->getReturn(); } } //用户基本信息不存在时创建用户基本信息 if (!$user_info) { if (!$info_id = $this->createUserInfo($channel_id, $open_id, $user_id, $time)) { $redis->del($nxKey); return $this->setMsg('用户基本信息添加失败')->getReturn(); } //添加用户创建时间 WhiteList::addUserCreatePayTime($user_id); } $redis->del($nxKey); return $this->setData($user_id)->getReturn(); } catch (\Exception $e) { LogService::error('weChatInsertUser Error:' . $e->getMessage()); return $this->setMsg('用户创建异常')->setCode(ErrorCodeConstants::EXCEPTION)->getReturn(); } } /** * 创建用户基本信息 * @param int $channel_id 渠道ID * @param string $open_id 微信OPEN_ID * @param int $user_id 用户ID * @param string $time 创建时间 * @return null */ public function createUserInfo($channel_id,$open_id,$user_id,$time){ $weChatUser = []; try{ $weChat = OpenPlatformService::instance()->officialAccount; $client = new Client(Config::get('wechat.http')); $weChat->http_client = $client; $weChatUser = $weChat->user->get($open_id); if(!empty($weChatUser) && !isset($weChatUser['errcode'])) { //获取注册赠送看点 $ids = explode(',', Config::get('site.give_shubi_channel_id')); if (in_array($channel_id, $ids)) { $kandian_reg = 3000; } else { $kandian_reg = empty(Config::get('site.kandian_reg')) ? 0 : intval(Config::get('site.kandian_reg')); } $user = new UserObject(); $user->id = $user_id; $user->openid = $open_id; $user->nickname = $weChatUser['nickname'] ?? '书友'; $user->sex = $weChatUser['sex'] ?? 0; $user->first_cancel_pay = 2; $user->avatar = $weChatUser['headimgurl'] ?? cdnurl('/assets/img/frontend/icon/nav_icon_4.png'); $user->is_subscribe = $weChatUser['subscribe'] ?? 0; $user->subscribe_time = $weChatUser['subscribe_time'] ?? 0; $user->operate_time = $time; $user->channel_id = $channel_id; $user->country = $weChatUser['country'] ?? ''; $user->province = $weChatUser['province'] ?? ''; $user->city = $weChatUser['city'] ?? ''; $user->createtime = $time; $user->updatetime = $time; $user_info_id = $this->getUserModel()->setConnect($user->id)->insertGetId($user->toArray()); if($user_info_id){ //新增用户累计 $cid = AdminService::instance()->getAdminExtendModel()->getChannelId($channel_id); $cacheKey = CacheConstants::getNewUserCacheKey($cid); Redis::instance()->incr($cacheKey); Redis::instance()->expire($cacheKey, 86400); LogService::debug('用户累计增加'); //赠送用户免费看点 $this->addFreeKanDian($user_id,$kandian_reg,$time); //新增用户打点 $dotData = new DotObject(); $dotData->user_id = $user_info_id; $dotData->channel_id = $channel_id; $dotData->sex = $user->sex; $dotData->action_type = MqConstants::ROUTING_KEY_SUBSCRIBE; $dotData->type = MqConstants::MSG_TYPE_INCREASE; $dotData->event_time = Request::instance()->server('REQUEST_TIME'); MqService::instance()->sendMessage($dotData); //性别打点 if ($user->sex) { $oSexAna = new AnalysisObject(); $oSexAna->event_time = $dotData->event_time; $oSexAna->type = KafkaDotConstants::TYPE_SEX; $oSexAna->data['sex'] = $user->sex; $oSexAna->data['user_collect'] = 1; KafkaDotService::instance()->sendMsg($user_info_id, $oSexAna); } //新增打点 $oAna = new AnalysisObject(); $oAna->event_time = $dotData->event_time; $oAna->type = KafkaDotConstants::TYPE_NEW; $oAna->data['user_collect'] = 1; KafkaDotService::instance()->sendMsg($user_info_id, $oAna); BookService::instance()->insertShelfRecommendBooks($user_info_id, $user->sex,$channel_id); return $user_info_id; } LogService::error('创建用户基本信息失败,USER表写入失败 Data:' . $user->toJson()); } }catch (\Exception $e){ LogService::notice('创建用户基本信息失败,Error:' . $e->getMessage()); } finally { LogService::notice(json_encode($weChatUser, JSON_UNESCAPED_UNICODE)); } return null; } /** * 伪造用户信息 (手机号注册时伪造openID创造用户) * @param int $channel_id 渠道ID * @param string $open_id 微信OPEN_ID * @param string $time 创建时间 * @return null */ public function fakeUserInfo($channel_id, $open_id, $phone, $time, $business_line = '0') { $redisAuto = Redis::instanceAuto(); $user_id = $redisAuto->incr('UID'); //redis自增返回新的user_id try { //获取注册赠送看点 $kandian_reg = empty(Config::get('site.phone_bind_credit')) ? 0 : intval(Config::get('site.phone_bind_credit')); $user = new UserObject(); $user->id = $user_id; $user->openid = $open_id; $user->nickname = '书友'; $user->sex = 0; $user->mobile = $phone; $user->first_cancel_pay = 2; $user->avatar = cdnurl('/assets/img/frontend/icon/nav_icon_4.png'); $user->is_subscribe = 0; $user->subscribe_time = 0; $user->operate_time = $time; $user->channel_id = $channel_id; $user->country = ''; $user->province = ''; $user->city = ''; $user->createtime = $time; $user->updatetime = $time; $user->business_line = PayConstants::BUSINESS_APP; if ($user_info_id = $this->getUserModel()->setConnect($user->id)->insertGetId($user->toArray())) { //赠送用户免费看点 $this->addFreeKanDian($user_id, $kandian_reg, $time, 'APP手机注册赠送书币', $business_line); //新增用户打点 $dotData = new DotObject(); $dotData->user_id = $user_info_id; $dotData->channel_id = $channel_id; $dotData->sex = $user->sex; $dotData->action_type = MqConstants::ROUTING_KEY_SUBSCRIBE; $dotData->type = MqConstants::MSG_TYPE_INCREASE; $dotData->event_time = Request::instance()->server('REQUEST_TIME'); MqService::instance()->sendMessage($dotData); return $user_info_id; } Log::error('创建用户基本信息失败,USER表写入失败 Data:' . $user->toJson()); } catch (\Exception $e) { Log::error('创建用户基本信息失败,Error:' . $e->getMessage()); } return null; } /** * 添加用户免费看点 * @param int $user_id 用户ID * @param int $kandian_reg 注册赠送看点 * @param int $time 添加时间 * @param string $notes 备注 */ public function addFreeKanDian($user_id,$kandian_reg,$time, $notes = '新用户注册赠送', $business_line = '0'){ try{ if (!$kandian_reg) { return; } //赠送用户免费书币 $endTime = intval(Config::get('site.kandian_free_day')) * 86400; $rdata = []; $rdata['free_kandian'] = $kandian_reg; $rdata['remain_free_kandian'] = $kandian_reg; $rdata['type'] = 3; $rdata['user_id'] = $user_id; $rdata['free_endtime'] = $endTime + $time; $rdata['business_line'] = $business_line; $rdata['notes'] = $notes; $rdata['createtime'] = $time; $rdata['updatetime'] = $time; FinancialService::instance()->getRechargeModel()->setConnect($user_id)->insertGetId($rdata); //存入redis Redis::instance()->del('ZR:' . $user_id); }catch (\Exception $e){ Log::error("添加注册用户免费看点记录失败,Error:".$e->getMessage()); } } /** * 创建用户ID * @param int $channel_id 渠道ID * @param string $open_id 微信OPEN_ID * @param string $time 创建时间 * @return int|null */ public function createUserID($channel_id, $open_id, $time) { try { if (ApiService::instance()->checkApiOn()) { return \app\source\service\UserService::instance()->createUser($channel_id, $open_id)->id; } else { $redisAuto = Redis::instanceAuto(); //redis自增返回新的user_id $userId = $redisAuto->incr('UID'); $data = ['channel_openid' => $channel_id . '_' . $open_id, 'user_id' => $userId, 'createtime' => $time, 'updatetime' => $time]; if ($autoId = OfficialAccountsService::instance()->getOpenidModel()->setConnect($channel_id, $open_id)->insertGetId($data)) { return $userId; } } Log::error('创建用户ID失败,OPENID表写入失败 Data:' . json_encode($data)); } catch (\Exception $e) { Log::error('创建用户ID失败,Error:' . $e->getMessage()); } return null; } /** * 微信登录 * @return bool|RedirectResponse * @throws \Exception * @throws \think\Exception * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\ModelNotFoundException * @throws \think\exception\DbException */ public function login() { $urlType = $this->getRunTimeObject()->urlType; switch ($urlType) { case OpenPlatformConstants::URL_TYPE_ADMIN: // 后台首页 break; case OpenPlatformConstants::URL_TYPE_PAY: // 充值页 return $this->loginPay(); break; case OpenPlatformConstants::URL_TYPE_SPREAD: // 推广页 return $this->loginAgent(); break; } return false; } /** * 充值页 登录 * @return ReturnObject|bool * @throws \Exception */ private function loginPay() { if (Ua::isWeiXin()) { $officialAccount = OpenPlatformService::instance()->getOfficialAccount(); if (Request::instance()->has('code')) { // 具有code,直接获取openid try { if (Request::instance()->has('tqwv')) { $startTime = floatval(Request::instance()->param('tqwv')); $endTime = microtime(true); $this->useTime = $this->useTime + ($endTime - $startTime); Log::info(sprintf('WeChat->LoginPay->Auth->Time StartTime:%f EndTime:%f RunTime:%f', $startTime, $endTime, $endTime - $startTime)); } $getOpenIDSTime = microtime(true); $user = $officialAccount->oauth->user(); $getOpenIDETime = microtime(true); Cookie::forever('app_id', Config::get('wechat.app_id')); Cookie::forever('openid', $user->getId()); Cookie::forever('open_id', $user->getId()); $this->useTime = $this->useTime + ($getOpenIDETime - $getOpenIDSTime); Log::info(sprintf('WeChat->LoginPay->OpenID->Time OpenID:%s StartTime:%f EndTime:%f RunTime:', $user->getId(), $getOpenIDSTime, $getOpenIDETime, $getOpenIDETime - $getOpenIDSTime)); } catch (\Exception $e) { return $this->loginFail($officialAccount, $e, 'tqwv'); } } else { $startTime = microtime(true); $url = get_url_no_port(true); if (stripos($url, '?') === false) { $url .= '?tqwv=' . $startTime; } else { $url .= '&tqwv=' . $startTime; } $url = del_url_params($url, 'code'); $response = $officialAccount->oauth->scopes(['snsapi_base'])->redirect($url); //获取code return $this->setCode(ErrorCodeConstants::REDIRECT)->setData($response->getTargetUrl())->getReturn(); } } else { $redirect = '/index/login/login?redirect=' . get_url_no_port(true); return $this->setCode(ErrorCodeConstants::REDIRECT)->setData($redirect)->getReturn(); } return true; } /** * 推广页 登录 * @return \app\main\model\object\ReturnObject|bool|RedirectResponse * @throws \Exception * @throws \think\Exception * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\ModelNotFoundException * @throws \think\exception\DbException */ private function loginAgent() { $urlChannelId = $this->getRunTimeObject()->channelId; if (Ua::isWeiXin()) { $adminConfig = AdminService::instance()->getAdminConfigModel()->getAdminInfoAll($urlChannelId); $refreshToken = OpenPlatformService::instance()->getRefreshToken($adminConfig['admin_id']); $officialAccount = OpenPlatformService::instance()->getOfficialAccount($adminConfig['appid'], $refreshToken); if (Request::instance()->has('code')) { // 具有code,直接获取openid try { if (Request::instance()->has('asss')) { $getAuthSTime = floatval(Request::instance()->param('asss')); $getAuthETime = microtime(true); $this->useTime = $this->useTime + ($getAuthETime - $getAuthSTime); Log::info(sprintf('WeChat->LoginAgent->Auth->Time StartTime:%f EndTime:%f RunTime:%f', $getAuthSTime, $getAuthETime, $getAuthETime - $getAuthSTime)); //异常访问抛出异常 if ($getAuthETime - $getAuthSTime > 60) { throw new HttpException(500, '访问超时!'); } } $getOpenIDStime = microtime(true); $oauth = $officialAccount->oauth; $oauth::setGuzzleOptions(Config::get('wechat.http')); $user = $oauth->user(); $openid = $user->getId(); $getOpenIDEtime = microtime(true); $this->useTime = $this->useTime + ($getOpenIDEtime - $getOpenIDStime); Log::info(sprintf('WeChat->LoginAgent->OpenID->Time OpenID:%s StartTime:%f EndTime:%f RunTime:%f', $user->getId(), $getOpenIDStime, $getOpenIDEtime, $getOpenIDEtime - $getOpenIDStime)); if ($openid) { $nxKey = 'L:' . $urlChannelId . ':' . $openid; //用户openid_渠道商id ,唯一,用于防止重复注册 $nxRes = Redis::instanceCache()->setnx($nxKey, 0); if (!$nxRes) { //已经存在 throw new HttpException(500, '请刷新页面重新访问!'); //用户创建中 } Redis::instanceCache()->expire($nxKey, 20); //20秒过期 //通过openid获取用户id $userId = OfficialAccountsService::instance()->getOpenidModel()->getUserId($urlChannelId, $openid); if ($userId) { //通过userid获取用户信息 $userInfo = $this->getUserModel()->setConnect($userId)->getUserInfo($userId); } else { $userInfo = false; } if ($userId && $userInfo) { //已经存在用户 Redis::instanceCache()->del($nxKey); UserService::instance()->setUserCache($userId); } else { try { if (!$userId) { //存在 openid表插入成功,但user表插入失败的情况。所以单独做逻辑判断 // 添加openid表信息 $userId = $this->createUserID($urlChannelId, $openid, time()); if (!$userId) { Log::error('创建用户失败!openid表插入数据失败!' . $urlChannelId . ':' . $openid); throw new HttpException(500, '创建用户失败!'); } } $user = new UserObject(); $user->id = $userId; $user->openid = $openid; $user->referral_id = (int)Request::instance()->get('referral_id'); $user->referral_id_permanent = $user->referral_id; $user->agent_id = (int)Request::instance()->get('agent_id'); $id = $this->insert($user); } catch (\Exception $exception) { Log::error('创建用户失败!' . $exception->getMessage()); $id = null; } Redis::instanceCache()->del($nxKey); if (!$id) { Log::error('创建用户失败!user表插入数据失败!'); throw new HttpException(500, '创建用户失败!'); } $referral_id = UrlService::instance()->getUserReferralId()->data; if (isset($wechatUser) && !isset($wechatUser['errcode']) && !$wechatUser['subscribe'] && $referral_id) { Redis::instance()->setex('U-T:' . $id, 172800, $referral_id); //2天有效期 } $result = UrlService::instance()->unlimitSecondaryDomain(); if ($result->code != ErrorCodeConstants::SUCCESS) { return $result; } } } Log::info(sprintf('WeChat->CallInterface->Time UseTime:%f', $this->useTime)); } catch (AuthorizeFailedException $e) { return $this->loginFail($officialAccount, $e, 'asss'); } } else { $startTime = microtime(true); $url = get_url_no_port(true); //删掉多余参数 $url = del_url_params($url, ['code', 'asss', 'state']); if (stripos($url, '?') === false) { $url .= '?asss=' . $startTime; } else { $url .= '&asss=' . $startTime; } //todo url跳转遗漏 $response = $officialAccount->oauth->scopes(['snsapi_base'])->redirect($url); //获取code return $this->setCode(ErrorCodeConstants::REDIRECT)->setData($response->getTargetUrl())->getReturn(); } } else { $redirect = '/index/login/login?redirect=' . get_url_no_port(true); return $this->setCode(ErrorCodeConstants::REDIRECT)->setData($redirect)->getReturn(); } return $this->getReturn(); } /** * @param \EasyWeChat\OfficialAccount\Application $officialAccount * @param \Exception $e * @param string $startQueryParamName * @return mixed */ private function loginFail($officialAccount, $e, $startQueryParamName) { $errMsg = $e->getMessage(); Log::notice('WeChat->Login->Error:' . $errMsg); $errMsg = str_replace('Authorize Failed:', '', $errMsg); $body = json_decode($errMsg, true); if (is_array($body) && in_array($body['errcode'], [40163, 40029, 41008])) { //code已被使用 或 code无效 Log::notice('code 无效,重试一次 [ CODE ]: ' . $body['errcode']); $startTime = microtime(true); $url = UrlService::instance()->getUrlNoPort(true); if (stripos($url, '?') === false) { $url .= "?$startQueryParamName=$startTime"; } else { $url .= "&$startQueryParamName=$startTime"; } $url = UrlService::instance()->delUrlParams($url, 'code'); if (!Request::instance()->has('jump_self')) { $url .= '&jump_self=1'; $response = $officialAccount->oauth->scopes(['snsapi_base'])->redirect($url); //获取code return $this->setCode(ErrorCodeConstants::REDIRECT)->setData($response->getTargetUrl())->getReturn(); } } } /** * 注册用户-推广页 * @param $data * @return int|string * @throws \Exception */ public function insert($data) { if (!($data instanceof BaseObject) && is_array($data)) { $data = (new UserObject())->bind($data); } $channelId = $this->getRunTimeObject()->channelId; $time = time(); $ids = explode(',', Config::get('site.give_shubi_channel_id')); if (in_array($channelId, $ids)) { $kandian_reg = 3000; } else { $kandian_reg = empty(Config::get('site.kandian_reg')) ? 0 : intval(Config::get('site.kandian_reg')); } $default = new UserObject(); $default->nickname = '书友'; $default->avatar = cdnurl('/assets/img/frontend/icon/nav_icon_4.png'); $default->channel_id = $channelId; $default->register_ip = Ip::ip() ?? null; $default->country = Ip::country(); $default->area = Ip::area(); $default->province = Ip::province(); $default->first_cancel_pay = 2; $default->is_subscribe = 0; $default->subscribe_time = 0; $default->city = Ip::city(); $default->sex = 0; $default->isp = substr(Ip::isp(), 0, 30); //数据库长度 30 $default->createtime = $time; $default->updatetime = $time; $insert = array_merge($default->toArray(), $data->toArray()); $id = $this->getUserModel()->setConnect($data->id)->insertGetId($insert); if ($id) { //注册成功 //新增用户累计 $cid = AdminService::instance()->getAdminExtendModel()->getChannelId($channelId); $cacheKey = CacheConstants::getNewUserCacheKey($cid); Redis::instance()->incr($cacheKey); Redis::instance()->expire($cacheKey, 86400); LogService::debug('用户累计增加'); $data->id = $id; UserService::setUserCache($id); //赠送用户免费书币 if ($kandian_reg) { $endTime = intval(Config::get('site.kandian_free_day')) * 86400; $rdata = []; $rdata['free_kandian'] = $kandian_reg; $rdata['remain_free_kandian'] = $kandian_reg; $rdata['type'] = 3; $rdata['user_id'] = $id; $rdata['free_endtime'] = $endTime + $time; $rdata['notes'] = '新用户注册赠送'; $rdata['createtime'] = $time; $rdata['updatetime'] = $time; FinancialService::instance()->getRechargeModel()->setConnect($id)->insertGetId($rdata); Redis::instance()->del('ZR:' . $id); } if ($insert['sex']) { $oSexAna = new AnalysisObject(); $oSexAna->event_time = UserService::instance()->getRunTimeObject()->requestTime; $oSexAna->type = KafkaDotConstants::TYPE_SEX; $oSexAna->data['sex'] = $insert['sex']; KafkaDotService::instance()->sendMsg($id, $oSexAna); } //新增用户打点 $dotData = new DotObject(); $dotData->channel_id = $channelId; $dotData->sex = $insert['sex']; $dotData->action_type = MqConstants::ROUTING_KEY_SUBSCRIBE; $dotData->type = MqConstants::MSG_TYPE_INCREASE; $dotData->event_time = UserService::instance()->getRunTimeObject()->requestTime; MqService::instance()->sendMessage($dotData); $oAna = new AnalysisObject(); $oAna->event_time = UserService::instance()->getRunTimeObject()->requestTime; $oAna->type = KafkaDotConstants::TYPE_NEW; //推广id的创建用户 if ($referral_id = UrlService::instance()->getUserReferralId()->data) { $oAna->user_from['referral_id'] = $referral_id; $dotData->referral_id = $referral_id; $dotData->action_type = MqConstants::ROUTING_KEY_SUBSCRIBE_REFERER; MqService::instance()->sendMessage($dotData); } $oAna->data['user_collect'] = 1; KafkaDotService::instance()->sendMsg($id, $oAna); //加入用户统计 // $this->getUserCollectModel()->addSubscribeCache($channelId, $data->sex, true); //添加用户创建时间 WhiteList::addUserCreatePayTime($id); BookService::instance()->insertShelfRecommendBooks($id, $insert['sex'],$channelId); } else { Log::error('创建用户失败!user表插入数据失败!data:' . json_encode($data)); } return $id; } /** * 刷新cookie资料 * * @param $userInfo */ public function refreshCookie($userInfo) { if (IS_CLI) { return; } if($userInfo instanceof BaseObject){ $userInfo = $userInfo->toArray(); } $urlType = $this->getRunTimeObject()->urlType; if (in_array($urlType, [OpenPlatformConstants::URL_TYPE_SPREAD, OpenPlatformConstants::URL_TYPE_PAY]) && $userInfo && isset($userInfo['id'])) { Cookie::set('user_id', $userInfo['id']); Cookie::set('channel_id', $userInfo['channel_id']); if (OpenPlatformConstants::URL_TYPE_SPREAD == $urlType) { Cookie::set('openid', $userInfo['openid']); } if ($userInfo['referral_id']) { Cookie::set('referral_id', $userInfo['referral_id']); } else { Cookie::delete('referral_id'); } if ($userInfo['agent_id']) { Cookie::set('agent_id', $userInfo['agent_id']); } else { Cookie::delete('agent_id'); } $ext = $userInfo['ext']??''; if ($ext) { Cookie::set('ext', $ext); } else { Cookie::delete('ext'); } } } /** * 检测是否登录 * @return bool */ public function isLogin() { $urlType = $this->getRunTimeObject()->urlType; switch ($urlType) { case OpenPlatformConstants::URL_TYPE_ADMIN: // 后台首页 break; case OpenPlatformConstants::URL_TYPE_PAY: // 充值页 if (Ua::isWeiXin()) { if (!Cookie::has('user_id')) { throw new HttpException(402, '账号错误'); } if (request()->isAjax()) { if (Cookie::has('openid') && Cookie::has('app_id') && Cookie::get('app_id') == Config::get('wechat.app_id')) { return true; } } else { if ( Cookie::has('openid') && Cookie::has('open_id') && Cookie::get('openid') == Cookie::get('open_id') && Cookie::has('app_id') && Cookie::get('app_id') == Config::get('wechat.app_id') ) { return true; } } } elseif (Cookie::has('user_id')) { return true; } break; case OpenPlatformConstants::URL_TYPE_SPREAD: // 推广页 if ($this->getUserInfo()->id) { return true; } break; } return false; } /** * 更新用户资料 * @param $data * @param $where * @return bool */ public function update($data, $where = []) { if (!$where) { $where['id'] = UserService::instance()->getUserInfo()->id; } if (isset($where['id']) && $where['id']) { $userId = $where['id']; if (UserService::instance()->getUserInfo()->id) { $this->getRunTimeObject()->user->bind($data); } if (ApiService::instance()->checkApiOn()) { $userUpdate = new UserUpdate(); $userUpdate->bind($data)->setId($where['id']); // $data['id'] = $where['id']; \app\source\service\UserService::instance()->updateUser($userUpdate)->id; return true; } else { $result = $this->getUserModel()->setConnect($userId)->update($data, $where); if ($result) { //加入redis $userKey = CacheConstants::getUserCacheKey($userId); if(Redis::instance()->exists($userKey)){ //更改 Redis::instance()->hmset($userKey,$data); Redis::instance()->expire($userKey,86400); }else{ //新增 $this->getUserModel()->getUserInfo($userId); } if (!Request::instance()->isAjax() && !IS_CLI) { $this->refreshCookie($this->getUserInfo()); } } return true; } } return false; } /** * 获取用户资料 * * @param bool $force 是否从数据库重新获取 默认false从缓存中获取 true从数据库重新获取 * @return UserObject */ public function getUserInfo($force = false) { $urlType = $this->getRunTimeObject()->urlType; $user = $this->getRunTimeObject()->user; if (!$user || !$user->id || $force) { switch ($urlType) { case OpenPlatformConstants::URL_TYPE_ADMIN: // 后台首页 break; case OpenPlatformConstants::URL_TYPE_PAY: // 充值页 if ($userId = Cookie::get('user_id')) { $user = $this->getUserModel()->getUserInfo($userId, $force); } break; case OpenPlatformConstants::URL_TYPE_SPREAD: // 推广页 if ($userId = Cookie::get('user_id')) { $user = $this->getUserModel()->getUserInfo($userId, $force); if (isset($user['openid']) && ($user['openid'] == Cookie::get('openid'))) { $this->refreshCookie($user); } } break; default: if ($userId = Cookie::get('user_id')) { $user = $this->getUserModel()->getUserInfo($userId, $force); } break; } if ($user) { $this->getRunTimeObject()->user = (new UserObject())->bind($user); $this->refreshCookie($user); }else{ $this->getRunTimeObject()->user = new UserObject(); } } if(!$this->getRunTimeObject()->user->avatar){ $this->getRunTimeObject()->user->avatar = '/assets/img/frontend/icon/nav_icon_4.png'; } return $this->getRunTimeObject()->user; } /** * 获取visitor,先获取cookie,若无,自动生成一个 * * @param bool $force 是否强制生成一个新的 * @return mixed|string */ public function visitor($force = false) { if (!$force && Cookie::has('visitor')) { return Cookie::get('visitor'); } else { return date('YmdHis') . Random::uuid(); } } /** * 程序运行参数汇总 * @return RunTimeObject */ public function getRunTimeObject() { if(!$this->runTimeObject){ $this->runTimeObject = new RunTimeObject(); } return $this->runTimeObject; } /** * 魔术方法获取(只支持单级属性获取,多级属性请使用getUserInfo) * * @param $name * @return mixed|null */ public function __get($name) { if ($this->getUserInfo()) { return $this->getUserInfo()->get($name) ?? null; } else { return null; } } /** * 获取用户表库索引 * @param $user_id * @return int */ public function getUserDBIndex($user_id) { return $user_id % 512; } /** * 获取openid表的库索引 * @param $channel_id * @param $open_id * @return int */ public function getOpenIdDBIndex($channel_id, $open_id) { $channel_openid = $channel_id . '_' . $open_id; return hash_code($channel_openid) % 512; } /** * 获取用户admin_id * @return \app\main\model\object\ReturnObject */ public function getAdminId() { if ($agentId = UrlService::instance()->getUserAgentId()->data) { return $this->setData($agentId)->getReturn(); } else if ($channelId = $this->getUserInfo()->channel_id) { return $this->setData($channelId)->getReturn(); } return $this->getReturn(); } public function setUserCache($user_id) { if ($user_id) { Cookie::set('user_id', $user_id); UserService::instance()->getUserInfo(true); } } /** * 更新用户缓存 * @param $user_id * @param $update */ public function updateRedisUserCache($user_id, $update) { $userKey = CacheConstants::getUserCacheKey($user_id); $this->getRunTimeObject()->user = $this->getRunTimeObject()->user->bind($update); if (Redis::instance()->exists($userKey)) { Redis::instance()->hmset($userKey, $update); Redis::instance()->expire($userKey, 86400); } } /** * @return ReturnObject */ public function getUserChannelId() { $channelAgentId = UserService::instance()->getUserInfo()->channel_id; $groupId = AdminService::instance()->getAuthGroupAccessModel()->getGroupId($channelAgentId); if ($groupId == AdminConstants::ADMIN_GROUP_ID_AGENT) { $adminExtend = AdminService::instance()->getAdminExtendModel()->getInfo($channelAgentId); return $this->setData($adminExtend['create_by'])->getReturn(); } return $this->setData($channelAgentId)->getReturn(); } /** * 设置用户额外信息 * @param $user_id * @param array $data * @return bool */ public function setOtherDataToRedis($user_id, $data = []) { $redisKey = self::USER_OTHER_DATA_KEY_PREFIX . $user_id; $redisData = $data; if (Redis::instance()->exists($redisKey)) { $redisData = Redis::instance()->hGetAll($redisKey); $redisData = array_merge($redisData, $data); } Redis::instance()->hMSet($redisKey, $redisData); return Redis::instance()->expire($redisKey, self::USER_OTHER_DATA_EXPIRE); } /** * 获取用户额外信息 * @param $user_id * @return array */ public function getOtherDataFromRedis($user_id) { $result = []; $redisKey = self::USER_OTHER_DATA_KEY_PREFIX . $user_id; if (Redis::instance()->exists($redisKey)) { $result = Redis::instance()->hGetAll($redisKey); } return $this->setData($result)->getReturn()->data; } public function getUserIdByPhone($phone){ $json_data = $this->getUserPhoneModel()->setConnect($phone)->getInfoByPhone($phone); $data = []; if($json_data){ $data = json_decode($json_data, true); } return $data; } }