零基础教你如何开发webman应用插件

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 . "&timestamp=$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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JPCstorm

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值