getBrandConfigAndState(); if ($conf instanceof Json) { return $conf; } return $this->successResponse($conf); } /** * 检测登录 通过cookie中的SUB字段的内容,调用用户接口检测登录状态 * @throws ClassNotFoundException * @throws ReflectionException * @return mixed */ public function checkLogin() { FacadeLog::info("cookies:" . json_encode(Request::post())); $sub = ""; $uid = 0; if (!empty($_COOKIE['SUB'])) { $sub = $_COOKIE['SUB']; } else { // 只在调试模式下开启从POST参数中获取UID,方便测试联调 if (env('app_debug')) { $sub = Request::post('cookie'); $uid = $sub; } else { return $this->response(403, 'not login.'); } } FacadeLog::info($sub); $userInfoRes = (new WeiboService($uid))->userinfo($sub); if (empty($userInfoRes) || $userInfoRes['ok'] != 1) { return $this->response(403, $userInfoRes['msg'] ?? '没有登录'); } // 使用客户端信息生成token $token = md5($_SERVER['HTTP_USER_AGENT'] . $_SERVER['HTTP_ACCEPT_ENCODING'] . $_SERVER['HTTP_ACCEPT_LANGUAGE'] . $_SERVER['HTTP_REFERER'] . get_client_ip(0) . $userInfoRes['data']['uid']); $user = $userInfoRes['data']; $userInfo = Db::table('awards_user_info')->where('uid', $user['uid'])->find(); if (empty($userInfo)) { $userAttr = [ 'uid' => $user['uid'], 'portrait' => $user['profile_image_url'], 'nickname' => $user['name'] ]; if (0 == Db::table('awards_user_info')->insert($userAttr)) { return $this->response(5001, '系统错误,请稍后再试~'); } } // 生成加密用的密钥和向量 $cipher = "aes-256-gcm"; $ivlen = openssl_cipher_iv_length($cipher); $iv = bin2hex(openssl_random_pseudo_bytes($ivlen)); $aesKey = bin2hex(openssl_random_pseudo_bytes(32)); $user = array_merge($user, [ 'aes_key' => $aesKey, 'ase_iv' => $iv, ]); $cacheUser = [ 'aes_key' => $aesKey, 'ase_iv' => $iv, 'uid' => $user['uid'], ]; $first = 0; $date = date('Y-m-d'); $userTask = Db::table('awards_user_task')->where('uid', $user['uid'])->where('date', $date)->find(); if (empty($userTask)) { // 当天第一次,初始化数据 $state = [ // 品牌任务完成状态 'finish_state' => 0, // 关注子任务状态 'follow_state' => 0, // 转发子任务状态 'forward_state' => 0, // 查看浏览主页任务状态 'view_state' => 0, // 品牌任务完成后是否加票 'finish_add_votes' => 0, // 分享完成后是否加票 'share_add_votes' => 0, 'uid' => $user['uid'], 'date' => $date, ]; if (0 == Db::table('awards_user_task')->insert($state)) { return $this->response(5001, '系统错误,请稍后再试~'); } } else if ($userTask['finish_state'] == 0 && $userTask['share_add_votes'] == 0) { $count = Db::table('awards_user_task_log')->where('uid', $user['uid'])->where('date', $date)->count('id'); if ($count < 1) { $first = 1; } } else if ($userTask['finish_state'] > 0 && $userTask['share_add_votes'] > 0) { $count = Db::table('awards_user_task_log')->where('uid', $user['uid'])->where('date', $date)->count('id'); if ($count < 2) { $first = 1; } } // 缓存用户信息1天 Cache::set('u:' . $token, json_encode($cacheUser), 86400); return $this->successResponse([ 'user' => $user, 'token' => $token, 'first' => $first, ]); } /** * 提交任务接口 * @throws FuncNotFoundException * @throws ClassNotFoundException * @throws DbException * @throws ModelNotFoundException * @throws DataNotFoundException * @return mixed */ public function submitTask() { $duration = Request::post("duration"); $number = Request::post("number"); $date = date('Y-m-d'); $userTask = Db::table('awards_user_task')->where('uid', Safe::$user['uid'])->where('date', $date)->find(); if (empty($userTask)) { return $this->response(403, '没有登录'); } $log = []; if ($userTask['finish_state'] == 0) { $count = Db::table('awards_user_task_log')->where('uid', Safe::$user['uid'])->where('date', $date)->count('id'); if ($count > 0) { return $this->response(403, '没有参与次数'); } $log = [ 'uid' => Safe::$user['uid'], 'date' => $date, 'duration' => $duration, 'number' => $number, 'create_at' => time() ]; Db::table('awards_user_task')->where('uid', Safe::$user['uid'])->where('date', $date)->update([ 'finish_state' => 1, ]); } else if ($userTask['share_add_votes'] == 1) { $count = Db::table('awards_user_task_log')->where('uid', Safe::$user['uid'])->where('date', $date)->count('id'); if ($count > 1) { return $this->response(403, '没有参与次数'); } $log = [ 'uid' => Safe::$user['uid'], 'date' => $date, 'duration' => $duration, 'number' => $number, 'create_at' => time() ]; } if (empty($log)) { return $this->response(403, '没有参与次数'); } if (0 == Db::table('awards_user_task_log')->insert($log)) { return $this->response(5001, '系统错误,请稍后再试~'); } return $this->successResponse(null, '提交成功'); } /** * 提交发布微博接口 * @throws FuncNotFoundException * @throws ClassNotFoundException * @throws DbException * @throws ModelNotFoundException * @throws DataNotFoundException * @return mixed */ public function submitShare() { $date = date('Y-m-d'); $userTask = Db::table('awards_user_task')->where('uid', Safe::$user['uid'])->where('date', $date)->find(); if (empty($userTask)) { return $this->response(403, '没有登录'); } if ($userTask['share_add_votes'] > 0) { return $this->response(601, '今日已发布'); } // 更新任务状态 $nums = Db::table('awards_user_task')->where('uid', Safe::$user['uid'])->where('date', $date)->update([ 'share_add_votes' => 1, ]); if ($nums) { return $this->response(601, '发布成功'); } else { return $this->response(601, '发布失败'); } } /** * 排行接口 * @throws FuncNotFoundException * @throws ClassNotFoundException * @throws DbException * @throws ModelNotFoundException * @throws DataNotFoundException * @return mixed */ public function ranking() { $date = date('Y-m-d'); $res = Db::table('awards_user_task_log')->alias("l") ->leftJoin('awards_user_info u', 'l.uid = u.uid') ->field(['u.nickname', 'u.portrait', 'u.uid', 'l.duration', 'l.number']) ->where('l.date', $date) ->order('l.number', 'desc') ->order('l.duration', 'asc') ->limit(15) ->select(); return $this->successResponse($res); } /** * 品牌任务关注接口 * @throws FuncNotFoundException * @throws ClassNotFoundException * @throws ReflectionException * @throws DbException * @throws ModelNotFoundException * @throws DataNotFoundException * @return mixed */ public function follow() { // 先获取品牌任务配置及状态 $conf = $this->getBrandConfigAndState(); if ($conf instanceof Json) { return $conf; } // 已经关注过了 if ($conf['state']['follow_state'] == 1) { return $this->successResponse([ 'result' => 2, 'brand' => $conf, ], '您已经关注过了'); } // 调用接口关注 $weiboRes = (new WeiboService(Safe::$user['uid']))->add($conf['config']['follow']['id']); if (empty($weiboRes) || $weiboRes['code'] != 10000) { return $this->response(600, $weiboRes['msg'] ?? '关注失败~'); } $date = date('Y-m-d'); $redisKey = $this->getTaskStateRedisKey(intval(Safe::$user['uid'])); // 如果已经完成了另外两项,则标记品牌任务已经完成 $finishState = $conf['state']['finish_state']; if ($conf['state']['view_state'] == 1 && $conf['state']['forward_state'] == 1) { $finishState = 1; } // 更新任务状态 $nums = Db::table('awards_user_task')->where('uid', Safe::$user['uid'])->where('date', $date)->update([ 'follow_state' => 1, 'finish_state' => $finishState, ]); if ($nums) { $conf['state']['follow_state'] = 1; $conf['state']['finish_state'] = $finishState; Cache::set($redisKey, json_encode($conf['state']), 86400); return $this->successResponse([ 'result' => 1, 'brand' => $conf, ], '关注成功'); } else { return $this->response(601, '更新任务状态失败'); } } /** * 品牌任务转发博文接口 * @throws FuncNotFoundException * @throws ClassNotFoundException * @throws ReflectionException * @throws DbException * @throws ModelNotFoundException * @throws DataNotFoundException * @return mixed */ public function forward() { // 先获取品牌任务配置及状态 $conf = $this->getBrandConfigAndState(); if ($conf instanceof Json) { return $conf; } // 已经转发过了 if ($conf['state']['forward_state'] == 1) { return $this->successResponse([ 'result' => 2, 'brand' => $conf, ], '您已经转发过了'); } // 调用微博接口转发 $weiboRes = (new WeiboService(Safe::$user['uid']))->repost($conf['config']['forward']['id'], $conf['config']['forward']['content'] ?? ''); if (empty($weiboRes) || $weiboRes['code'] != 10000) { return $this->response(600, $weiboRes['msg'] ?? '转发失败~'); } $date = date('Y-m-d'); $redisKey = $this->getTaskStateRedisKey(intval(Safe::$user['uid'])); // 如果已经完成了另外两项,则标记品牌任务已经完成 $finishState = $conf['state']['finish_state']; if ($conf['state']['view_state'] == 1 && $conf['state']['follow_state'] == 1) { $finishState = 1; } // 更新任务状态 $nums = Db::table('awards_user_task')->where('uid', Safe::$user['uid'])->where('date', $date)->update([ 'forward_state' => 1, 'finish_state' => $finishState, ]); if ($nums) { $conf['state']['forward_state'] = 1; $conf['state']['finish_state'] = $finishState; Cache::set($redisKey, json_encode($conf['state']), 86400); return $this->successResponse([ 'result' => 1, 'brand' => $conf, ], '转发成功'); } else { return $this->response(601, '更新任务状态失败'); } } /** * 获取活动规则 * @throws FuncNotFoundException * @throws ReflectionException * @throws InvalidArgumentException * @throws ClassNotFoundException * @return mixed */ public function getRule() { $config = SystemService::instance()->getData('activity:rule'); return $this->successResponse($config); } /** * 聚合页配置信息 * @throws FuncNotFoundException * @throws ReflectionException * @throws InvalidArgumentException * @throws ClassNotFoundException * @return mixed */ public function groupPageConfig() { return $this->successResponse(['config' => SystemService::instance()->getData('group:page:config')]); } public function index() { $this->redirect(sysuri('admin/login/index')); } /** * 聚合页通知获取 * 查询最近20条通知 * @throws DbException * @throws ModelNotFoundException * @throws DataNotFoundException * @return mixed */ public function notices() { $rows = SystemNotice::limit(20)->order('id', 'desc')->select(); return $this->successResponse([ "lists" => $rows, ]); } /** * 首次弹窗 * 发放邀请函微博 * @return Json */ public function sendInviteWeibo() { $config = SystemService::instance()->getData('group:page:config'); $sendRes = (new WeiboService(Safe::$user['uid']))->status($config['firstDialog']['content']); if (empty($sendRes) || $sendRes['code'] != 10000) { return $this->response(403, $sendRes['msg'] ?? '发布失败'); } Cache::set('u:f:' . Safe::$user['uid'], 1, 15552000); return $this->successResponse(null, '发布成功!'); } /** * 首次弹窗用户未选择发送邀请函 * 标记已经首次弹窗过了 * @return mixed */ public function setFirst() { Cache::set('u:f:' . Safe::$user['uid'], 1, 15552000); return $this->successResponse(null, '操作成功!'); } /** * 标记用户已经浏览过主页了,用户点了去浏览时调用 * @throws FuncNotFoundException * @throws ClassNotFoundException * @throws ReflectionException * @throws DbException * @throws ModelNotFoundException * @throws DataNotFoundException * @return mixed */ public function setViewed() { // 先获取品牌任务配置及状态 $conf = $this->getBrandConfigAndState(); if ($conf instanceof Json) { return $conf; } if ($conf['state']['view_state'] == 1) { return $this->successResponse([ 'result' => 2, 'brand' => $conf, ], '您已经浏览过了'); } $date = date('Y-m-d'); $redisKey = $this->getTaskStateRedisKey(intval(Safe::$user['uid'])); // 如果已经完成了另外两项,则标记品牌任务已经完成 $finishState = $conf['state']['finish_state']; if ($conf['state']['forward_state'] == 1 && $conf['state']['follow_state'] == 1) { $finishState = 1; } $nums = Db::table('awards_user_task')->where('uid', Safe::$user['uid'])->where('date', $date)->update([ 'view_state' => 1, 'finish_state' => $finishState, ]); if ($nums) { $conf['state']['view_state'] = 1; $conf['state']['finish_state'] = $finishState; Cache::set($redisKey, json_encode($conf['state']), 86400); return $this->successResponse([ 'result' => 1, 'brand' => $conf, ], '浏览成功'); } else { return $this->response(601, '更新任务状态失败'); } } /** * 用户完成端外分享时调用接口加票 * @throws FuncNotFoundException * @throws ClassNotFoundException * @throws ReflectionException * @throws DbException * @throws ModelNotFoundException * @throws DataNotFoundException * @return mixed */ public function shareFinishAddVotes() { // 先获取品牌任务配置及状态 $conf = $this->getBrandConfigAndState(); if ($conf instanceof Json) { return $conf; } if ($conf['state']['share_add_votes'] == 1) { return $this->successResponse([ 'result' => 2, 'brand' => $conf, ], '您今日已经领取过投票机会了~'); } // 调用接口给用户发券(加票) $weiboRes = (new WeiboService(Safe::$user['uid']))->setcoupons($conf['config']['share']['votes']); if (empty($weiboRes) || $weiboRes['code'] != 10000) { return $this->response(600, $weiboRes['msg'] ?? '加票失败~'); } // 标记状态 $date = date('Y-m-d'); $redisKey = $this->getTaskStateRedisKey(intval(Safe::$user['uid'])); $nums = Db::table('awards_user_task')->where('uid', Safe::$user['uid'])->where('date', $date)->update([ 'share_add_votes' => 1, ]); if ($nums) { $conf['state']['share_add_votes'] = 1; Cache::set($redisKey, json_encode($conf['state']), 86400); return $this->successResponse([ 'result' => 1, 'brand' => $conf, ], '加票成功'); } else { return $this->response(601, '更新任务状态失败'); } } /** * 完成品牌任务后领取加票机会接口 * @throws FuncNotFoundException * @throws ClassNotFoundException * @throws ReflectionException * @throws DbException * @throws ModelNotFoundException * @throws DataNotFoundException * @return mixed */ public function taskFinishAddVotes() { // 先获取品牌任务配置及状态 $conf = $this->getBrandConfigAndState(); if ($conf instanceof Json) { return $conf; } if ($conf['state']['finish_add_votes'] == 1) { return $this->successResponse([ 'result' => 2, 'brand' => $conf, ], '您今日已经领取过投票机会了~'); } // 未完成品牌任务 领取失败 if ($conf['state']['finish_state'] == 0) { return $this->response(603, '请先完成品牌任务,再来领取加票', [ 'result' => 0, 'brand' => $conf, ]); } // 调用微博接口 给用户发券(加票) $weiboRes = (new WeiboService(Safe::$user['uid']))->setcoupons($conf['config']['task']['votes']); if (empty($weiboRes) || $weiboRes['code'] != 10000) { return $this->response(600, $weiboRes['msg'] ?? '加票失败~'); } // 标记加票成功 $date = date('Y-m-d'); $redisKey = $this->getTaskStateRedisKey(intval(Safe::$user['uid'])); $nums = Db::table('awards_user_task')->where('uid', Safe::$user['uid'])->where('date', $date)->update([ 'finish_add_votes' => 1, ]); if ($nums) { $conf['state']['finish_add_votes'] = 1; Cache::set($redisKey, json_encode($conf['state']), 86400); return $this->successResponse([ 'result' => 1, 'brand' => $conf, ], '加票成功'); } else { return $this->response(601, '更新任务状态失败'); } } /** * 获取品牌任务配置及状态 * @throws FuncNotFoundException * @throws ReflectionException * @throws InvalidArgumentException * @throws ClassNotFoundException * @throws DbException * @throws ModelNotFoundException * @throws DataNotFoundException * @return \think\response\Json|array */ protected function getBrandConfigAndState() { $config = SystemService::instance()->getData('brand:task:config'); $date = date('Y-m-d'); $dateForRedis = date('Ymd'); if (empty(Safe::$user['uid'])) { $state = [ // 品牌任务完成状态 'finish_state' => 0, // 关注子任务状态 'follow_state' => 0, // 转发子任务状态 'forward_state' => 0, // 查看浏览主页任务状态 'view_state' => 0, // 品牌任务完成后是否加票 'finish_add_votes' => 0, // 分享完成后是否加票 'share_add_votes' => 0, 'uid' => 0, 'date' => $date, ]; } else { $redisKey = "t:{$dateForRedis}:" . Safe::$user['uid']; $state = Cache::get($redisKey); if (empty($state)) { // 缓存失败 查数据库 $state = Db::table('awards_user_task')->where('uid', Safe::$user['uid'])->where('date', $date)->find(); if (empty($state)) { // 当天第一次,初始化数据 $state = [ // 品牌任务完成状态 'finish_state' => 0, // 关注子任务状态 'follow_state' => 0, // 转发子任务状态 'forward_state' => 0, // 查看浏览主页任务状态 'view_state' => 0, // 品牌任务完成后是否加票 'finish_add_votes' => 0, // 分享完成后是否加票 'share_add_votes' => 0, 'uid' => Safe::$user['uid'], 'date' => $date, ]; if (0 == Db::table('awards_user_task')->insert($state)) { return $this->response(5001, '系统错误,请稍后再试~'); } } Cache::set($redisKey, json_encode($state), 86400); } else { $state = json_decode($state, true); } // 如果未关注状态,查询下已经实际已经关注了 if ($state['follow_state'] == 0) { $weiboRes = (new WeiboService(Safe::$user['uid']))->friends($config['follow']['id']); if (isset($weiboRes['data'][$config['follow']['id']]) && $weiboRes['data'][$config['follow']['id']] == 1) { $nums = Db::table('awards_user_task')->where('uid', Safe::$user['uid'])->where('date', $date)->update(['follow_state' => 1]); if ($nums) { $state['follow_state'] = 1; Cache::set($redisKey, json_encode($state), 86400); } } } } // 校准状态,可能存在异常情况关注,转发,浏览都完成了,但是总的品牌任务状态没标记成已完成 if ($state['follow_state'] == 1 && $state['forward_state'] == 1 && $state['view_state'] == 1 && $state['finish_state'] != 1) { $nums = Db::table('awards_user_task')->where('uid', Safe::$user['uid'])->where('date', $date)->update(['finish_state' => 1]); if ($nums) { $state['finish_state'] = 1; Cache::set($redisKey, json_encode($state), 86400); } } return [ 'config' => $config, 'state' => $state, ]; } /** * 获取品牌任务redis 缓存键 * @param int $uid * @return string */ protected function getTaskStateRedisKey(int $uid): string { $dateForRedis = date('Ymd'); return "t:{$dateForRedis}:" . $uid; } /** * @param $code * @param $msg * @param $data * @return Json */ protected function response($code, $msg, $data = null) { return json( [ 'code' => $code, 'message' => $msg, 'data' => $data, 'trackID' => Log::$logID, ], 200 ); } /** * @param $data * @param $msg * @return mixed */ protected function successResponse($data, $msg = '操作成功') { return $this->response(0, $msg, $data); } }