Live.php 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
  4. // +----------------------------------------------------------------------
  5. // | Copyright (c) 2016~2022 https://www.crmeb.com All rights reserved.
  6. // +----------------------------------------------------------------------
  7. // | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
  8. // +----------------------------------------------------------------------
  9. // | Author: CRMEB Team <admin@crmeb.com>
  10. // +----------------------------------------------------------------------
  11. namespace app\wap\controller;
  12. use Api\AliyunLive as ApiAliyunLive;
  13. use app\wap\model\live\LiveBarrage;
  14. use app\wap\model\live\LiveGoods;
  15. use app\wap\model\live\LiveHonouredGuest;
  16. use app\wap\model\live\LiveReward;
  17. use app\wap\model\live\LiveStudio;
  18. use app\wap\model\live\LivePlayback;
  19. use app\wap\model\live\LiveUser;
  20. use app\wap\model\live\LiveGift;
  21. use app\wap\model\special\SpecialBuy;
  22. use app\wap\model\special\Special;
  23. use app\wap\model\special\SpecialTask;
  24. use app\wap\model\special\SpecialContent;
  25. use app\wap\model\user\User;
  26. use app\wap\model\user\UserBill;
  27. use service\SystemConfigService;
  28. use service\UtilService;
  29. use think\Config;
  30. use service\JsonService;
  31. use think\Cookie;
  32. use think\Db;
  33. use think\Session;
  34. use think\Url;
  35. /**直播间控制器
  36. * Class Live
  37. * @package app\wap\controller
  38. */
  39. class Live extends AuthController
  40. {
  41. /*
  42. * 白名单
  43. * */
  44. public static function WhiteList()
  45. {
  46. return [
  47. 'get_live_record_list',
  48. ];
  49. }
  50. /**
  51. * 阿里云直播句柄
  52. * @var \Api\AliyunLive
  53. */
  54. protected $aliyunLive;
  55. protected function _initialize()
  56. {
  57. parent::_initialize();
  58. $this->aliyunLive = ApiAliyunLive::instance([
  59. 'AccessKey' => SystemConfigService::get('accessKeyId'),
  60. 'AccessKeySecret' => SystemConfigService::get('accessKeySecret'),
  61. 'OssEndpoint' => SystemConfigService::get('aliyun_live_end_point'),
  62. 'OssBucket' => SystemConfigService::get('aliyun_live_oss_bucket'),
  63. 'appName' => SystemConfigService::get('aliyun_live_appName'),
  64. 'payKey' => SystemConfigService::get('aliyun_live_play_key'),
  65. 'key' => SystemConfigService::get('aliyun_live_push_key'),
  66. 'playLike' => SystemConfigService::get('aliyun_live_playLike'),
  67. 'rtmpLink' => SystemConfigService::get('aliyun_live_rtmpLink'),
  68. ]);
  69. }
  70. /**
  71. * 直播间主页
  72. * @param string $stream_name
  73. * @return mixed|void
  74. * @throws \think\Exception
  75. * @throws \think\db\exception\DataNotFoundException
  76. * @throws \think\db\exception\ModelNotFoundException
  77. * @throws \think\exception\DbException
  78. */
  79. public function index($stream_name = '', $special_id = 0, $live_id = 0, $record_id = 0)
  80. {
  81. if ($special_id && $special_id != 0 && $live_id && $live_id != 0) {
  82. $special_task = SpecialTask::where(['special_id' => $special_id, 'live_id' => $live_id])->value('live_id');
  83. if (!$special_task) {
  84. $this->failed('直播间不存在', Url::build('index/index'));
  85. }
  86. $stream_name = LiveStudio::where('id', $live_id)->value('stream_name');
  87. }
  88. if (!$stream_name) return $this->failed('缺少在直播间号!', Url::build('index/index'));
  89. $liveInfo = LiveStudio::where('stream_name', $stream_name)->find();
  90. if (!$liveInfo) return $this->failed('直播间不存在', Url::build('index/index'));
  91. if ($liveInfo->is_del) return $this->failed('直播间已被删除', Url::build('index/index'));
  92. $userInfo = LiveUser::setLiveUser($this->uid, $liveInfo->id);
  93. if ($userInfo === false) return $this->failed(LiveUser::getErrorInfo('用户写入不成功'), Url::build('index/index'));
  94. $specialLive = Special::PreWhere()->where(['id' => $liveInfo->special_id])->find();
  95. if (!$specialLive) return $this->failed('专题不存在或者已被删除', Url::build('index/index'));
  96. $user_level = !$this->uid ? 0 : $this->userInfo;
  97. if ($specialLive->pay_type == 1 && !SpecialBuy::PaySpecial($specialLive->id, $this->uid)) {
  98. if ($specialLive->member_pay_type == 1 || ($user_level['level'] <= 0 && $specialLive->member_pay_type == 0)) {
  99. return $this->failed('您还没有支付请支付后再进行观看', Url::build('special/details', ['id' => $liveInfo->special_id]));
  100. }
  101. }
  102. if ($specialLive->pay_type == 2) {
  103. $cookie_value = Cookie::get($stream_name . "studio_pwd");
  104. if (!$cookie_value || $cookie_value != $liveInfo['studio_pwd']) {
  105. return $this->failed('您需要先获得密码后再进行观看', Url::build('special/details', ['id' => $liveInfo->special_id]));
  106. }
  107. }
  108. $AliyunLive = $this->aliyunLive;
  109. if ($liveInfo->is_play)
  110. $PullUrl = $AliyunLive->getPullSteam($liveInfo->stream_name);
  111. else {
  112. $record_id = $record_id ? $record_id : $liveInfo->playback_record_id;
  113. if ($liveInfo->is_playback && $record_id) {
  114. $livePlayBack = LivePlayback::where(['RecordId' => $record_id, 'stream_name' => $liveInfo->stream_name])->find();
  115. $PullUrl = $livePlayBack ? $livePlayBack->playback_url : false;
  116. } else
  117. $PullUrl = false;
  118. }
  119. $live_status = 0;
  120. $datatime = strtotime($liveInfo->start_play_time);
  121. $endTime = strtotime($liveInfo->stop_play_time);
  122. if ($datatime < time() && $endTime > time())
  123. $live_status = 1;//正在直播
  124. else if ($datatime < time() && $endTime < time())
  125. $live_status = 2;//直播结束
  126. else if ($datatime > time())
  127. $live_status = 0;//尚未直播
  128. $user_type = LiveHonouredGuest::where(['uid' => $this->uid, 'live_id' => $liveInfo->id])->value('type');
  129. if (is_null($user_type)) $user_type = 2;
  130. $uids = LiveHonouredGuest::where(['live_id' => $liveInfo->id])->column('uid');
  131. $liveInfo['abstract'] = $specialLive->abstract;
  132. $content = SpecialContent::where(['special_id'=>$specialLive->id])->value('content');
  133. $liveInfo['content'] = htmlspecialchars_decode($content);
  134. $this->assign([
  135. 'goldInfo' => json_encode(SystemConfigService::more("gold_name,gold_rate,gold_image")),
  136. 'liveInfo' => json_encode($liveInfo),
  137. 'UserSum' => bcadd(LiveUser::where(['live_id' => $liveInfo->id, 'is_open_ben' => 0, 'is_online' => 1])->sum('visit_num'), $liveInfo->online_num, 0),
  138. 'live_title' => $liveInfo->live_title,
  139. 'PullUrl' => $PullUrl,
  140. 'is_ban' => $userInfo->is_ban,
  141. 'room' => $liveInfo->id,
  142. 'datatime' => $datatime,
  143. 'workerman' => json_encode(Config::get('workerman.chat', [])),
  144. 'phone_type' => UtilService::getDeviceType(),
  145. 'live_status' => $live_status,
  146. 'user_type' => $user_type,
  147. 'OpenCommentCount' => LiveBarrage::where(['live_id' => $liveInfo->id, 'is_show' => 1])->count(),
  148. 'OpenCommentTime' => LiveBarrage::where(['live_id' => $liveInfo->id, 'is_show' => 1])->order('add_time asc')->value('add_time'),
  149. 'CommentCount' => LiveBarrage::where(['live_id' => $liveInfo->id, 'is_show' => 1])->where('uid', 'in', $uids)->count(),
  150. 'CommentTime' => LiveBarrage::where(['live_id' => $liveInfo->id, 'is_show' => 1])->where('uid', 'in', $uids)->order('add_time asc')->value('add_time'),
  151. ]);
  152. return $this->fetch();
  153. }
  154. /**
  155. * 获取助教评论
  156. */
  157. public function get_comment_list()
  158. {
  159. list($page, $limit, $live_id, $add_time) = UtilService::getMore([
  160. ['page', 0],
  161. ['limit', 20],
  162. ['live_id', 0],
  163. ['add_time', 0],
  164. ], $this->request, true);
  165. if (!$live_id) return JsonService::fail('缺少参数!');
  166. $uids = LiveHonouredGuest::where(['live_id' => $live_id])->column('uid');
  167. if (!$uids) {
  168. $ystemConfig = SystemConfigService::more(['site_name', 'home_logo']);
  169. $data = [
  170. 'nickname' => $ystemConfig['site_name'],
  171. 'avatar' => $ystemConfig['home_logo'],
  172. 'user_type' => 2,
  173. 'content' => LiveStudio::where('id', $live_id)->value('auto_phrase'),
  174. 'id' => 0,
  175. 'type' => 1,
  176. 'uid' => 0
  177. ];
  178. return JsonService::successful(['list' => [$data], 'page' => 0]);
  179. }
  180. return JsonService::successful(LiveBarrage::getCommentList($uids, $live_id, $page, $limit, $add_time));
  181. }
  182. /**
  183. * 获取助教,讲师,普通人的评论
  184. */
  185. public function get_open_comment_list()
  186. {
  187. list($page, $limit, $live_id, $add_time) = UtilService::getMore([
  188. ['page', 0],
  189. ['limit', 20],
  190. ['live_id', 0],
  191. ['add_time', 0],
  192. ], $this->request, true);
  193. if (!$live_id) return JsonService::fail('缺少参数!');
  194. return JsonService::successful(LiveBarrage::getCommentList(false, $live_id, $page, $limit, $add_time));
  195. }
  196. /**
  197. * 获取直播间下的录制内容
  198. * @param string $record_id
  199. * @param string $stream_name
  200. * @param string $start_time
  201. * @param string $end_time
  202. * @param int $page
  203. * @param int $limit
  204. */
  205. public function get_live_record_list($special_id = '', $start_time = '', $end_time = '', $page = 1, $limit = 10)
  206. {
  207. if (!$special_id) return JsonService::fail('参数缺失');
  208. $specialInfo = Special::get($special_id);
  209. if (!$specialInfo) return JsonService::fail('直播专题不存在');
  210. $liveStudio = LiveStudio::where(['special_id' => $specialInfo['id']])->find();
  211. if (!$liveStudio) return JsonService::fail('缺少直播间');
  212. if (!$liveStudio['stream_name']) return JsonService::fail('缺少直播间id');
  213. $data = [];
  214. $count = 0;
  215. $data = compact('data', 'count');
  216. if ($liveStudio['is_playback'] == 1) {
  217. $where['stream_name'] = $liveStudio['stream_name'];
  218. $where['page'] = $page;
  219. $where['limit'] = $limit;
  220. $where['start_time'] = $start_time;
  221. $where['end_time'] = $end_time;
  222. $data = LivePlayback::getLivePlaybackList($where);
  223. }
  224. $data['page'] = $page++;
  225. return JsonService::successful($data);
  226. }
  227. /**
  228. * 获取直播间下的录制内容
  229. * @param string $record_id
  230. * @param string $stream_name
  231. * @param string $start_time
  232. * @param string $end_time
  233. * @param int $page
  234. * @param int $limit
  235. */
  236. public function get_live_record_list1($special_id = '', $start_time = '', $end_time = '', $page = 1, $limit = 10)
  237. {
  238. if (!$special_id) return JsonService::fail('参数缺失');
  239. $specialInfo = Special::get($special_id);
  240. if (!$specialInfo) return JsonService::fail('直播专题不存在');
  241. $liveStudio = LiveStudio::where(['special_id' => $specialInfo['id']])->find();
  242. if (!$liveStudio) return JsonService::fail('缺少直播间');
  243. if (!$liveStudio['stream_name']) return JsonService::fail('缺少直播间id');
  244. $aliyunLive = $this->aliyunLive;
  245. $beginToday = mktime(0, 0, 0, date('m'), date('d') - 3, date('Y'));
  246. if ($start_time && $end_time) {
  247. $start_time = strtotime($start_time);
  248. $end_time = strtotime($end_time);
  249. if ($start_time > $end_time) return JsonService::fail('开始时间不能大于结束时间');
  250. $time = bcsub($end_time, $start_time, 0) / 86400;
  251. if ($time > 4) return JsonService::fail('开始和结束的时间不能间隔4天');
  252. }
  253. $res = $aliyunLive->queryLiveRecordFiles(
  254. $liveStudio['stream_name'],
  255. $start_time ? ApiAliyunLive::setTimeFormat($start_time) : ApiAliyunLive::setTimeFormat($beginToday),
  256. $end_time ? ApiAliyunLive::setTimeFormat($end_time) : ApiAliyunLive::setTimeFormat(time()),
  257. $page,
  258. $limit
  259. );
  260. $data = [];
  261. $count = 0;
  262. if ($res) {
  263. if (isset($res['RecordIndexInfoList']['RecordIndexInfo'])) {
  264. foreach ($res['RecordIndexInfoList']['RecordIndexInfo'] as $item) {
  265. $data['list'][] = [
  266. 'StreamName' => $item['StreamName'],
  267. 'RecordId' => $item['RecordId'],
  268. 'playback_record_id' => $liveStudio['playback_record_id'],
  269. 'RecordUrl' => $item['RecordUrl'],
  270. 'StartTime' => $item['StartTime'],
  271. 'EndTime' => $item['EndTime'],
  272. ];
  273. }
  274. }
  275. if (isset($res['TotalNum'])) $count = $res['TotalNum'];
  276. $data['page'] = $page++;
  277. $data['count'] = $count;
  278. return JsonService::successful($data);
  279. } else {
  280. return JsonService::fail("网络错误");
  281. }
  282. }
  283. /**
  284. * 打赏礼物列表
  285. */
  286. public function live_gift_list()
  287. {
  288. $live_gift = LiveGift::liveGiftList();
  289. return JsonService::successful($live_gift);
  290. }
  291. /**打赏接口
  292. * @throws \think\Exception
  293. * @throws \think\db\exception\DataNotFoundException
  294. * @throws \think\db\exception\ModelNotFoundException
  295. * @throws \think\exception\DbException
  296. */
  297. public function live_reward()
  298. {
  299. list($uid, $live_gift_id, $live_gift_num, $stream_name, $special_id) = UtilService::postMore([
  300. ['uid', 0],
  301. ['live_gift_id', 0],
  302. ['live_gift_num', 0],
  303. ['stream_name', 0],
  304. ['special_id', 0],
  305. ], $this->request, true);
  306. if (!$uid) return JsonService::fail('用户id缺失');
  307. if (!$live_gift_id || !is_numeric($live_gift_id)) return JsonService::fail('礼物id缺失');
  308. if (!$stream_name || !is_numeric($stream_name)) return JsonService::fail('直播间号缺失');
  309. if (!$special_id || !is_numeric($special_id)) return JsonService::fail('直播专题ID缺失');
  310. $user_info = $this->userInfo;
  311. if ($uid != $user_info['uid']) return JsonService::fail('非法用户');
  312. if (!$live_gift_num || !is_numeric($live_gift_num) || $live_gift_num < 0) return JsonService::fail('请选择礼物数量');
  313. //获取礼物配置列表
  314. $live_gift = LiveGift::liveGiftOne($live_gift_id);
  315. if (!$live_gift) return JsonService::fail('礼物不存在');
  316. //查看直播间是否存在
  317. $live_studio = LiveStudio::where(['stream_name' => $stream_name])->find();
  318. if (!$live_studio) return JsonService::fail('直播间不存在');
  319. $live_studio = $live_studio->toarray();
  320. if ($live_studio['special_id'] != $special_id) return JsonService::fail('直播专题有误');
  321. //看金币是否足够
  322. $gift_price = $live_gift['live_gift_price'] * $live_gift_num;
  323. $gold_name = SystemConfigService::get('gold_name');
  324. if ($user_info['gold_num'] <= 0 || $gift_price > $user_info['gold_num']) return JsonService::fail('您当前' . $gold_name . '不够,请充值', [], 406);
  325. try {
  326. User::beginTrans();
  327. //插入打赏数据
  328. $add_gift['uid'] = $uid;
  329. $add_gift['live_id'] = $live_studio['id'];
  330. $add_gift['nickname'] = $user_info['nickname'];
  331. $add_gift['gift_id'] = $live_gift_id;
  332. $add_gift['gift_name'] = $live_gift['live_gift_name'];
  333. $add_gift['gift_price'] = $live_gift['live_gift_price'];
  334. $add_gift['total_price'] = $gift_price;
  335. $add_gift['gift_num'] = $live_gift_num;
  336. $add_gift['add'] = time();
  337. $live_reward_id = LiveReward::insertLiveRewardData($add_gift);
  338. //插入聊天记录
  339. $add_barrage['uid'] = $uid;
  340. $add_barrage['to_uid'] = 0;
  341. $add_barrage['type'] = 4;//礼物
  342. $add_barrage['barrage'] = $live_gift_id;//礼物ID
  343. $add_barrage['live_id'] = $live_reward_id;
  344. $add_barrage['is_show'] = 1;
  345. LiveBarrage::set($add_barrage);
  346. //插入虚拟货币支出记录(资金监管记录表)
  347. $gold_name = SystemConfigService::get("gold_name");
  348. $mark = '用户赠送' . $stream_name . "号直播间" . $live_gift_num . '个' . $live_gift["live_gift_name"] . ',扣除' . $gold_name . $gift_price . '金币';
  349. UserBill::expend('用户打赏扣除金币', $uid, 'gold_num', 'live_reward', $gift_price, 0, $this->userInfo['gold_num'], $mark);
  350. User::bcDec($uid, 'gold_num', $gift_price, 'uid');
  351. User::commitTrans();
  352. return JsonService::successful($mark);
  353. } catch (\Exception $e) {
  354. User::rollbackTrans();
  355. return JsonService::fail('网路异常,打赏失败');
  356. }
  357. }
  358. /**
  359. * 带货商品列表
  360. */
  361. public function live_goods_list()
  362. {
  363. list($live_id) = UtilService::getMore([
  364. ['live_id', 0],
  365. ], $this->request, true);
  366. $is_member = isset($this->userInfo['level']) ? $this->userInfo['level'] : 0;
  367. return JsonService::successful(LiveGoods::getLiveGoodsList(['is_show' => 1, 'live_id' => $live_id], $is_member, 0, 0));
  368. }
  369. /**直播礼物排行榜
  370. * @throws \think\db\exception\DataNotFoundException
  371. * @throws \think\db\exception\ModelNotFoundException
  372. * @throws \think\exception\DbException
  373. */
  374. public function get_live_reward()
  375. {
  376. list($uid, $live_id, $page, $limit) = UtilService::postMore([
  377. ['uid', 0],
  378. ['live_id', 0],
  379. ['page', 1],
  380. ['limit', 20],
  381. ], $this->request, true);
  382. if (!$uid) return JsonService::fail('用户参数缺失');
  383. $user_info = $this->userInfo;
  384. if ($uid != $user_info['uid']) return JsonService::fail('非法用户');
  385. if (!$live_id) return JsonService::fail('直播间参数缺失');
  386. $live_info = LiveStudio::where('id', $live_id)->find();
  387. if (!$live_info) return JsonService::fail('直播间不存在');
  388. $data = LiveReward::getLiveRewardList(['live_id' => $live_id], $page, $limit);
  389. $now_user_reward = LiveReward::getLiveRewardOne(['live_id' => $live_id, 'uid' => $uid]);
  390. $data['now_user_reward'] = $now_user_reward;
  391. return JsonService::successful($data);
  392. }
  393. }