convertUrlQuery($urlArr['query']); } $queryArr['has_silent'] = '1'; unset($queryArr['code']); $new_url = $urlArr['scheme'] . "://" . $urlArr['host'] . $urlArr['path'] . "?" . http_build_query($queryArr); return $new_url; } /** * Returns the url query as associative array * * @param string query * @return array params */ function convertUrlQuery($query) { $queryParts = explode('&', $query); $params = array(); foreach ($queryParts as $param) { $item = explode('=', $param); $params[$item[0]] = $item[1]; } return $params; } /** * 判断是否已经有静默渠道关联数据 * @param $user_id * @param $channel_id * @param $open_id * @param $tri_channel_id * @return bool */ public function getSilentData($user_id, $channel_id, $open_id, $tri_channel_id) { $redisKey = $this->preRedisKey . $user_id . ':' . $channel_id . ":" . $open_id . ":" . $tri_channel_id; LogService::info('F:silent:rediskey:' . $redisKey); if (Redis::instance()->get($redisKey)) { return true; } else { $obj = $this->getUserSilentModel() ->where( [ 'user_id' => $user_id, 'channel_id' => $channel_id, 'openid' => $open_id, 'tri_channel_id' => $tri_channel_id, ] ) ->find(); if ($obj) { Redis::instance()->set($redisKey, 1, 86400); return true; } else { return false; } } } /** * 存储静默渠道关联数据 * @param $user_id * @param $channel_id * @param $open_id * @param $tri_channel_id * @param $tri_openid */ public function saveSilentData($user_id, $channel_id, $open_id, $tri_channel_id, $tri_openid) { LogService::info("F:silent:saveSilentData2:{$user_id},{$channel_id},{$open_id},{$tri_channel_id},{$tri_openid}"); $result = []; if ($user_id) { $redisKey = $this->preRedisKey . $user_id . ':' . $channel_id . ":" . $open_id . ":" . $tri_channel_id; LogService::info("F:silent:Redis:redisKey:" . $redisKey . ':value:' . Redis::instance()->get($redisKey)); if (!Redis::instance()->get($redisKey)) { try { // 解决问题:线上有并发请求问题,会同时执行两条相同的插入操作 $redisKeyNx = $this->preRedisKey . 'nx:' . $user_id; if (Redis::instance()->setnx($redisKeyNx, 1)) { Redis::instance()->expire($redisKeyNx, 10); $obj = $this->getUserSilentModel() ->where( [ 'user_id' => $user_id, 'channel_id' => $channel_id, 'openid' => $open_id, 'tri_channel_id' => $tri_channel_id, 'tri_openid' => $tri_openid, ] ) ->find(); if (!$obj) { $tri_appid = ''; $tri_arr = model('AdminConfig')->getAdminInfoAll($tri_channel_id); if (!empty($tri_arr['appid'])) { $tri_appid = $tri_arr['appid']; } LogService::info("F:silent:saveSilentData3:{$user_id},{$channel_id},{$open_id},{$tri_channel_id},{$tri_openid},{$tri_appid}"); $insertData = [ 'user_id' => $user_id, 'channel_id' => $channel_id, 'openid' => $open_id, 'tri_channel_id' => $tri_channel_id, 'tri_openid' => $tri_openid, 'tri_appid' => $tri_appid, 'updatetime' => time(), 'createtime' => time(), ]; $this->getUserSilentModel()->insert($insertData); $result = $insertData; } } } catch (\Exception $exception) { LogService::error("F:silent: error:" . $exception->getMessage()); } } } return $result; } /** * 校验渠道是否开启静默授权 * @param $channel_id * @return bool */ public function silentChannel($channel_id) { // 开启静默授权的渠道 $silent_channels = Config::get('site.silent_channels') ?? ''; // 默认转移到的渠道 $silent_default_channel = Config::get('site.silent_default_channel') ?? ''; if ($channel_id == $silent_default_channel) { return true; } if (!$silent_default_channel) { return false; } if (!$silent_channels) { return false; } elseif ($silent_channels == -1) { return true; } else { $silent_channels = str_replace(',', ',', $silent_channels); $silent_channels_arr = explode(',', $silent_channels); if (in_array($channel_id, $silent_channels_arr)) { return true; } else { return false; } } } /** * 渠道粉丝转移功能 * @param $nowUserRow * @param $uid * @param $to_channel_id * @param $openid * @param $from_channel_id */ public function channelFansTransfer($nowUserRow, $uid, $to_channel_id, $openid, $from_channel_id) { //当前用户 if (empty($nowUserRow)) { $nowUserRow = $this->getUserSilentModel()->where([ 'user_id' => $uid, 'channel_id' => $to_channel_id, 'openid' => $openid ])->find(); } if (empty($nowUserRow)) { LogService::info("F:silent: info:未找到静默授权关联数据"); return false; } //老用户 $oldUserRow = $this->getUserSilentModel()->where([ 'tri_channel_id' => $nowUserRow['tri_channel_id'], 'tri_openid' => $nowUserRow['tri_openid'], 'channel_id' => $from_channel_id ])->find(); if (empty($oldUserRow)) { LogService::info("F:silent: info:新用户不需要转移.uid:" . $uid); return false; } else { $this->doTransfer($oldUserRow['user_id'], $uid); $record['uid'] = $uid; $record['from_cid'] = $from_channel_id; $record['to_cid'] = $to_channel_id; $record['createtime'] = time(); model('ChannelUserTransferRecord')->save($record); } return true; } /** * 执行转移 * @param $old_user_id * @param $current_user_id * @throws \Exception */ public function doTransfer($old_user_id, $current_user_id) { //书架最新5本 //老用户阅读记录 $oldResult = BookService::instance()->getUserRecentlyRead()->setConnect($old_user_id)->getRecentlyRead(0, 5, $old_user_id, true); $oldData = $oldResult['data']; if (!empty($oldData)) { foreach ($oldData as $old) { $chapterInfo = BookService::instance()->getChapterInfo($old['book_id'], $old['chapter_id']); if ($chapterInfo->code == ErrorCodeConstants::SUCCESS) { $chapterInfo = $chapterInfo->data; BookService::instance()->setRecentlyRead($old['chapter_name'], $old['chapter_id'], $old['book_id'], $chapterInfo['idx'], $current_user_id); } } } //余额 $kandian_total = FinancialService::instance()->getTotalKandianAndFreeKandian($old_user_id)->data; if ($kandian_total) { $this->addFreeKandian($current_user_id, $kandian_total, RechargeConstants::RECHARGE_TYPE_KANDIAN, OrderContents::ORDER_DEDUCT_YES, '2', '渠道用户转移看点', 20); } $aOldUserInfo = UserService::instance()->getUserModel()->getUserInfo($old_user_id); $newUserInfoObj = UserService::instance()->getUserModel()->getUserInfo($current_user_id); //vip转移 if (intval($aOldUserInfo['vip_endtime']) > time()) { //$userData['id'] = $current_user_id; $rechargeData['user_id'] = $current_user_id; $rechargeData['type'] = 4; $rechargeData['notes'] = '渠道用户转移VIP时长'; $rechargeData['edit_type'] = 2; $rechargeData['createtime'] = time(); $vipAddTime = intval($aOldUserInfo['vip_endtime']) - time(); if (intval($newUserInfoObj['vip_endtime']) > time()) { $userData['vip_endtime'] = $vipAddTime + intval($newUserInfoObj['vip_endtime']); $rechargeData['vip_starttime'] = intval($newUserInfoObj['vip_starttime']); } else { $userData['vip_endtime'] = $vipAddTime + time(); $rechargeData['vip_starttime'] = time(); } $rechargeData['day'] = floor($vipAddTime / 86400); $rechargeData['hour'] = floor(($vipAddTime - $rechargeData['day'] * 86400) / 3600); $userData['vip_starttime'] = model('Recharge')->getVipStartTime($current_user_id); $rechargeData['channel_vip_starttime'] = model('Recharge')->getChannelVipStartTime($current_user_id); if (ApiService::instance()->checkApiOn()) { $userUpdate = new UserUpdate(); $userUpdate->setAddvipday($vipAddTime)->setId($current_user_id); \app\source\service\UserService::instance()->updateUser($userUpdate); } else { model('User')->setConnect($current_user_id)->where('id',$current_user_id)->update($userData); //更改用户表数据 Redis::instance()->del('UN:' . $current_user_id); } model('Recharge')->setConnect($current_user_id)->insert($rechargeData); //插入充值记录 } } /** * 添加免费书币 * @param $user_id * @param $kandian * @param $order_id * @param $type * @param $edit_type * @param $notes * @param $dd * @return \app\main\model\object\ReturnObject */ public function addFreeKandian($user_id, $kandian, $type, $dd, $edit_type, $notes, $day, $order_id = '') { $recharge = [ 'user_id' => $user_id, 'type' => $type, 'kandian' => 0, 'remain_kandian' => 0, 'free_kandian' => $kandian, 'remain_free_kandian' => $kandian, 'free_endtime' => time() + $day * 86400, 'orders_id' => $order_id, 'book_id' => '', 'dd' => $dd, 'edit_type' => $edit_type, 'notes' => $notes, 'createtime' => time(), 'updatetime' => time(), 'business_line' => PayConstants::BUSINESS_WECHAT, ]; $result = FinancialService::instance()->getRechargeModel()->setConnect($user_id)->insertGetId($recharge); Redis::instance()->del(CacheConstants::getFreeKandianUserRechargeListCacheKey($user_id)); return $this->setData($result)->getReturn(); } }