mirror of
https://gitee.com/koogua/course-tencent-cloud.git
synced 2025-06-22 03:32:47 +08:00
修复file_transcode
This commit is contained in:
parent
122b4adfa8
commit
6abca790bc
@ -26,6 +26,7 @@ class CleanLogTask extends Task
|
|||||||
$this->cleanOrderLog();
|
$this->cleanOrderLog();
|
||||||
$this->cleanRefundLog();
|
$this->cleanRefundLog();
|
||||||
$this->cleanPointLog();
|
$this->cleanPointLog();
|
||||||
|
$this->cleanDingTalkLog();
|
||||||
$this->cleanNoticeLog();
|
$this->cleanNoticeLog();
|
||||||
$this->cleanOtherLog();
|
$this->cleanOtherLog();
|
||||||
}
|
}
|
||||||
@ -234,6 +235,18 @@ class CleanLogTask extends Task
|
|||||||
$this->whitelist[] = $type;
|
$this->whitelist[] = $type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清理钉钉日志
|
||||||
|
*/
|
||||||
|
protected function cleanDingTalkLog()
|
||||||
|
{
|
||||||
|
$type = 'dingtalk';
|
||||||
|
|
||||||
|
$this->cleanLog($type, 7);
|
||||||
|
|
||||||
|
$this->whitelist[] = $type;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 清理通知日志
|
* 清理通知日志
|
||||||
*/
|
*/
|
||||||
|
81
app/Console/Tasks/LiveTeacherNoticeTask.php
Normal file
81
app/Console/Tasks/LiveTeacherNoticeTask.php
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Console\Tasks;
|
||||||
|
|
||||||
|
use App\Models\ChapterLive as ChapterLiveModel;
|
||||||
|
use App\Repos\Chapter as ChapterRepo;
|
||||||
|
use App\Services\DingTalk\Notice\LiveTeacher as LiveTeacherNotice;
|
||||||
|
use Phalcon\Mvc\Model\Resultset;
|
||||||
|
use Phalcon\Mvc\Model\ResultsetInterface;
|
||||||
|
|
||||||
|
class LiveTeacherNoticeTask extends Task
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成讲师提醒
|
||||||
|
*/
|
||||||
|
public function provideAction()
|
||||||
|
{
|
||||||
|
$lives = $this->findLives();
|
||||||
|
|
||||||
|
if ($lives->count() == 0) return;
|
||||||
|
|
||||||
|
$redis = $this->getRedis();
|
||||||
|
|
||||||
|
$keyName = $this->getCacheKeyName();
|
||||||
|
|
||||||
|
foreach ($lives as $live) {
|
||||||
|
$redis->sAdd($keyName, $live->chapter_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
$redis->expire($keyName, 86400);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消费讲师提醒
|
||||||
|
*/
|
||||||
|
public function consumeAction()
|
||||||
|
{
|
||||||
|
$redis = $this->getRedis();
|
||||||
|
|
||||||
|
$keyName = $this->getCacheKeyName();
|
||||||
|
|
||||||
|
$chapterIds = $redis->sMembers($keyName);
|
||||||
|
|
||||||
|
if (count($chapterIds) == 0) return;
|
||||||
|
|
||||||
|
$chapterRepo = new ChapterRepo();
|
||||||
|
|
||||||
|
$notice = new LiveTeacherNotice();
|
||||||
|
|
||||||
|
foreach ($chapterIds as $chapterId) {
|
||||||
|
|
||||||
|
$live = $chapterRepo->findChapterLive($chapterId);
|
||||||
|
|
||||||
|
if ($live->start_time - time() < 30 * 60) {
|
||||||
|
|
||||||
|
$notice->handle($live);
|
||||||
|
|
||||||
|
$redis->sRem($keyName, $chapterId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return ResultsetInterface|Resultset|ChapterLiveModel[]
|
||||||
|
*/
|
||||||
|
protected function findLives()
|
||||||
|
{
|
||||||
|
$today = strtotime(date('Ymd'));
|
||||||
|
|
||||||
|
return ChapterLiveModel::query()
|
||||||
|
->betweenWhere('start_time', $today, $today + 86400)
|
||||||
|
->execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getCacheKeyName()
|
||||||
|
{
|
||||||
|
return 'live_teacher_notice';
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
180
app/Console/Tasks/MonitorTask.php
Normal file
180
app/Console/Tasks/MonitorTask.php
Normal file
@ -0,0 +1,180 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Console\Tasks;
|
||||||
|
|
||||||
|
use App\Library\Benchmark;
|
||||||
|
use App\Library\Utils\ServerInfo;
|
||||||
|
use App\Models\User as UserModel;
|
||||||
|
use App\Services\DingTalkNotice;
|
||||||
|
use App\Services\Search\UserSearcher;
|
||||||
|
use GatewayClient\Gateway;
|
||||||
|
|
||||||
|
class MonitorTask extends Task
|
||||||
|
{
|
||||||
|
|
||||||
|
public function mainAction()
|
||||||
|
{
|
||||||
|
$items = [
|
||||||
|
'cpu' => $this->checkCPU(),
|
||||||
|
'disk' => $this->checkDisk(),
|
||||||
|
'mysql' => $this->checkMysql(),
|
||||||
|
'redis' => $this->checkRedis(),
|
||||||
|
'xunsearch' => $this->checkXunSearch(),
|
||||||
|
'websocket' => $this->checkWebSocket(),
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach ($items as $key => $value) {
|
||||||
|
if (empty($value)) {
|
||||||
|
unset($items[$key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($items)) return;
|
||||||
|
|
||||||
|
$notice = new DingTalkNotice();
|
||||||
|
|
||||||
|
$content = implode("\n", $items);
|
||||||
|
|
||||||
|
$notice->atTechSupport($content);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function checkCPU()
|
||||||
|
{
|
||||||
|
$coreCount = $this->getCpuCoreCount();
|
||||||
|
|
||||||
|
$cpu = ServerInfo::cpu();
|
||||||
|
|
||||||
|
if ($cpu[1] > $coreCount / 2) {
|
||||||
|
return sprintf("cpu负载超过%s", $cpu[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function checkDisk()
|
||||||
|
{
|
||||||
|
$disk = ServerInfo::disk();
|
||||||
|
|
||||||
|
if ($disk['percent'] > 80) {
|
||||||
|
return sprintf("disk空间超过%s%%", $disk['percent']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function checkMysql()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
|
||||||
|
$benchmark = new Benchmark();
|
||||||
|
|
||||||
|
$benchmark->start();
|
||||||
|
|
||||||
|
$user = UserModel::findFirst();
|
||||||
|
|
||||||
|
$benchmark->stop();
|
||||||
|
|
||||||
|
$elapsedTime = $benchmark->getElapsedTime();
|
||||||
|
|
||||||
|
if ($user === false) {
|
||||||
|
return sprintf("mysql查询失败");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($elapsedTime > 1) {
|
||||||
|
return sprintf("mysql查询响应超过%s秒", round($elapsedTime, 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return sprintf("mysql可能存在异常");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function checkRedis()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
|
||||||
|
$benchmark = new Benchmark();
|
||||||
|
|
||||||
|
$benchmark->start();
|
||||||
|
|
||||||
|
$site = $this->getSettings('site');
|
||||||
|
|
||||||
|
$benchmark->stop();
|
||||||
|
|
||||||
|
$elapsedTime = $benchmark->getElapsedTime();
|
||||||
|
|
||||||
|
if (empty($site)) {
|
||||||
|
return sprintf("redis查询失败");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($elapsedTime > 1) {
|
||||||
|
return sprintf("redis查询响应超过%s秒", round($elapsedTime, 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return sprintf("redis可能存在异常");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function checkXunSearch()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
|
||||||
|
$benchmark = new Benchmark();
|
||||||
|
|
||||||
|
$benchmark->start();
|
||||||
|
|
||||||
|
$searcher = new UserSearcher();
|
||||||
|
|
||||||
|
$user = $searcher->search('id:10000');
|
||||||
|
|
||||||
|
$benchmark->stop();
|
||||||
|
|
||||||
|
$elapsedTime = $benchmark->getElapsedTime();
|
||||||
|
|
||||||
|
if (empty($user)) {
|
||||||
|
return sprintf("xunsearch搜索失败");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($elapsedTime > 1) {
|
||||||
|
return sprintf("xunsearch搜索响应超过%s秒", round($elapsedTime, 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return sprintf("xunsearch可能存在异常");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function checkWebSocket()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
|
||||||
|
$benchmark = new Benchmark();
|
||||||
|
|
||||||
|
$config = $this->getConfig();
|
||||||
|
|
||||||
|
Gateway::$registerAddress = $config->path('websocket.register_address');
|
||||||
|
|
||||||
|
$benchmark->start();
|
||||||
|
|
||||||
|
Gateway::isUidOnline(10000);
|
||||||
|
|
||||||
|
$benchmark->stop();
|
||||||
|
|
||||||
|
$elapsedTime = $benchmark->getElapsedTime();
|
||||||
|
|
||||||
|
if ($elapsedTime > 1) {
|
||||||
|
return sprintf("websocket响应超过%s秒", round($elapsedTime, 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return sprintf("websocket可能存在异常");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getCpuCoreCount()
|
||||||
|
{
|
||||||
|
$cpuInfo = file_get_contents('/proc/cpuinfo');
|
||||||
|
|
||||||
|
preg_match_all('/^processor/m', $cpuInfo, $matches);
|
||||||
|
|
||||||
|
return count($matches[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -378,4 +378,30 @@ class SettingController extends Controller
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Route("/dingtalk/robot", name="admin.setting.dingtalk_robot")
|
||||||
|
*/
|
||||||
|
public function dingtalkRobotAction()
|
||||||
|
{
|
||||||
|
$section = 'dingtalk.robot';
|
||||||
|
|
||||||
|
$settingService = new SettingService();
|
||||||
|
|
||||||
|
if ($this->request->isPost()) {
|
||||||
|
|
||||||
|
$data = $this->request->getPost();
|
||||||
|
|
||||||
|
$settingService->updatePointSettings($section, $data);
|
||||||
|
|
||||||
|
return $this->jsonSuccess(['msg' => '更新配置成功']);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
$robot = $settingService->getSettings($section);
|
||||||
|
|
||||||
|
$this->view->pick('setting/dingtalk_robot');
|
||||||
|
$this->view->setVar('robot', $robot);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ use App\Http\Admin\Services\AlipayTest as AlipayTestService;
|
|||||||
use App\Http\Admin\Services\Setting as SettingService;
|
use App\Http\Admin\Services\Setting as SettingService;
|
||||||
use App\Http\Admin\Services\WxpayTest as WxpayTestService;
|
use App\Http\Admin\Services\WxpayTest as WxpayTestService;
|
||||||
use App\Services\Captcha as CaptchaService;
|
use App\Services\Captcha as CaptchaService;
|
||||||
|
use App\Services\DingTalkNotice as DingTalkNoticeService;
|
||||||
use App\Services\Live as LiveService;
|
use App\Services\Live as LiveService;
|
||||||
use App\Services\Mail\Test as TestMailService;
|
use App\Services\Mail\Test as TestMailService;
|
||||||
use App\Services\MyStorage as StorageService;
|
use App\Services\MyStorage as StorageService;
|
||||||
@ -250,4 +251,20 @@ class TestController extends Controller
|
|||||||
return $this->jsonSuccess(['status' => $status]);
|
return $this->jsonSuccess(['status' => $status]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Post("/dingtalk/robot", name="admin.test.dingtalk_robot")
|
||||||
|
*/
|
||||||
|
public function dingTalkRobotAction()
|
||||||
|
{
|
||||||
|
$noticeService = new DingTalkNoticeService();
|
||||||
|
|
||||||
|
$result = $noticeService->test();
|
||||||
|
|
||||||
|
if ($result) {
|
||||||
|
return $this->jsonSuccess(['msg' => '发送消息成功,请到钉钉确认']);
|
||||||
|
} else {
|
||||||
|
return $this->jsonError(['msg' => '发送消息失败,请检查配置']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -800,6 +800,12 @@ class AuthNode extends Service
|
|||||||
'type' => 'menu',
|
'type' => 'menu',
|
||||||
'route' => 'admin.setting.wechat_oa',
|
'route' => 'admin.setting.wechat_oa',
|
||||||
],
|
],
|
||||||
|
[
|
||||||
|
'id' => '5-1-15',
|
||||||
|
'title' => '钉钉机器人',
|
||||||
|
'type' => 'menu',
|
||||||
|
'route' => 'admin.setting.dingtalk_robot',
|
||||||
|
],
|
||||||
[
|
[
|
||||||
'id' => '5-1-14',
|
'id' => '5-1-14',
|
||||||
'title' => '积分设置',
|
'title' => '积分设置',
|
||||||
|
55
app/Http/Admin/Views/setting/dingtalk_robot.volt
Normal file
55
app/Http/Admin/Views/setting/dingtalk_robot.volt
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
{% extends 'templates/main.volt' %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<form class="layui-form kg-form" method="POST" action="{{ url({'for':'admin.setting.dingtalk_robot'}) }}">
|
||||||
|
<fieldset class="layui-elem-field layui-field-title">
|
||||||
|
<legend>钉钉机器人</legend>
|
||||||
|
</fieldset>
|
||||||
|
<div class="layui-form-item">
|
||||||
|
<label class="layui-form-label">App Secret</label>
|
||||||
|
<div class="layui-input-block">
|
||||||
|
<input class="layui-input" type="text" name="app_secret" value="{{ robot.app_secret }}" layui-verify="required">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="layui-form-item">
|
||||||
|
<label class="layui-form-label">App Token</label>
|
||||||
|
<div class="layui-input-block">
|
||||||
|
<input class="layui-input" type="text" name="app_token" value="{{ robot.app_token }}" layui-verify="required">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="layui-form-item">
|
||||||
|
<label class="layui-form-label">技术手机号</label>
|
||||||
|
<div class="layui-input-block">
|
||||||
|
<input class="layui-input" type="text" name="ts_mobiles" placeholder="技术人员手机号,多个号码逗号分隔" value="{{ robot.ts_mobiles }}" layui-verify="required">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="layui-form-item">
|
||||||
|
<label class="layui-form-label">客服手机号</label>
|
||||||
|
<div class="layui-input-block">
|
||||||
|
<input class="layui-input" type="text" name="cs_mobiles" placeholder="客服人员手机号,多个号码逗号分隔" value="{{ robot.ts_mobiles }}" layui-verify="required">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="layui-form-item" style="margin-top:20px;">
|
||||||
|
<label class="layui-form-label"></label>
|
||||||
|
<div class="layui-input-block">
|
||||||
|
<button class="layui-btn" lay-submit="true" lay-filter="go">提交</button>
|
||||||
|
<button type="button" class="kg-back layui-btn layui-btn-primary">返回</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<form class="layui-form kg-form" method="POST" action="{{ url({'for':'admin.test.dingtalk_robot'}) }}">
|
||||||
|
<fieldset class="layui-elem-field layui-field-title">
|
||||||
|
<legend>通知测试</legend>
|
||||||
|
</fieldset>
|
||||||
|
<div class="layui-form-item">
|
||||||
|
<label class="layui-form-label"></label>
|
||||||
|
<div class="layui-input-block">
|
||||||
|
<button class="layui-btn" lay-submit="true" lay-filter="go">提交</button>
|
||||||
|
<button type="button" class="kg-back layui-btn layui-btn-primary">返回</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
{% endblock %}
|
27
app/Library/Benchmark.php
Normal file
27
app/Library/Benchmark.php
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Library;
|
||||||
|
|
||||||
|
class Benchmark
|
||||||
|
{
|
||||||
|
|
||||||
|
protected $startTime = 0;
|
||||||
|
|
||||||
|
protected $endTime = 0;
|
||||||
|
|
||||||
|
public function start()
|
||||||
|
{
|
||||||
|
$this->startTime = microtime(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function stop()
|
||||||
|
{
|
||||||
|
$this->endTime = microtime(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getElapsedTime()
|
||||||
|
{
|
||||||
|
return $this->endTime - $this->startTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -35,6 +35,24 @@ function kg_substr($str, $start, $length, $suffix = '...')
|
|||||||
return $str == $result ? $str : $result . $suffix;
|
return $str == $result ? $str : $result . $suffix;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 占位替换
|
||||||
|
*
|
||||||
|
* @param string $str
|
||||||
|
* @param array $data
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
function kg_ph_replace($str, $data = [])
|
||||||
|
{
|
||||||
|
if (empty($data)) return $str;
|
||||||
|
|
||||||
|
foreach ($data as $key => $value) {
|
||||||
|
$str = str_replace('{' . $key . '}', $value, $str);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $str;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* uniqid封装
|
* uniqid封装
|
||||||
*
|
*
|
||||||
|
@ -14,10 +14,11 @@ class Task extends Model
|
|||||||
const TYPE_LUCKY_GIFT_DELIVER = 4; // 抽奖礼品派发
|
const TYPE_LUCKY_GIFT_DELIVER = 4; // 抽奖礼品派发
|
||||||
|
|
||||||
const TYPE_NOTICE_ACCOUNT_LOGIN = 11; // 帐号登录通知
|
const TYPE_NOTICE_ACCOUNT_LOGIN = 11; // 帐号登录通知
|
||||||
const TYPE_NOTICE_LIVE_BEGIN = 12; // 直播开始通知
|
const TYPE_NOTICE_LIVE_BEGIN = 12; // 直播学员通知
|
||||||
const TYPE_NOTICE_ORDER_FINISH = 13; // 订单完成通知
|
const TYPE_NOTICE_ORDER_FINISH = 13; // 订单完成通知
|
||||||
const TYPE_NOTICE_REFUND_FINISH = 14; // 退款完成通知
|
const TYPE_NOTICE_REFUND_FINISH = 14; // 退款完成通知
|
||||||
const TYPE_NOTICE_CONSULT_REPLY = 15; // 咨询回复通知
|
const TYPE_NOTICE_CONSULT_REPLY = 15; // 咨询回复通知
|
||||||
|
const TYPE_NOTICE_LIVE_TEACHER = 16; // 直播讲师通知
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 优先级
|
* 优先级
|
||||||
|
32
app/Services/DingTalk/Notice/ConsultCreate.php
Normal file
32
app/Services/DingTalk/Notice/ConsultCreate.php
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Services\DingTalk\Notice;
|
||||||
|
|
||||||
|
use App\Models\Consult as ConsultModel;
|
||||||
|
use App\Repos\Course as CourseRepo;
|
||||||
|
use App\Repos\User as UserRepo;
|
||||||
|
use App\Services\DingTalkNotice;
|
||||||
|
|
||||||
|
class ConsultCreate extends DingTalkNotice
|
||||||
|
{
|
||||||
|
|
||||||
|
public function handle(ConsultModel $consult)
|
||||||
|
{
|
||||||
|
$userRepo = new UserRepo();
|
||||||
|
|
||||||
|
$user = $userRepo->findById($consult->owner_id);
|
||||||
|
|
||||||
|
$courseRepo = new CourseRepo();
|
||||||
|
|
||||||
|
$course = $courseRepo->findById($consult->course_id);
|
||||||
|
|
||||||
|
$content = kg_ph_replace("{user.name} 对课程:{course.title} 发起了咨询:\n{consult.question}", [
|
||||||
|
'user.name' => $user->name,
|
||||||
|
'course.title' => $course->title,
|
||||||
|
'consult.question' => $consult->question,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->atCourseTeacher($course->id, $content);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
36
app/Services/DingTalk/Notice/CustomService.php
Normal file
36
app/Services/DingTalk/Notice/CustomService.php
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Services\DingTalk\Notice;
|
||||||
|
|
||||||
|
use App\Models\ImMessage as ImMessageModel;
|
||||||
|
use App\Repos\User as UserRepo;
|
||||||
|
use App\Services\DingTalkNotice;
|
||||||
|
|
||||||
|
class CustomService extends DingTalkNotice
|
||||||
|
{
|
||||||
|
|
||||||
|
public function handle(ImMessageModel $message)
|
||||||
|
{
|
||||||
|
$keyName = "dingtalk_cs_notice:{$message->sender_id}";
|
||||||
|
|
||||||
|
$cache = $this->getCache();
|
||||||
|
|
||||||
|
$content = $cache->get($keyName);
|
||||||
|
|
||||||
|
if ($content) return;
|
||||||
|
|
||||||
|
$cache->save($keyName, 1, 3600);
|
||||||
|
|
||||||
|
$userRepo = new UserRepo();
|
||||||
|
|
||||||
|
$sender = $userRepo->findById($message->sender_id);
|
||||||
|
|
||||||
|
$content = kg_ph_replace("{user} 通过在线客服给你发送了消息:{message}", [
|
||||||
|
'user' => $sender->name,
|
||||||
|
'message' => $message->content,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->atCustomService($content);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
26
app/Services/DingTalk/Notice/LiveTeacher.php
Normal file
26
app/Services/DingTalk/Notice/LiveTeacher.php
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Services\DingTalk\Notice;
|
||||||
|
|
||||||
|
use App\Models\ChapterLive as ChapterLiveModel;
|
||||||
|
use App\Repos\Course as CourseRepo;
|
||||||
|
use App\Services\DingTalkNotice;
|
||||||
|
|
||||||
|
class LiveTeacher extends DingTalkNotice
|
||||||
|
{
|
||||||
|
|
||||||
|
public function handle(ChapterLiveModel $live)
|
||||||
|
{
|
||||||
|
$courseRepo = new CourseRepo();
|
||||||
|
|
||||||
|
$course = $courseRepo->findById($live->course_id);
|
||||||
|
|
||||||
|
$content = kg_ph_replace("课程:{course.title} 计划于 {live.start_time} 开播,不要错过直播时间哦!", [
|
||||||
|
'course.title' => $course->title,
|
||||||
|
'live.start_time' => date('Y-m-d H:i', $live->start_time),
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->atCourseTeacher($course->id, $content);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
27
app/Services/DingTalk/Notice/OrderFinish.php
Normal file
27
app/Services/DingTalk/Notice/OrderFinish.php
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Services\DingTalk\Notice;
|
||||||
|
|
||||||
|
use App\Models\Order as OrderModel;
|
||||||
|
use App\Repos\User as UserRepo;
|
||||||
|
use App\Services\DingTalkNotice;
|
||||||
|
|
||||||
|
class OrderFinish extends DingTalkNotice
|
||||||
|
{
|
||||||
|
|
||||||
|
public function handle(OrderModel $order)
|
||||||
|
{
|
||||||
|
$userRepo = new UserRepo();
|
||||||
|
|
||||||
|
$user = $userRepo->findById($order->owner_id);
|
||||||
|
|
||||||
|
$text = kg_ph_replace("开单啦,{user.name} 同学完成了订单!\n订单名称:{order.subject}\n订单金额:¥{order.amount}", [
|
||||||
|
'user.name' => $user->name,
|
||||||
|
'order.subject' => $order->subject,
|
||||||
|
'order.amount' => $order->amount,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->send(['text' => $text]);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
214
app/Services/DingTalkNotice.php
Normal file
214
app/Services/DingTalkNotice.php
Normal file
@ -0,0 +1,214 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Services;
|
||||||
|
|
||||||
|
use App\Repos\Account as AccountRepo;
|
||||||
|
use App\Repos\Course as CourseRepo;
|
||||||
|
use GuzzleHttp\Client as HttpClient;
|
||||||
|
use Phalcon\Logger\Adapter\File as FileLogger;
|
||||||
|
|
||||||
|
class DingTalkNotice extends Service
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $settings;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var FileLogger
|
||||||
|
*/
|
||||||
|
protected $logger;
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->settings = $this->getSettings('dingtalk.robot');
|
||||||
|
|
||||||
|
$this->logger = $this->getLogger('dingtalk');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 测试消息
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function test()
|
||||||
|
{
|
||||||
|
$params = [
|
||||||
|
'msgtype' => 'text',
|
||||||
|
'text' => ['content' => '我是一条测试消息啦!'],
|
||||||
|
];
|
||||||
|
|
||||||
|
return $this->send($params);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 给技术人员发消息
|
||||||
|
*
|
||||||
|
* @param string $content
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function atTechSupport($content)
|
||||||
|
{
|
||||||
|
$atMobiles = $this->parseAtMobiles($this->settings['ts_mobiles']);
|
||||||
|
$atContent = $this->buildAtContent($content, $atMobiles);
|
||||||
|
|
||||||
|
$params = [
|
||||||
|
'msgtype' => 'text',
|
||||||
|
'text' => ['content' => $atContent],
|
||||||
|
'at' => ['atMobiles' => $atMobiles],
|
||||||
|
];
|
||||||
|
|
||||||
|
return $this->send($params);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 给客服人员发消息
|
||||||
|
*
|
||||||
|
* @param string $content
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function atCustomService($content)
|
||||||
|
{
|
||||||
|
$atMobiles = $this->parseAtMobiles($this->settings['cs_mobiles']);
|
||||||
|
$atContent = $this->buildAtContent($content, $atMobiles);
|
||||||
|
|
||||||
|
$params = [
|
||||||
|
'msgtype' => 'text',
|
||||||
|
'text' => ['content' => $atContent],
|
||||||
|
'at' => ['atMobiles' => $atMobiles],
|
||||||
|
];
|
||||||
|
|
||||||
|
return $this->send($params);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 给课程讲师发消息
|
||||||
|
*
|
||||||
|
* @param int $courseId
|
||||||
|
* @param string $content
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function atCourseTeacher($courseId, $content)
|
||||||
|
{
|
||||||
|
$courseRepo = new CourseRepo();
|
||||||
|
|
||||||
|
$course = $courseRepo->findById($courseId);
|
||||||
|
|
||||||
|
$accountRepo = new AccountRepo();
|
||||||
|
|
||||||
|
$account = $accountRepo->findById($course->teacher_id);
|
||||||
|
|
||||||
|
if (empty($account->phone)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$atMobiles = $account->phone;
|
||||||
|
|
||||||
|
$atContent = $this->buildAtContent($content, $atMobiles);
|
||||||
|
|
||||||
|
$params = [
|
||||||
|
'msgtype' => 'text',
|
||||||
|
'text' => ['content' => $atContent],
|
||||||
|
'at' => ['atMobiles' => $atMobiles],
|
||||||
|
];
|
||||||
|
|
||||||
|
return $this->send($params);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送消息
|
||||||
|
*
|
||||||
|
* @param array $params
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function send($params)
|
||||||
|
{
|
||||||
|
if (isset($params['msgtype'])) {
|
||||||
|
$params['msgtype'] = 'text';
|
||||||
|
}
|
||||||
|
|
||||||
|
$webHook = "https://oapi.dingtalk.com/robot/send?access_token=%s×tamp=%s&sign=%s";
|
||||||
|
|
||||||
|
$appSecret = $this->settings['app_secret'];
|
||||||
|
$appToken = $this->settings['app_token'];
|
||||||
|
|
||||||
|
$timestamp = time() * 1000;
|
||||||
|
$data = sprintf("%s\n%s", $timestamp, $appSecret);
|
||||||
|
$sign = urlencode(base64_encode(hash_hmac('sha256', $data, $appSecret, true)));
|
||||||
|
$postUrl = sprintf($webHook, $appToken, $timestamp, $sign);
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
$client = new HttpClient();
|
||||||
|
|
||||||
|
$response = $client->post($postUrl, ['json' => $params]);
|
||||||
|
|
||||||
|
$content = $response->getBody()->getContents();
|
||||||
|
|
||||||
|
$content = json_decode($content, true);
|
||||||
|
|
||||||
|
$this->logger->debug('Send Message Request ' . kg_json_encode($params));
|
||||||
|
|
||||||
|
$this->logger->debug('Send Message Response ' . kg_json_encode($content));
|
||||||
|
|
||||||
|
$result = $content['errcode'] == 0;
|
||||||
|
|
||||||
|
if ($result == false) {
|
||||||
|
$this->logger->error('Send Message Failed ' . kg_json_encode($content));
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
|
||||||
|
$this->logger->error('Send Message Exception ' . kg_json_encode([
|
||||||
|
'file' => $e->getFile(),
|
||||||
|
'line' => $e->getLine(),
|
||||||
|
'message' => $e->getMessage(),
|
||||||
|
]));
|
||||||
|
|
||||||
|
$result = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $mobiles
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
protected function parseAtMobiles($mobiles)
|
||||||
|
{
|
||||||
|
if (empty($mobiles)) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
$mobiles = explode(',', $mobiles);
|
||||||
|
|
||||||
|
return array_map(function ($mobile) {
|
||||||
|
return trim($mobile);
|
||||||
|
}, $mobiles);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $content
|
||||||
|
* @param array $mobiles
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
protected function buildAtContent($content, $mobiles = [])
|
||||||
|
{
|
||||||
|
if (count($mobiles) == 0) {
|
||||||
|
return $content;
|
||||||
|
}
|
||||||
|
|
||||||
|
$result = '';
|
||||||
|
|
||||||
|
foreach ($mobiles as $mobile) {
|
||||||
|
$result .= sprintf('@%s ', $mobile);
|
||||||
|
}
|
||||||
|
|
||||||
|
$result .= $content;
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
42
db/migrations/20210215024511_data_202102151130.php
Normal file
42
db/migrations/20210215024511_data_202102151130.php
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
class Data202102151130 extends Phinx\Migration\AbstractMigration
|
||||||
|
{
|
||||||
|
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
$rows = [
|
||||||
|
[
|
||||||
|
'section' => 'dingtalk.robot',
|
||||||
|
'item_key' => 'app_secret',
|
||||||
|
'item_value' => '',
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'section' => 'dingtalk.robot',
|
||||||
|
'item_key' => 'app_token',
|
||||||
|
'item_value' => '',
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'section' => 'dingtalk.robot',
|
||||||
|
'item_key' => 'ts_mobiles',
|
||||||
|
'item_value' => '',
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'section' => 'dingtalk.robot',
|
||||||
|
'item_key' => 'cs_mobiles',
|
||||||
|
'item_value' => '',
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
$this->table('kg_setting')->insert($rows)->save();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
$this->getQueryBuilder()
|
||||||
|
->delete('kg_setting')
|
||||||
|
->where(['section' => 'dingtalk.robot'])
|
||||||
|
->execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -25,6 +25,9 @@ $scheduler->php($script, $bin, ['--task' => 'vod_event', '--action' => 'main'])
|
|||||||
$scheduler->php($script, $bin, ['--task' => 'close_trade', '--action' => 'main'])
|
$scheduler->php($script, $bin, ['--task' => 'close_trade', '--action' => 'main'])
|
||||||
->at('*/13 * * * *');
|
->at('*/13 * * * *');
|
||||||
|
|
||||||
|
$scheduler->php($script, $bin, ['--task' => 'monitor', '--action' => 'main'])
|
||||||
|
->at('*/12 * * * *');
|
||||||
|
|
||||||
$scheduler->php($script, $bin, ['--task' => 'point_gift_deliver', '--action' => 'main'])
|
$scheduler->php($script, $bin, ['--task' => 'point_gift_deliver', '--action' => 'main'])
|
||||||
->at('*/11 * * * *');
|
->at('*/11 * * * *');
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user