0X04 编写应用
菜单配置
菜单配置文件位置:plugin/dingdingtalk/config/menu.php
<?php
/**
* @desc 菜单配置
* @author Tinywan(ShaoBo Wan)
* @date 2024/5/4 18:28
*/
declare(strict_types=1);
return [
[
'title' => '钉钉机器人应用插件',
'icon' => 'layui-icon-template-1',
'href' => '/app/dingdingtalk/setting',
'pid' => 9,
'key' => \plugin\dingdingtalk\app\controller\SettingController::class,
'weight' => 10,
'type' => 1,
]
];
接口调用类
文件位置:plugin/dingdingtalk/api/DingDingtalk.php
<?php
/**
* @desc 接口调用类
* @author Tinywan(ShaoBo Wan)
* @date 2024/5/4 18:28
*/
declare(strict_types=1);
namespace plugin\dingdingtalk\api;
class DingDingtalk
{
/**
* Option表的name字段值
*/
const SETTING_OPTION_NAME = 'dingdingtalk';
/**
* 发送消息
* @param array $args
* @return bool|string
*/
public static function send(array $args)
{
$accessToken = $args['accessToken'];
$secret = $args['secret'];
$title = $args['title'];
$message = $args['message'] . " \n";
$data = [
'msgtype' => 'markdown',
'markdown' => [
'title' => $title,
'text' => $message
],
'at' => [
'isAtAll' => true
]
];
$orderPayUrl = 'https://oapi.dingtalk.com/robot/send?access_token=' . $accessToken;
return self::request_by_curl(self::_sign($orderPayUrl, $secret), json_encode($data, JSON_UNESCAPED_UNICODE));
}
/**
* @desc: 请求签名
* @param string $url
* @param string $secret
* @return string
* @author Tinywan(ShaoBo Wan)
*/
private static function _sign(string $url, string $secret): string
{
[$s1, $s2] = explode(' ', microtime());
$timestamp = (float)sprintf('%.0f', (floatval($s1) + floatval($s2)) * 1000);
$data = $timestamp . "\n" . $secret;
$signStr = base64_encode(hash_hmac('sha256', $data, $secret, true));
$signStr = utf8_encode(urlencode($signStr));
return $url . "×tamp=$timestamp&sign=$signStr";
}
/**
* @desc: 自定义请求类
* @param string $remote_server
* @param string $postString
* @return bool|string
* @author Tinywan(ShaoBo Wan)
*/
private static function request_by_curl(string $remote_server, string $postString)
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $remote_server);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json;charset=utf-8'));
curl_setopt($ch, CURLOPT_POSTFIELDS, $postString);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
$data = curl_exec($ch);
curl_close($ch);
return $data;
}
}
控制器编写
SettingController.php
文件位置:plugin/dingdingtalk/app/controller/SettingController.php
<?php
/**
* @desc 钉钉机器人配置控制器
* @author Tinywan(ShaoBo Wan)
* @date 2024/5/4 18:28
*/
declare(strict_types=1);
namespace plugin\dingdingtalk\app\controller;
use plugin\admin\app\model\Option;
use plugin\dingdingtalk\api\DingDingtalk;
use support\Request;
use support\Response;
class SettingController
{
/**
* @desc: 设置首页
* @return Response
* @author Tinywan(ShaoBo Wan)
*/
public function index(): Response
{
return view('setting/index');
}
/**
* @desc: 获取设置
* @return Response
* @author Tinywan(ShaoBo Wan)
*/
public function get(): Response
{
$name = DingDingtalk::SETTING_OPTION_NAME;
$setting = Option::where('name', $name)->value('value');
$setting = $setting ? json_decode($setting, true) : [];
return json(['code' => 0, 'msg' => 'ok', 'data' => $setting]);
}
/**
* @desc: 更改设置
* @param Request $request
* @return Response
* @author Tinywan(ShaoBo Wan)
*/
public function save(Request $request): Response
{
$data = [
'AccessToken' => $request->post('AccessToken'),
'Secret' => $request->post('Secret'),
];
$value = json_encode($data);
$name = DingDingtalk::SETTING_OPTION_NAME;
$option = Option::where('name', $name)->first();
if ($option) {
Option::where('name', $name)->update(['value' => $value]);
} else {
$option = new Option();
$option->name = $name;
$option->value = $value;
$option->save();
}
return json(['code' => 0, 'msg' => 'ok']);
}
/**
* 应用测试
* @param Request $request
* @return Response
* @author Tinywan(ShaoBo Wan)
*/
public function test(Request $request): Response
{
$option = Option::where('name', DingDingtalk::SETTING_OPTION_NAME)->value('value');
if (!$option) {
return json(['code' => 403, 'msg' => '请先配置签名']);
}
$jsonArr = json_decode($option, true);
$args = [
'accessToken' => $jsonArr['AccessToken'],
'secret' => $jsonArr['Secret'],
'title' => $request->post('Title', '机器人标题'),
'message' => $request->post('Content', '这是一个测试内容'),
];
DingDingtalk::send($args);
return json(['code' => 0, 'msg' => 'ok', 'data' => $option]);
}
}
控制器视图
index.html
文件位置:plugin/dingdingtalk/app/view/setting/index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>钉钉机器人设置</title>
<link rel="stylesheet" href="/app/admin/component/pear/css/pear.css"/>
<link rel="stylesheet" href="/app/admin/admin/css/reset.css"/>
</head>
<body class="pear-container">
<div class="layui-card">
<div class="layui-card-body">
<div class="layui-tab layui-tab-brief">
<ul class="layui-tab-title">
<li class="layui-this" permission="app.dingtalk.admin.setting.save">钉钉设置</li>
<li permission="app.dingtalk.admin.setting.test">演示测试</li>
</ul>
<div class="layui-tab-content">
<!-- 钉钉设置 -->
<div class="layui-tab-item layui-show">
<form class="layui-form" onsubmit="return false" lay-filter="setting" style="width: 520px">
<div class="layui-form-item">
<label class="layui-form-label">访问令牌</label>
<div class="layui-input-block">
<input type="text" name="AccessToken" required lay-verify="required" autocomplete="off"
class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">加签</label>
<div class="layui-input-block">
<input type="text" name="Secret" required lay-verify="required" autocomplete="off"
class="layui-input">
</div>
</div>
<div class="layui-form-item">
<div class="layui-input-block">
<button type="submit" class="pear-btn pear-btn-primary pear-btn-md" lay-submit=""
lay-filter="saveSetting">
保存设置
</button>
</div>
</div>
</form>
</div>
<div class="layui-tab-item">
<form class="layui-form" onsubmit="return false" lay-filter="test" style="width: 520px">
<div class="layui-form-item layui-form-text">
<label class="layui-form-label">测试标题</label>
<div class="layui-input-block">
<label>
<input type="text" name="Title" placeholder="请输入内容"
class="layui-input"></input>
</label>
</div>
</div>
<div class="layui-form-item layui-form-text">
<label class="layui-form-label">消息内容</label>
<div class="layui-input-block">
<label>
<textarea name="Content" placeholder="请输入内容" class="layui-textarea"></textarea>
</label>
</div>
</div>
<div class="layui-form-item">
<div class="layui-input-block">
<button type="submit" class="pear-btn pear-btn-danger pear-btn-md" lay-submit=""
lay-filter="sendMail">
测试
</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
<script src="/app/admin/component/layui/layui.js"></script>
<script src="/app/admin/component/pear/pear.js"></script>
<script src="/app/admin/admin/js/common.js"></script>
<!-- 测试 -->
<script>
layui.use(["form", "popup"], function () {
let form = layui.form;
let $ = layui.jquery;
$.ajax({
url: "/app/dingdingtalk/setting/get",
success: function (res) {
if (res.code) {
return layui.popup.failure(res.msg);
}
form.val("setting", res.data);
form.val("test", res.data);
}
});
// 保存设置
form.on("submit(saveSetting)", function (data) {
$.ajax({
url: "/app/dingdingtalk/setting/save",
dataType: "json",
type: "POST",
data: data.field,
success: function (res) {
if (res.code) {
return layui.popup.failure(res.msg);
}
form.val("test", data.field);
return layui.popup.success("操作成功");
}
});
return false;
});
// 测试表单
form.on("submit(sendMail)", function (data) {
$.ajax({
url: "/app/dingdingtalk/setting/test",
dataType: "json",
type: "POST",
data: data.field,
success: function (res) {
if (res.code) {
return layui.popup.failure(res.msg);
}
return layui.popup.success("操作成功");
}
});
return false;
});
});
</script>
<style>
.layui-input-block {
margin-left: 150px;
}
.layui-form-label {
width: 120px;
}
</style>
</body>
</html>
最终目录结构如下
├── dingdingtalk
│ ├── api
│ │ ├── DingDingtalk.php
│ │ └── Install.php
│ ├── app
│ │ ├── controller
│ │ │ └── SettingController.php
│ │ ├── functions.php
│ │ ├── middleware
│ │ ├── model
│ │ └── view
│ │ └── setting
│ │ └── index.html
│ ├── config
│ │ ├── app.php
│ │ ├── autoload.php
│ │ ├── container.php
│ │ ├── database.php
│ │ ├── exception.php
│ │ ├── log.php
│ │ ├── menu.php
│ │ ├── middleware.php
│ │ ├── process.php
│ │ ├── redis.php
│ │ ├── route.php
│ │ ├── static.php
│ │ ├── thinkorm.php
│ │ ├── translation.php
│ │ └── view.php
│ └── public