diff --git a/app/Console/Tasks/CleanLogTask.php b/app/Console/Tasks/CleanLogTask.php index e198d702..581d6163 100644 --- a/app/Console/Tasks/CleanLogTask.php +++ b/app/Console/Tasks/CleanLogTask.php @@ -26,6 +26,7 @@ class CleanLogTask extends Task $this->cleanOrderLog(); $this->cleanRefundLog(); $this->cleanPointLog(); + $this->cleanDingTalkLog(); $this->cleanNoticeLog(); $this->cleanOtherLog(); } @@ -234,6 +235,18 @@ class CleanLogTask extends Task $this->whitelist[] = $type; } + /** + * 清理钉钉日志 + */ + protected function cleanDingTalkLog() + { + $type = 'dingtalk'; + + $this->cleanLog($type, 7); + + $this->whitelist[] = $type; + } + /** * 清理通知日志 */ diff --git a/app/Http/Admin/Controllers/SettingController.php b/app/Http/Admin/Controllers/SettingController.php index 76cff636..c7734972 100644 --- a/app/Http/Admin/Controllers/SettingController.php +++ b/app/Http/Admin/Controllers/SettingController.php @@ -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); + } + } + } diff --git a/app/Http/Admin/Controllers/TestController.php b/app/Http/Admin/Controllers/TestController.php index 4db114d2..d159935d 100644 --- a/app/Http/Admin/Controllers/TestController.php +++ b/app/Http/Admin/Controllers/TestController.php @@ -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\WxpayTest as WxpayTestService; use App\Services\Captcha as CaptchaService; +use App\Services\DingTalkNotice as DingTalkNoticeService; use App\Services\Live as LiveService; use App\Services\Mail\Test as TestMailService; use App\Services\MyStorage as StorageService; @@ -250,4 +251,20 @@ class TestController extends Controller 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' => '发送消息失败,请检查配置']); + } + } + } \ No newline at end of file diff --git a/app/Http/Admin/Services/AuthNode.php b/app/Http/Admin/Services/AuthNode.php index 20dedbb5..374aa629 100644 --- a/app/Http/Admin/Services/AuthNode.php +++ b/app/Http/Admin/Services/AuthNode.php @@ -800,6 +800,12 @@ class AuthNode extends Service 'type' => 'menu', 'route' => 'admin.setting.wechat_oa', ], + [ + 'id' => '5-1-15', + 'title' => '钉钉机器人', + 'type' => 'menu', + 'route' => 'admin.setting.dingtalk_robot', + ], [ 'id' => '5-1-14', 'title' => '积分设置', diff --git a/app/Library/Benchmark.php b/app/Library/Benchmark.php new file mode 100644 index 00000000..e6943787 --- /dev/null +++ b/app/Library/Benchmark.php @@ -0,0 +1,27 @@ +startTime = microtime(true); + } + + public function stop() + { + $this->endTime = microtime(true); + } + + public function getElapsedTime() + { + return $this->endTime - $this->startTime; + } + +} \ No newline at end of file diff --git a/app/Library/Helper.php b/app/Library/Helper.php index af1d528a..47363e5c 100644 --- a/app/Library/Helper.php +++ b/app/Library/Helper.php @@ -35,6 +35,24 @@ function kg_substr($str, $start, $length, $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封装 * diff --git a/app/Models/Task.php b/app/Models/Task.php index de8cb067..eb63af53 100644 --- a/app/Models/Task.php +++ b/app/Models/Task.php @@ -17,7 +17,7 @@ class Task extends Model * 针对外部用户 */ 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_REFUND_FINISH = 14; // 退款完成通知 const TYPE_NOTICE_CONSULT_REPLY = 15; // 咨询回复通知 diff --git a/app/Services/DingTalkNotice.php b/app/Services/DingTalkNotice.php new file mode 100644 index 00000000..fad0c1f0 --- /dev/null +++ b/app/Services/DingTalkNotice.php @@ -0,0 +1,214 @@ +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; + } + +} \ No newline at end of file