| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602 |
- <?php
- namespace Modules\Web\Controllers;
- use App\Constants\CreatorConstant;
- use App\Jobs\SavePcVideoCoverCebJob;
- use App\Model\TypeModel;
- use App\Model\TypeVideoModel;
- use App\Model\VideoModel;
- use App\Repositories\ConfigRepoistory;
- use App\Repositories\CreatorRepository;
- use App\Repositories\CreatorRuleRepository;
- use App\Repositories\UserRepository;
- use App\Repositories\Utils\MediaCenterRepository;
- use App\Repositories\VideoRepository;
- use Carbon\Carbon;
- use Hyperf\Validation\Contract\ValidatorFactoryInterface;
- use Modules\Web\Services\AuthService;
- use Psr\SimpleCache\CacheInterface;
- class PcController extends BaseController
- {
- /**
- * 签名token/key
- * @var string
- */
- private $signToken = 'uwgnnDtzTZR1xzoW';
- /**
- * @var null|AuthService
- */
- private $authService = null;
- /**
- * @var null|UserRepository
- */
- private $userRepo = null;
- /**
- * @var null|CacheInterface
- */
- private $cacheRepo = null;
- public function index()
- {
- return 'pc-ok-pong';
- }
- /**
- * 轮询登陆是否成功.
- * @return mixed
- * @throws \Psr\SimpleCache\InvalidArgumentException
- */
- public function lookup()
- {
- $qrcodeContent = trim(request()->input('qc', ''));
- $qrFrom = request()->input('from', 'web');
- $qrInfo = $this->getUserCodeByQrCode($qrcodeContent);
- if (!empty($qrInfo['err_msg'])) {
- return $this->jsonFail($qrInfo['err_msg'], 5001);
- }
- $realUserCode = '';
- $userCode = $qrInfo['user_code'];
- $userInfo = $this->getAuthInfo();
- if (!empty($userInfo['code'])) {
- return $this->jsonFail('授权无效1', 5002);
- }
- if ($userInfo['code'] !== $userCode) {
- return $this->jsonFail('授权非法1', 5003);
- }
- $status = 2; // 状态,1=拿到token,2=未拿到,未登陆状态
- $cacheKey = $this->getAuthService()->getUserCacheKey($userCode);
- $token = $this->getCacheRepo()->get($cacheKey, '');
- if (empty($token)) {
- $status = 1;
- } else {
- $realUserCode = $userCode;
- }
- $result = [
- 'status' => $status,
- 'token' => $token,
- 'user_code' => $realUserCode,
- ];
- return $this->jsonSuccess($result);
- }
- /**
- * 检查是否合法登陆
- * @return mixed
- */
- public function checkLogin()
- {
- $userInfo = $this->getAuthInfo();
- if (empty($userInfo['code'])) {
- return $this->jsonFail('授权无效', 5091);
- }
- $result = [
- 'is_success' => true,
- ];
- return $this->jsonSuccess($result);
- }
- public function setting()
- {
- $userInfo = $this->getAuthInfo();
- if (empty($userInfo['code'])) {
- return $this->jsonFail('授权无效', 5091);
- }
- $userCode = $userInfo['code'];
- $configRepo = make(ConfigRepoistory::class);
- $creatorRepo = make(CreatorRepository::class);
- $ruleRepo = make(CreatorRuleRepository::class);
- $detail = $creatorRepo->detail($userCode);
- $todayCanUpload = false;
- $level = 0;
- $dayAddonNum = 0;
- $dayVideo = 0;
- if (!empty($detail)) {
- $level = intval($detail->level);
- $dayAddonNum = intval($detail->day_addon_num);
- $dayVideo = intval($detail->day_video);
- }
- $ruleLevel = $ruleRepo->getRuleByLevel($level);
- $dayMaxVideo = intval($ruleLevel->day_max_video) + $dayAddonNum;
- $todayVideo = !empty($detail) ? $dayVideo : 0;
- if ($todayVideo < $dayMaxVideo) {
- $todayCanUpload = true;
- }
- $fileMaxSizeMb = CreatorConstant::VIDEO_MAX_SIZE_MB; // 文件最大多少MB
- $maxCoin = CreatorConstant::VIDEO_SELL_MAX_COIN; // 最多设置金币个数
- $creatorMinVideoNum = CreatorConstant::FREE_VIDEO_NUM; // 创作者,level>0
- $normalMinVideoNum = CreatorConstant::LEVEL_0_FREE_VIDEO_NUM; // 普通人, level=0
- $maxTagNum = CreatorConstant::VIDEO_TAG_MAX_NUM; // 最多选择标签个数.
- $tags = $creatorRepo->canUseTags();
- $ppvodParams = $configRepo->gets(['ppvod_upload_category', 'ppvod_upload_tpl_id', 'ppvod_upload_tpl_name'], 'sys', []);
- $isCanUploadCoin = isset($detail->coin_uper) ? boolval($detail->coin_uper) : false; // 是否能传收费视频
- $needUploadFreeNum = 0; // 还需要上传免费视频个数.
- $countFreeVideos = $creatorRepo->countPublishedCoinVideo($userCode, true); // 统计免费视频个数
- $countNotFreeVideos = $creatorRepo->countPublishedCoinVideo($userCode, false); //统计收费视频个数
- if ($level <= 0) {
- if (CreatorConstant::LEVEL_0_FREE_VIDEO_NUM > 0) {
- // 金币视频 x 免费要求 = 最低历史上传免费个数
- $leastFreeNum = $countNotFreeVideos > 0 ? $countNotFreeVideos * CreatorConstant::LEVEL_0_FREE_VIDEO_NUM : CreatorConstant::LEVEL_0_FREE_VIDEO_NUM;
- if ($countFreeVideos >= $leastFreeNum) {
- $isCanUploadCoin = true;
- } else {
- $needUploadFreeNum = $leastFreeNum - $countFreeVideos;
- }
- } else {
- $isCanUploadCoin = true;
- }
- } else {
- if (CreatorConstant::FREE_VIDEO_NUM > 0) {
- // 金币视频 x 免费要求 = 最低限制上传免费个数
- $leastFreeNum = $countNotFreeVideos > 0 ? $countNotFreeVideos * CreatorConstant::FREE_VIDEO_NUM : CreatorConstant::FREE_VIDEO_NUM;
- if ($countFreeVideos >= $leastFreeNum) {
- $isCanUploadCoin = true;
- } else {
- $needUploadFreeNum = $leastFreeNum - $countFreeVideos;
- }
- } else {
- $isCanUploadCoin = true;
- }
- }
- $uploadIsMaintenance = false;
- $uploadMaintenanceDesc = '';
- $arrConfig = $configRepo->gets(['upload_maintenance_status', 'upload_maintenance_desc'], 'sys', []);
- if (isset($arrConfig['upload_maintenance_status']) && intval($arrConfig['upload_maintenance_status']) == 1) {
- $uploadIsMaintenance = true;
- $uploadMaintenanceDesc = $arrConfig['upload_maintenance_desc'] ?? '上传维护中,请稍后恢复再试';
- }
- $result = [
- 'user_id' => $userInfo['code'],
- 'nick' => $userInfo['nick'],
- 'level' => $level,
- 'today_can_upload' => $todayCanUpload,
- 'file_max_size_mb' => $fileMaxSizeMb,
- 'max_coin' => $maxCoin,
- 'creator_min_video_num' => $creatorMinVideoNum,
- 'normal_min_video_num' => $normalMinVideoNum,
- 'max_tag_num' => $maxTagNum,
- 'tags' => $tags,
- 'is_can_upload_coin' => $isCanUploadCoin,
- 'need_upload_free_num' => $needUploadFreeNum,
- 'count_free_videos' => $countFreeVideos,
- 'count_not_free_videos' => $countNotFreeVideos,
- 'upload_category' => !empty($ppvodParams['ppvod_upload_category']) ? $ppvodParams['ppvod_upload_category'] : '用户上传',
- 'upload_tpl_id' => !empty($ppvodParams['ppvod_upload_tpl_id']) ? $ppvodParams['ppvod_upload_tpl_id'] : '',
- 'upload_tpl_name' => !empty($ppvodParams['ppvod_upload_tpl_name']) ? $ppvodParams['ppvod_upload_tpl_name'] : '默认',
- 'upload_is_maintenance' => $uploadIsMaintenance,
- 'upload_maintenance_desc' => $uploadMaintenanceDesc,
- ];
- return $this->jsonSuccess($result);
- }
- public function createVideo()
- {
- $userInfo = $this->getAuthInfo();
- if (empty($userInfo['code'])) {
- return $this->jsonFail('授权无效', 5091);
- }
- $userCode = $userInfo['code'];
- $validatorFactory = make(ValidatorFactoryInterface::class);
- $inputData = request()->all();
- $rules = [
- 'title' => 'required',
- 'cover' => 'nullable|max:700',
- 'coins' => 'required|int',
- 'tags' => 'required', // 这个是ID
- 'file_hash' => 'required'
- ];
- $validator = $validatorFactory->make($inputData, $rules);
- if ($validator->fails()) {
- // 如果有错误(可能是多个信息),这里只取第一个错误信息返回.
- return json_fail($validator->errors()->first());
- }
- $videoRepo = make(VideoRepository::class);
- if ($videoRepo->checkExist($inputData['file_hash'])) {
- return $this->jsonFail('此视频已被其他人上传过,请重新更换', 6444);
- }
- $mediaCenterRepo = make(MediaCenterRepository::class);
- $hashVideoInfo = $mediaCenterRepo->getHashInfo($inputData['file_hash']);
- if (!empty($hashVideoInfo)) {
- return $this->jsonFail('此视频有人上传过了,请重新更换', 6444);
- }
- $ruleRepo = make(CreatorRuleRepository::class);
- $creatorRepo = make(CreatorRepository::class);
- $detail = $creatorRepo->detail($userCode);
- $level = 0;
- $dayAddonNum = 0;
- $dayVideo = 0;
- if (!empty($detail)) {
- $level = intval($detail->level);
- $dayAddonNum = intval($detail->day_addon_num);
- $dayVideo = intval($detail->day_video);
- } else {
- // 自动申请为原创者.
- $detail = $creatorRepo->applyToUncheck($userCode);
- $level = intval($detail->level);
- }
- $ruleLevel = $ruleRepo->getRuleByLevel($level);
- $dayMaxVideo = intval($ruleLevel->day_max_video) + $dayAddonNum;
- $todayVideo = !empty($detail) ? $dayVideo : 0;
- if ($todayVideo >= $dayMaxVideo) {
- return $this->jsonFail('今日已经超出上传数量限制');
- }
- $cover = trim(data_get($inputData, 'cover', ''));
- $cover = substr($cover, 0, 255);
- $coins = intval(data_get($inputData, 'coins', 0)); // 金币,单位数量个,10金币=1元人民币
- $uploadingUrl = ''; // TODO,这里可以做一个固定视频,等待用户上传转码中.
- if ($coins < 0) {
- $coins = 0;
- }
- if ($coins > CreatorConstant::VIDEO_SELL_MAX_COIN) {
- return $this->jsonFail('售卖金币价格太大,可以提前联系客服');
- }
- $arrTagIds = [];
- $tmpTagIds = data_get($inputData, 'tags', '');
- if (is_string($tmpTagIds)) {
- $arrTagIds = explode(',', $tmpTagIds);
- } else {
- $arrTagIds = $tmpTagIds;
- }
- if (!empty($arrTagIds)) {
- $arrTagIds = array_filter($arrTagIds);
- $arrTagIds = array_unique($arrTagIds);
- }
- if (empty($arrTagIds)) {
- return $this->jsonFail('请选择至少1个口味');
- }
- if (count($arrTagIds) > CreatorConstant::VIDEO_TAG_MAX_NUM) {
- return $this->jsonFail('最多选择'. strval(CreatorConstant::VIDEO_TAG_MAX_NUM) .'个口味');
- }
- // 处理关联标签.
- $tagIdsRaltion = [];
- $tagNames = [];
- if (!empty($arrTagIds)) {
- foreach ($arrTagIds as $v) {
- $tagObj = TypeModel::query()->where('id', $v)->first();
- if (!empty($tagObj->id)) {
- $tagIdsRaltion[] = $tagObj->id;
- $tagNames[] = $tagObj->title;
- }
- }
- }
- $isCanUploadCoin = isset($detail->coin_uper) ? boolval($detail->coin_uper) : false; // 是否能传收费视频
- $needUploadFreeNum = 0; // 还需要上传免费视频个数.
- $countFreeVideos = $creatorRepo->countPublishedCoinVideo($userCode, true); // 统计免费视频个数
- $countNotFreeVideos = $creatorRepo->countPublishedCoinVideo($userCode, false); //统计收费视频个数
- if ($level <= 0) {
- if (CreatorConstant::LEVEL_0_FREE_VIDEO_NUM > 0) {
- // 金币视频 x 免费要求 = 最低历史上传免费个数
- $leastFreeNum = $countNotFreeVideos > 0 ? $countNotFreeVideos * CreatorConstant::LEVEL_0_FREE_VIDEO_NUM : CreatorConstant::LEVEL_0_FREE_VIDEO_NUM;
- if ($countFreeVideos >= $leastFreeNum) {
- $isCanUploadCoin = true;
- } else {
- $needUploadFreeNum = $leastFreeNum - $countFreeVideos;
- }
- } else {
- $isCanUploadCoin = true;
- }
- } else {
- if (CreatorConstant::FREE_VIDEO_NUM > 0) {
- // 金币视频 x 免费要求 = 最低限制上传免费个数
- $leastFreeNum = $countNotFreeVideos > 0 ? $countNotFreeVideos * CreatorConstant::FREE_VIDEO_NUM : CreatorConstant::FREE_VIDEO_NUM;
- if ($countFreeVideos >= $leastFreeNum) {
- $isCanUploadCoin = true;
- } else {
- $needUploadFreeNum = $leastFreeNum - $countFreeVideos;
- }
- } else {
- $isCanUploadCoin = true;
- }
- }
- if ($coins > 0 && !$isCanUploadCoin) {
- return $this->jsonFail('还不能上传收费视频,请先再传'. strval($needUploadFreeNum) . '个免费视频');
- }
- $payType = 2; // 默认金币
- if ($coins == 0) {
- $payType = 1; // vip
- }
- $newStrTagNames = !empty($tagNames) ? implode(',', $tagNames) : '';
- $newStrTagIds = !empty($arrTagIds) ? implode(',', $arrTagIds) : '';
- $title = trim(data_get($inputData, 'title', ''));
- $title = mb_substr($title, 0, 24);
- $fileHash = trim(data_get($inputData, 'file_hash', ''));
- $fileHash = substr($fileHash, 0, 32);
- $setarr = [
- 'uid' => $userCode,
- 'status' => 3,
- 'check' => 0,
- 'pay_type' => $payType,
- 'type' => 1,
- 'mu' => $uploadingUrl,
- 'title' => $title,
- 'cover' => $cover,
- 'coins' => $coins,
- 'tags' => $newStrTagNames,
- 'file_hash' => $fileHash,
- 'custom_cover' => $cover, // 用户自定义封面.
- ];
- $videoObj = VideoModel::query()->create($setarr);
- if ($videoObj) {
- $videoId = $videoObj->id;
- if (!empty($tagIdsRaltion)) {
- foreach ($tagIdsRaltion as $tagId) {
- $setarr2 = [
- 'type_id' => $tagId,
- 'video_id' => $videoId,
- 'status' => 1,
- ];
- TypeVideoModel::query()->create($setarr2);
- }
- }
- // 累加今日上传视频数量.
- $detail->day_video++;
- $detail->save();
- if (!empty($cover)) {
- $coverFileName = basename($cover);
- $coverExt = $this->fileExt($coverFileName);
- if ($coverExt != 'ceb' && in_array($coverExt, ['jpg', 'jpeg', 'png', 'gif'])) {
- $jobParams = [
- 'video_id' => $videoId,
- 'cover' => $cover,
- ];
- dispatch_job(new SavePcVideoCoverCebJob($jobParams));
- }
- }
- } else {
- return $this->jsonFail('创建视频失败');
- }
- $result = [
- 'video' => [
- 'id' => $videoObj->id, // 给前端的。前端拿到这个, 拼接 app应用全称(媒资库里定义的)| 模块名 | 视频ID ,doukui|video|video_id
- // 'title' => $setarr['title'],
- // 'coins' => $setarr['coins'],
- // 'cover' => '', // 这里ppvod的是暴露的jpg路径,不能用,直接访问空字符串
- // 'tag_names' => $newStrTagNames,
- // 'tag_ids' => $newStrTagIds,
- ],
- ];
- return $this->jsonSuccess($result);
- }
- /**
- * 二维码登陆
- * @return mixed
- * @throws \Psr\SimpleCache\InvalidArgumentException
- */
- public function qrcodeLogin()
- {
- $qrcodeContent = trim(request()->input('qc', ''));
- $qrFrom = request()->input('from', 'web');
- $qrInfo = $this->getUserCodeByQrCode($qrcodeContent);
- if (!empty($qrInfo['err_msg'])) {
- return $this->jsonFail($qrInfo['err_msg']);
- }
- $userCode = $qrInfo['user_code'];
- // $cacheKey = $this->getAuthService()->getUserCacheKey($userCode);
- // $token = $this->getCacheRepo()->get($cacheKey);
- $tokenInfo = $this->getAuthService()->createSingleJwt($userCode);
- $token = $tokenInfo['token'];
- $result = [
- 'token' => $token,
- 'user_code' => $userCode,
- ];
- return $this->jsonSuccess($result);
- }
- public function upAuth()
- {
- $userInfo = $this->getAuthInfo();
- if (empty($userInfo['code'])) {
- logger('upAuth', ['msg' => '[4]握手失败']);
- return response('[4]握手失败', 500);
- }
- $queryUserCode = $userInfo['code'];
- $inputData = request()->all();
- $rules = [
- 'auth_event' => 'required',
- 'auth_timestamp' => 'required',
- 'app_name' => 'required',
- 'auth_user' => 'required',
- 'auth_sign' => 'required|string',
- 'file_hash' => 'nullable',
- 'file_origin_name' => 'nullable',
- 'file_ext' => 'nullable',
- ];
- $validator = make(ValidatorFactoryInterface::class)
- ->make($inputData, $rules);
- if ($validator->fails()) {
- // 如果有错误(可能是多个信息),这里只取第一个错误信息返回.
- logger('upAuth', ['msg' => $validator->errors()->first()]);
- return response($validator->errors()->first(), 500);
- }
- $authTimestamp = strval(data_get($inputData, 'auth_timestamp', ''));
- $appName = data_get($inputData, 'app_name', '');
- $authUserCode = data_get($inputData, 'auth_user', '');
- $authSign = data_get($inputData, 'auth_sign', '');
- $authEvent = data_get($inputData, 'auth_event', '');
- $fileOriginName = data_get($inputData, 'file_origin_name', '');
- $fileHash = data_get($inputData, 'file_hash', '');
- $fileExt = strtolower(data_get($inputData, 'file_ext', ''));
- $tmpTimestamp = substr($authTimestamp, 0, 10);
- if (abs(Carbon::createFromTimestamp($tmpTimestamp)->diffInMinutes(Carbon::now())) > 30) {
- logger('upAuth', ['msg' => '[5]握手失败']);
- return response('[5]握手失败', 500);
- }
- $inSign = $this->createSign($authTimestamp, $appName, $authUserCode, $authEvent);
- if ($inSign !== $authSign) {
- logger('upAuth', ['msg' => '[3]握手失败']);
- return response('[3]握手失败', 500);
- }
- if (empty($queryUserCode) || $queryUserCode !== $authUserCode) {
- logger('upAuth', ['msg' => '[6]握手失败']);
- return response('[6]握手失败', 500);
- }
- return response('success', 200);
- }
- /**
- * 获取认证里的用户信息.
- * @return array
- */
- private function getAuthInfo()
- {
- $authInfo = $this->getAuthService()->getTokenUserInfo();
- if (empty($authInfo['user_id'])) {
- return [];
- }
- $userInfo = $this->getAuthService()->checkValid($authInfo['user_id']);
- if (empty($userInfo)) {
- return [];
- }
- $userInfo['user_id'] = $userInfo['code']; // 兼容.
- return $userInfo;
- }
- /**
- * 获取服务.
- * @return mixed|AuthService
- */
- private function getAuthService()
- {
- if (!$this->authService instanceof AuthService) {
- $this->authService = make(AuthService::class);
- }
- return $this->authService;
- }
- /**
- * 获取用户仓库.
- * @return UserRepository|mixed
- */
- private function getUserRepo()
- {
- if (!$this->userRepo instanceof UserRepository) {
- $this->userRepo = make(UserRepository::class);
- }
- return $this->userRepo;
- }
- /**
- * 获取缓存仓库.
- * @return mixed|CacheInterface
- */
- private function getCacheRepo()
- {
- if (!$this->cacheRepo instanceof CacheInterface) {
- $this->cacheRepo = make(CacheInterface::class);
- }
- return $this->cacheRepo;
- }
- /**
- * 通过二维码内容获取用户code.
- * @param $qrcodeContent
- * @return string[]
- */
- private function getUserCodeByQrCode($qrcodeContent)
- {
- $result = [
- 'err_msg' => '',
- 'user_code' => '',
- ];
- if (empty($qrcodeContent)) {
- $result['err_msg'] = '无效的二维码1';
- return $result;
- }
- $txt = $qrcodeContent;
- if (empty($txt)) {
- $result['err_msg'] = '无效的二维码2';
- return $result;
- }
- $account = hand_decrypt($txt, $this->getUserRepo()->getAcKey(), $this->getUserRepo()->getAcIv());
- if (empty($account)) {
- $result['err_msg'] = '无效的二维码3';
- return $result;
- }
- $pattern = '/^user:\/\/([a-zA-Z0-9]{6,12})/';
- preg_match($pattern, $account, $matches);
- if (empty($matches[1])) {
- $result['err_msg'] = '无效的二维码4';
- return $result;
- }
- $userCode = $matches[1];
- $userInfo = $this->getUserRepo()->getUserInfoFromCache($userCode);
- if (empty($userInfo['code'])) {
- $result['err_msg'] = '无效的二维码5';
- return $result;
- }
- $result['user_code'] = $userCode;
- return $result;
- }
- /**
- * @param $timestamp
- * @param $appName
- * @param $userCode
- * @return string
- */
- private function createSign($timestamp, $appName, $userCode, $authEvent)
- {
- $strParams = $appName . '-' . $authEvent . '-' . $userCode. '-'. $timestamp;
- $strSign = md5(md5($strParams) . '-'. $this->signToken);
- return $strSign;
- }
- private function fileExt($filename) {
- return strtolower(trim(substr(strrchr($filename, '.'), 1)));
- }
- }
|