redirect(sysuri('admin/login/index')); } /** * 检测登录 通过cookie中的SUB字段的内容,调用用户接口检测登录状态 * @return mixed * @throws ClassNotFoundException * @throws ReflectionException */ public function checkLogin() { $userInfoRes = (new WeiboService(0))->userinfo(); if (empty($userInfoRes) || $userInfoRes['code'] != 10000) { return $this->response(403, $userInfoRes['msg'] ?? '没有登录'); } // 使用客户端信息生成token $token = md5($_SERVER['HTTP_USER_AGENT'] . $_SERVER['HTTP_ACCEPT_ENCODING'] . $_SERVER['HTTP_ACCEPT_LANGUAGE'] . get_client_ip(0)) . $userInfoRes['data']['uid']; $user = $userInfoRes['data']; // 生成加密用的密钥和向量 $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, ]); // 缓存用户信息1天 Cache::set('u:' . $token, json_encode($user), 86400); return $this->successResponse([ 'user' => $user, 'token' => $token, 'first' => Cache::get('u:f:' . $user['uid']) != 1, ]); } /** * 聚合页配置信息 * @return mixed * @throws FuncNotFoundException * @throws ReflectionException * @throws InvalidArgumentException * @throws ClassNotFoundException */ public function groupPageConfig() { return $this->successResponse(['config' => SystemService::instance()->getData('group:page:config')]); } /** * 聚合页通知获取 * 查询最近20条通知 * @return mixed * @throws DbException * @throws ModelNotFoundException * @throws DataNotFoundException */ public function notices() { $rows = SinaNotice::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, 0); return $this->successResponse(null, '发布成功!'); } /** * 首次弹窗用户未选择发送邀请函 * 标记已经首次弹窗过了 * @return mixed */ public function setFirst() { Cache::set('u:f:' . Safe::$user['uid'], 1, 0); return $this->successResponse(null, '操作成功!'); } /** * 获取活动规则 * @return mixed * @throws FuncNotFoundException * @throws ReflectionException * @throws InvalidArgumentException * @throws ClassNotFoundException */ public function getRule() { $config = SystemService::instance()->getData('activity:rule'); return $this->successResponse($config); } /** * 获取品牌任务相关配置 * * @return mixed * @throws FuncNotFoundException * @throws ClassNotFoundException * @throws ReflectionException * @throws DbException * @throws ModelNotFoundException * @throws DataNotFoundException */ public function brand() { $conf = $this->getBrandConfigAndState(); if ($conf instanceof Json) { return $conf; } return $this->successResponse($conf); } /** * 品牌任务关注接口 * @return mixed * @throws FuncNotFoundException * @throws ClassNotFoundException * @throws ReflectionException * @throws DbException * @throws ModelNotFoundException * @throws DataNotFoundException */ 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('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, '更新任务状态失败'); } } /** * 品牌任务转发博文接口 * @return mixed * @throws FuncNotFoundException * @throws ClassNotFoundException * @throws ReflectionException * @throws DbException * @throws ModelNotFoundException * @throws DataNotFoundException */ 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('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, '更新任务状态失败'); } } /** * 完成品牌任务后领取加票机会接口 * @return mixed * @throws FuncNotFoundException * @throws ClassNotFoundException * @throws ReflectionException * @throws DbException * @throws ModelNotFoundException * @throws DataNotFoundException */ 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('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, '更新任务状态失败'); } } /** * 用户完成端外分享时调用接口加票 * @return mixed * @throws FuncNotFoundException * @throws ClassNotFoundException * @throws ReflectionException * @throws DbException * @throws ModelNotFoundException * @throws DataNotFoundException */ 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('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, '更新任务状态失败'); } } /** * 标记用户已经浏览过主页了,用户点了去浏览时调用 * @return mixed * @throws FuncNotFoundException * @throws ClassNotFoundException * @throws ReflectionException * @throws DbException * @throws ModelNotFoundException * @throws DataNotFoundException */ 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('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, '更新任务状态失败'); } } /** * 获取品牌任务redis 缓存键 * @param int $uid * @return string */ protected function getTaskStateRedisKey(int $uid): string { $dateForRedis = date('Ymd'); return "t:{$dateForRedis}:" . $uid; } /** * 获取品牌任务配置及状态 * @return \think\response\Json|array * @throws FuncNotFoundException * @throws ReflectionException * @throws InvalidArgumentException * @throws ClassNotFoundException * @throws DbException * @throws ModelNotFoundException * @throws DataNotFoundException */ protected function getBrandConfigAndState() { $config = SystemService::instance()->getData('brand:task:config'); $date = date('Y-m-d'); $dateForRedis = date('Ymd'); $redisKey = "t:{$dateForRedis}:" . Safe::$user['uid']; $state = Cache::get($redisKey); if (empty($state)) { // 缓存失败 查数据库 $state = Db::table('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('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('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('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, ]; } /** * @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); } }