diff --git a/app/Http/Web/Controllers/AlipayController.php b/app/Http/Web/Controllers/AlipayController.php
deleted file mode 100644
index 3ea96d33..00000000
--- a/app/Http/Web/Controllers/AlipayController.php
+++ /dev/null
@@ -1,29 +0,0 @@
-notify();
-
- if (!$response) exit;
-
- $response->send();
-
- exit;
- }
-
-}
diff --git a/app/Http/Web/Controllers/LiveController.php b/app/Http/Web/Controllers/LiveController.php
index d4c88e56..d20f09b7 100644
--- a/app/Http/Web/Controllers/LiveController.php
+++ b/app/Http/Web/Controllers/LiveController.php
@@ -14,6 +14,20 @@ class LiveController extends Controller
use ResponseTrait;
+ /**
+ * @Get("/{id:[0-9]+}/preview", name="web.live.preview")
+ */
+ public function previewAction($id)
+ {
+ $service = new LiveService();
+
+ $stats = $service->getStats($id);
+
+ $this->view->setRenderLevel(View::LEVEL_ACTION_VIEW);
+ $this->view->pick('chapter/live_stats');
+ $this->view->setVar('stats', $stats);
+ }
+
/**
* @Get("/{id:[0-9]+}/chats", name="web.live.chats")
*/
diff --git a/app/Http/Web/Controllers/PublicController.php b/app/Http/Web/Controllers/PublicController.php
index 989e44b6..3c245685 100644
--- a/app/Http/Web/Controllers/PublicController.php
+++ b/app/Http/Web/Controllers/PublicController.php
@@ -4,6 +4,8 @@ namespace App\Http\Web\Controllers;
use App\Library\CsrfToken as CsrfTokenService;
use App\Models\ContentImage as ContentImageModel;
+use App\Services\Pay\Alipay as AlipayService;
+use App\Services\Pay\Wxpay as WxpayService;
use App\Services\Storage as StorageService;
use App\Traits\Response as ResponseTrait;
use App\Traits\Security as SecurityTrait;
@@ -67,4 +69,44 @@ class PublicController extends \Phalcon\Mvc\Controller
return $this->jsonSuccess(['token' => $token]);
}
+ /**
+ * @Post("/alipay/notify", name="web.alipay_notify")
+ */
+ public function alipayNotifyAction()
+ {
+ $alipayService = new AlipayService();
+
+ $response = $alipayService->notify();
+
+ if (!$response) exit;
+
+ $response->send();
+
+ exit;
+ }
+
+ /**
+ * @Post("/wxpay/notify", name="web.wxpay_notify")
+ */
+ public function wxpayNotifyAction()
+ {
+ $wxpayService = new WxpayService();
+
+ $response = $wxpayService->notify();
+
+ if (!$response) exit;
+
+ $response->send();
+
+ exit;
+ }
+
+ /**
+ * @Post("/live/notify", name="web.live_notify")
+ */
+ public function liveNotifyAction()
+ {
+
+ }
+
}
diff --git a/app/Http/Web/Controllers/WxpayController.php b/app/Http/Web/Controllers/WxpayController.php
deleted file mode 100644
index bc6274ab..00000000
--- a/app/Http/Web/Controllers/WxpayController.php
+++ /dev/null
@@ -1,29 +0,0 @@
-notify();
-
- if (!$response) exit;
-
- $response->send();
-
- exit;
- }
-
-}
diff --git a/app/Http/Web/Services/Live.php b/app/Http/Web/Services/Live.php
index 19cc4e4f..51981116 100644
--- a/app/Http/Web/Services/Live.php
+++ b/app/Http/Web/Services/Live.php
@@ -17,7 +17,9 @@ class Live extends Service
$key = $this->getRedisListKey($id);
- $items = $redis->lRange($key, 0, 10);
+ $redis->expire($key, 3 * 3600);
+
+ $items = $redis->lRange($key, 0, 15);
$result = [];
@@ -88,7 +90,7 @@ class Live extends Service
$content = $this->request->getPost('content', ['trim', 'striptags']);
- $content = kg_substr($content, 0, 150);
+ $content = kg_substr($content, 0, 80);
Gateway::$registerAddress = $this->getRegisterAddress();
@@ -111,9 +113,14 @@ class Live extends Service
Gateway::sendToGroup($groupName, $encodeMessage, $clientId);
$redis = $this->getRedis();
+
$key = $this->getRedisListKey($id);
+
$redis->lPush($key, $encodeMessage);
- $redis->lTrim($key, 0, 10);
+
+ if ($redis->lLen($key) % 20 == 0) {
+ $redis->lTrim($key, 0, 15);
+ }
return $message;
}
diff --git a/app/Http/Web/Views/chapter/live_chats.volt b/app/Http/Web/Views/chapter/live_chats.volt
index 47bb3675..38362395 100644
--- a/app/Http/Web/Views/chapter/live_chats.volt
+++ b/app/Http/Web/Views/chapter/live_chats.volt
@@ -1,6 +1,6 @@
{% for chat in chats %}
- {% if chat.user.vip == 0 %}
+ {% if chat.user.vip == 1 %}
{% endif %}
{{ chat.user.name }}
diff --git a/app/Http/Web/Views/chapter/show_live.volt b/app/Http/Web/Views/chapter/show_live.volt
index 03ef0ef5..116e214a 100644
--- a/app/Http/Web/Views/chapter/show_live.volt
+++ b/app/Http/Web/Views/chapter/show_live.volt
@@ -31,12 +31,16 @@
-
-
-
+ {% if auth_user.id > 0 %}
+
+
+
+ {% else %}
+
登录后才可以发言哦~
+ {% endif %}
diff --git a/app/Http/Web/Views/index/index.volt b/app/Http/Web/Views/index/index.volt
index 985f432d..ca7dae70 100644
--- a/app/Http/Web/Views/index/index.volt
+++ b/app/Http/Web/Views/index/index.volt
@@ -68,19 +68,8 @@
{% endblock %}
-{% block inline_js %}
+{% block include_js %}
-
+ {{ js_include('web/js/index.js') }}
{% endblock %}
\ No newline at end of file
diff --git a/app/Http/Web/Views/templates/full.volt b/app/Http/Web/Views/templates/full.volt
index 6d717396..7166528b 100644
--- a/app/Http/Web/Views/templates/full.volt
+++ b/app/Http/Web/Views/templates/full.volt
@@ -2,6 +2,7 @@
+
diff --git a/app/Http/Web/Views/templates/layer.volt b/app/Http/Web/Views/templates/layer.volt
index b9b1c962..e15ecd90 100644
--- a/app/Http/Web/Views/templates/layer.volt
+++ b/app/Http/Web/Views/templates/layer.volt
@@ -2,6 +2,7 @@
+
{{ icon_link('favicon.ico') }}
diff --git a/app/Library/CsrfToken.php b/app/Library/CsrfToken.php
index 099450cb..2ef2a861 100644
--- a/app/Library/CsrfToken.php
+++ b/app/Library/CsrfToken.php
@@ -34,15 +34,21 @@ class CsrfToken
public function checkToken($token)
{
+ if (!$token) return false;
+
$text = $this->crypt->decryptBase64($token);
- list($time, $fixed, $random) = explode($this->delimiter, $text);
+ $params = explode($this->delimiter, $text);
- if ($time != intval($time) || $fixed != $this->fixed || strlen($random) != 8) {
+ if (!isset($params[0]) || !isset($params[1]) || !isset($params[2])) {
return false;
}
- if (time() - $time > $this->lifetime) {
+ if ($params[0] != intval($params[0]) || $params[1] != $this->fixed || strlen($params[2]) != 8) {
+ return false;
+ }
+
+ if (time() - $params[0] > $this->lifetime) {
return false;
}
diff --git a/app/Services/Frontend/Chapter/ChapterInfo.php b/app/Services/Frontend/Chapter/ChapterInfo.php
index deb7ee77..e0fe0601 100644
--- a/app/Services/Frontend/Chapter/ChapterInfo.php
+++ b/app/Services/Frontend/Chapter/ChapterInfo.php
@@ -130,11 +130,6 @@ class ChapterInfo extends FrontendService
$playUrls = $service->getPlayUrls($chapter->id);
- /**
- * @var array $attrs
- */
- $attrs = $chapter->attrs;
-
return [
'id' => $chapter->id,
'title' => $chapter->title,
@@ -150,22 +145,36 @@ class ChapterInfo extends FrontendService
protected function formatChapterLive(ChapterModel $chapter)
{
- $liveService = new LiveService();
+ $service = new LiveService();
- $playUrls = $liveService->getPullUrls("chapter_{$chapter->id}");
+ $streamName = $this->getLiveStreamName($chapter->id);
- /**
- * @var array $attrs
- */
- $attrs = $chapter->attrs;
+ $chapterRepo = new ChapterRepo();
+
+ $live = $chapterRepo->findChapterLive($chapter->id);
+
+ $playUrls = [];
+
+ if ($live->start_time - time() > 1800) {
+ $status = 'pending';
+ } elseif (time() - $live->end_time > 1800) {
+ $status = 'finished';
+ } else {
+ $status = $service->getStreamState($streamName);
+ }
+
+ if ($status == 'active') {
+ $playUrls = $service->getPullUrls($streamName);
+ }
return [
'id' => $chapter->id,
'title' => $chapter->title,
'summary' => $chapter->summary,
'model' => $chapter->model,
- 'start_time' => $attrs['start_time'],
- 'end_time' => $attrs['end_time'],
+ 'status' => $status,
+ 'start_time' => $live->start_time,
+ 'end_time' => $live->end_time,
'play_urls' => $playUrls,
'user_count' => $chapter->user_count,
'agree_count' => $chapter->agree_count,
@@ -180,11 +189,6 @@ class ChapterInfo extends FrontendService
$read = $chapterRepo->findChapterRead($chapter->id);
- /**
- * @var array $attrs
- */
- $attrs = $chapter->attrs;
-
return [
'id' => $chapter->id,
'title' => $chapter->title,
@@ -259,4 +263,9 @@ class ChapterInfo extends FrontendService
$this->eventsManager->fire('chapterCounter:incrUserCount', $this, $chapter);
}
+ protected function getLiveStreamName($id)
+ {
+ return "chapter_{$id}";
+ }
+
}
diff --git a/app/Services/Live.php b/app/Services/Live.php
index 2f81bb92..038ecaa6 100644
--- a/app/Services/Live.php
+++ b/app/Services/Live.php
@@ -2,32 +2,191 @@
namespace App\Services;
+use Phalcon\Logger\Adapter\File as FileLogger;
+use TencentCloud\Common\Credential;
+use TencentCloud\Common\Exception\TencentCloudSDKException;
+use TencentCloud\Common\Profile\ClientProfile;
+use TencentCloud\Common\Profile\HttpProfile;
+use TencentCloud\Live\V20180801\LiveClient;
+use TencentCloud\Live\V20180801\Models\DescribeLiveStreamStateRequest;
+use TencentCloud\Live\V20180801\Models\ForbidLiveStreamRequest;
+use TencentCloud\Live\V20180801\Models\ResumeLiveStreamRequest;
+
class Live extends Service
{
+ const END_POINT = 'live.tencentcloudapi.com';
+
/**
* @var array
*/
protected $settings;
+ /**
+ * @var LiveClient
+ */
+ protected $client;
+
+ /**
+ * @var FileLogger
+ */
+ protected $logger;
+
public function __construct()
{
$this->settings = $this->getSectionSettings('live');
+
+ $this->logger = $this->getLogger('live');
+
+ $this->client = $this->getLiveClient();
+ }
+
+ /**
+ * 获取流的状态
+ *
+ * @param string $streamName
+ * @param string $appName
+ * @return string|bool
+ */
+ public function getStreamState($streamName, $appName = 'live')
+ {
+ try {
+
+ $request = new DescribeLiveStreamStateRequest();
+
+ $params = json_encode([
+ 'DomainName' => $this->settings['push_domain'],
+ 'AppName' => $appName ?: 'live',
+ 'StreamName' => $streamName,
+ ]);
+
+ $request->fromJsonString($params);
+
+ $this->logger->debug('Describe Live Stream State Request ' . $params);
+
+ $response = $this->client->DescribeLiveStreamState($request);
+
+ $this->logger->debug('Describe Live Stream State Response ' . $response->toJsonString());
+
+ $result = $response->StreamState;
+
+ } catch (TencentCloudSDKException $e) {
+
+ $this->logger->error('Describe Live Stream State Exception ' . kg_json_encode([
+ 'code' => $e->getErrorCode(),
+ 'message' => $e->getMessage(),
+ 'requestId' => $e->getRequestId(),
+ ]));
+
+ $result = false;
+ }
+
+ return $result;
+ }
+
+ /**
+ * 禁推直播推流
+ *
+ * @param string $streamName
+ * @param string $appName
+ * @param string $reason
+ * @return array|bool
+ */
+ public function forbidStream($streamName, $appName = 'live', $reason = '')
+ {
+ try {
+
+ $request = new ForbidLiveStreamRequest();
+
+ $params = json_encode([
+ 'DomainName' => $this->settings['push_domain'],
+ 'AppName' => $appName ?: 'live',
+ 'StreamName' => $streamName,
+ 'Reason' => $reason,
+ ]);
+
+ $request->fromJsonString($params);
+
+ $this->logger->debug('Forbid Live Stream Request ' . $params);
+
+ $response = $this->client->ForbidLiveStream($request);
+
+ $this->logger->debug('Forbid Live Stream Response ' . $response->toJsonString());
+
+ $result = json_decode($response->toJsonString(), true);
+
+ } catch (TencentCloudSDKException $e) {
+
+ $this->logger->error('Forbid Live Stream Exception ' . kg_json_encode([
+ 'code' => $e->getErrorCode(),
+ 'message' => $e->getMessage(),
+ 'requestId' => $e->getRequestId(),
+ ]));
+
+ $result = false;
+ }
+
+ return $result;
+ }
+
+ /**
+ * 恢复直播推流
+ *
+ * @param string $streamName
+ * @param string $appName
+ * @return array|bool
+ */
+ public function resumeStream($streamName, $appName = 'live')
+ {
+ try {
+
+ $request = new ResumeLiveStreamRequest();
+
+ $params = json_encode([
+ 'DomainName' => $this->settings['push_domain'],
+ 'AppName' => $appName ?: 'live',
+ 'StreamName' => $streamName,
+ ]);
+
+ $request->fromJsonString($params);
+
+ $this->logger->debug('Resume Live Stream Request ' . $params);
+
+ $response = $this->client->ResumeLiveStream($request);
+
+ $this->logger->debug('Resume Live Stream Response ' . $response->toJsonString());
+
+ $result = json_decode($response->toJsonString(), true);
+
+ } catch (TencentCloudSDKException $e) {
+
+ $this->logger->error('Resume Live Stream Exception ' . kg_json_encode([
+ 'code' => $e->getErrorCode(),
+ 'message' => $e->getMessage(),
+ 'requestId' => $e->getRequestId(),
+ ]));
+
+ $result = false;
+ }
+
+ return $result;
}
/**
* 获取推流地址
*
* @param string $streamName
+ * @param string $appName
* @return string
*/
- function getPushUrl($streamName)
+ function getPushUrl($streamName, $appName = 'live')
{
+ $appName = $appName ?: 'live';
+
$authEnabled = $this->settings['push_auth_enabled'];
$authKey = $this->settings['push_auth_key'];
$expireTime = $this->settings['push_auth_delta'] + time();
$domain = $this->settings['push_domain'];
- $appName = 'live';
$authParams = $this->getAuthParams($streamName, $authKey, $expireTime);
@@ -46,6 +205,8 @@ class Live extends Service
*/
public function getPullUrls($streamName, $appName = 'live')
{
+ $appName = $appName ?: 'live';
+
$protocol = $this->settings['pull_protocol'];
$domain = $this->settings['pull_domain'];
$authEnabled = $this->settings['pull_auth_enabled'];
@@ -116,4 +277,25 @@ class Live extends Service
]);
}
+ protected function getLiveClient()
+ {
+ $secret = $this->getSectionSettings('secret');
+
+ $secretId = $secret['secret_id'];
+ $secretKey = $secret['secret_key'];
+ $region = '';
+
+ $credential = new Credential($secretId, $secretKey);
+
+ $httpProfile = new HttpProfile();
+
+ $httpProfile->setEndpoint(self::END_POINT);
+
+ $clientProfile = new ClientProfile();
+
+ $clientProfile->setHttpProfile($httpProfile);
+
+ return new LiveClient($credential, $region, $clientProfile);
+ }
+
}
diff --git a/config/config.default.php b/config/config.default.php
index 70ad4f74..890d6181 100644
--- a/config/config.default.php
+++ b/config/config.default.php
@@ -123,12 +123,12 @@ $config['throttle']['lifetime'] = 60;
$config['throttle']['rate_limit'] = 60;
/**
- * 客户端连接地址
+ * 客户端连接地址(外部可访问的ip或域名)
*/
$config['websocket']['url'] = 'ws://127.0.0.1:8282';
/**
- * gateway和worker注册地址
+ * gateway和worker注册地址(内部访问)
*/
$config['websocket']['register_address'] = '127.0.0.1:1238';
diff --git a/public/static/web/css/common.css b/public/static/web/css/common.css
index da2cb3da..b058d74a 100644
--- a/public/static/web/css/common.css
+++ b/public/static/web/css/common.css
@@ -183,6 +183,7 @@
.index-course-list .course-card .info {
border: 1px solid #eee;
+ padding-bottom: 18px;
}
.index-carousel {
@@ -803,6 +804,14 @@
color: #666;
}
+.chat-login-tips {
+ border-top: 1px solid #f2f2f2;
+ padding-top: 10px;
+ text-align: center;
+ font-size: 12px;
+ color: #999;
+}
+
.chat-msg-form .layui-input {
height: 32px;
font-size: 12px;
@@ -822,18 +831,6 @@
margin-right: 10px;
}
-.live-user-card {
- margin-bottom: 10px;
- line-height: 25px;
-}
-
-.chat-login-tips {
- padding-top: 20px;
- text-align: center;
- font-size: 12px;
- color: #999;
-}
-
.chapter-bg {
background-color: #f2f2f2;
}
diff --git a/public/static/web/js/index.js b/public/static/web/js/index.js
new file mode 100644
index 00000000..becd6b1f
--- /dev/null
+++ b/public/static/web/js/index.js
@@ -0,0 +1,13 @@
+layui.use(['carousel', 'flow'], function () {
+
+ var carousel = layui.carousel;
+ var flow = layui.flow;
+
+ carousel.render({
+ elem: '#carousel',
+ width: '100%',
+ height: '270px'
+ });
+
+ flow.lazyimg();
+});
\ No newline at end of file
diff --git a/public/static/web/js/live.im.js b/public/static/web/js/live.im.js
index 6acc035b..57bd40b4 100644
--- a/public/static/web/js/live.im.js
+++ b/public/static/web/js/live.im.js
@@ -65,7 +65,7 @@ layui.use(['jquery', 'form', 'helper'], function () {
function showNewMessage(res) {
var html = '
';
- if (res.user.vip === 0) {
+ if (res.user.vip === 1) {
html += '';
}
html += '' + res.user.name + ':';