如何将PHP项目接入钉钉机器人?

wen PHP项目 7

本文目录导读:

如何将PHP项目接入钉钉机器人?

  1. 场景一:群机器人(发送消息)
  2. 场景二:应用机器人(接收与回复消息)
  3. 总结选择

将 PHP 项目接入钉钉机器人,主要分为两种场景:

  1. 群机器人(Webhook):向钉钉群发送消息通知(如报警、日志、订单提醒),最常见。
  2. 应用机器人(Stream/HTTP):接收并回复用户的消息(类似客服或 ChatBot),交互更复杂。

下面分别提供这两种场景的详细接入步骤和 PHP 代码示例。


群机器人(发送消息)

这是最常用的方式,主要用于将系统事件推送到钉钉群,不需要复杂的认证,操作简单。

创建群机器人

  • 步骤:在钉钉目标群里,点击群设置 -> 智能群助手 -> 添加机器人 -> 选择“自定义”(通过 Webhook 接入)。
  • 关键信息
    • Webhook URLhttps://oapi.dingtalk.com/robot/send?access_token=xxxxx
    • 安全设置
      • 方式1(推荐):加签(Secret),需要将时间戳和 Secret 拼接后做 HmacSHA256 签名,添加到请求中。
      • 方式2:自定义关键词,消息中必须包含该关键词。
      • 方式3:IP 地址段,只允许指定 IP 调用。

PHP 代码实现(使用 cURL)

以下代码封装了加签发送消息的逻辑,兼容常用消息类型。

<?php
class DingTalkRobot
{
    private $webhookUrl;
    private $secret;
    /**
     * @param string $webhookUrl 钉钉机器人的 Webhook 地址
     * @param string $secret 安全设置的加签密钥 (如果不加签,传空字符串)
     */
    public function __construct($webhookUrl, $secret = '')
    {
        $this->webhookUrl = $webhookUrl;
        $this->secret = $secret;
    }
    /**
     * 生成签名(用于加签模式)
     * @return string 拼接了 timestamp 和 sign 的完整 URL
     */
    private function generateSignedUrl()
    {
        if (empty($this->secret)) {
            return $this->webhookUrl;
        }
        $timestamp = round(microtime(true) * 1000);
        $stringToSign = $timestamp . "\n" . $this->secret;
        $sign = base64_encode(hash_hmac('sha256', $stringToSign, $this->secret, true));
        // 追加到 URL
        return $this->webhookUrl . "×tamp=" . $timestamp . "&sign=" . urlencode($sign);
    }
    /**
     * 发送消息
     * @param array $data 消息体数组
     * @return array 响应结果 ['errcode' => 0, 'errmsg' => 'ok']
     */
    public function send($data)
    {
        $url = $this->generateSignedUrl();
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
        curl_setopt($ch, CURLOPT_HTTPHEADER, [
            'Content-Type: application/json',
        ]);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_TIMEOUT, 10);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // 本地调试建议 false,生产环境建议 true
        $response = curl_exec($ch);
        $error = curl_error($ch);
        curl_close($ch);
        if ($error) {
            return ['errcode' => -1, 'errmsg' => 'cURL error: ' . $error];
        }
        return json_decode($response, true);
    }
    // ---------- 便捷消息封装 ----------
    /**
     * 发送文本消息
     * @param string $content 消息内容
     * @param array $atMobiles 被@人的手机号列表
     * @param bool $isAtAll 是否@所有人
     */
    public function sendText($content, $atMobiles = [], $isAtAll = false)
    {
        $data = [
            'msgtype' => 'text',
            'text' => [
                'content' => $content,
            ],
            'at' => [
                'atMobiles' => $atMobiles,
                'isAtAll' => $isAtAll,
            ],
        ];
        return $this->send($data);
    }
    /**
     * 发送 Markdown 消息
     * @param string $title 标题(用于首屏)
     * @param string $markdownContent 支持 Markdown 的正文
     */
    public function sendMarkdown($title, $markdownContent)
    {
        $data = [
            'msgtype' => 'markdown',
            'markdown' => [
                'title' => $title,
                'text' => $markdownContent,
            ],
        ];
        return $this->send($data);
    }
    /**
     * 发送 ActionCard 消息
     */
    public function sendActionCard($title, $text, $singleTitle, $singleURL)
    {
        $data = [
            'msgtype' => 'actionCard',
            'actionCard' => [
                'title' => $title,
                'text' => $text,
                'btnOrientation' => '0', // 0: 按钮竖直排列, 1: 水平排列
                'singleTitle' => $singleTitle,
                'singleURL' => $singleURL,
            ],
        ];
        return $this->send($data);
    }
}
// -------------------- 使用示例 --------------------
// 1. 初始化(将 YOUR_WEBHOOK_URL 和 YOUR_SECRET 替换为你的真实信息)
$webhookUrl = 'https://oapi.dingtalk.com/robot/send?access_token=YOUR_ACCESS_TOKEN';
$secret = 'YOUR_SECRET'; // 如果没加签,传空字符串 ''
$robot = new DingTalkRobot($webhookUrl, $secret);
// 2. 发送文本消息(无需@)
$result = $robot->sendText('【订单通知】新订单 #12345 已创建');
// 3. 发送 Markdown 消息(支持加粗、链接、列表)
$markdown = "## 📢 服务器告警\n";
$markdown .= "- **服务器**: 生产01\n";
$markdown .= "- **状态**: CPU 使用率 95%\n";
$markdown .= "- [查看详情](http://example.com)";
$result = $robot->sendMarkdown('告警通知', $markdown);
// 4. 检查结果
if ($result['errcode'] === 0) {
    echo "消息发送成功!";
} else {
    echo "发送失败:" . $result['errmsg'];
}

注意事项

  • 如果设置了,消息内容必须包含该关键词,否则会被钉钉过滤。
  • 消息频率有限制(每个机器人每分钟最多 20 条),过多消息会被限流。

应用机器人(接收与回复消息)

如果需要实现对话交互(用户向机器人发消息,机器人处理后回复),需要创建“应用机器人”,旧方案使用 HTTP 回调(需公网固定IP),新推荐方案是 Stream 模式(WebSocket),无需公网 IP

Stream 模式接入(推荐,无需公网 IP)

  • 准备
    • 在钉钉开发者后台创建“企业内部应用”或“第三方企业应用”。
    • 开启“机器人与消息推送”功能。
    • 获取应用的 clientId(即 AppKey)和 clientSecret
  • 原理:你的本地 PHP 应用通过 WebSocket 连接到钉钉服务端,服务端将用户消息转发到你的应用,应用处理后再发回。

PHP 接入 Stream 模式(使用官方 SDK)

钉钉提供了官方的 PHP SDK (dingtalk/robot-stream) 来处理连接和消息。

安装步骤

composer require dingtalk/robot-stream

核心代码(demo.php):

<?php
require_once __DIR__ . '/vendor/autoload.php';
use GuzzleHttp\Client;
use DingTalk\Robot\RobotStreamClient;
use DingTalk\Robot\Message\TextMessage;
use DingTalk\Robot\Message\MarkdownMessage;
use Psr\Log\AbstractLogger;
// 1. 配置日志(可选,方便调试)
class SimpleLogger extends AbstractLogger
{
    public function log($level, $message, array $context = [])
    {
        echo "[{$level}] {$message}" . PHP_EOL;
    }
}
// 2. 初始化客户端(传入你的 AppKey 和 AppSecret)
$clientId = 'your_app_key'; // 从应用详情页获取
$clientSecret = 'your_app_secret'; // 从应用详情页获取
$logger = new SimpleLogger();
// 3. 创建 RobotStreamClient 实例
$robotClient = new RobotStreamClient($clientId, $clientSecret, $logger);
// 4. 设置消息回调(当用户@机器人时触发)
$robotClient->setMessageHandler(function ($messageData) use (&$robotClient) {
    // $messageData 结构包含: senderId, senderNick, conversationType, text/content 等
    $senderId = $messageData->getSenderId(); // 发送者 userId
    $content = $messageData->getText()->getContent(); // 用户发来的文本消息
    // 根据用户消息进行处理,构建回复
    if (strpos($content, '你好') !== false) {
        $replyText = "你好!我是 PHP 机器人。\n\n你可以输入:\n- 天气\n- 时间";
    } elseif ($content === '时间') {
        $replyText = "当前时间:" . date('Y-m-d H:i:s');
    } else {
        $replyText = "收到:「{$content}」,我还不理解,再试试别的吧。";
    }
    // 发送回复消息(调用官方 SDK 的 reply 方法)
    $robotClient->replyMessageText($replyText, $messageData);
    // 或者回复 Markdown:
    // $robotClient->replyMessage(new MarkdownMessage("标题\n**加粗**\n- 列表"), $messageData);
});
// 5. 启动服务(保持连接)
echo "机器人服务启动中...\n";
$robotClient->run();

运行方式

# 在命令行运行(需保持终端开启)
php demo.php
  • 优势:无公共 IP 要求,长连接,稳定,官方维护。
  • 缺点:PHP 脚本需常驻后台(守护进程),建议配合 Supervisor 使用。

总结选择

场景 方案 适用场景 实现难度
只发消息 群机器人(Webhook) 监控报警、订单通知、日志推送 ★☆☆☆☆
收发消息 应用机器人(Stream) 客服机器人、AI 对话、内部工具 ★★★★☆

建议

  • 如果你只是需要在 PHP 项目执行到某个点时(例如支付成功)通知运维/销售,用场景一的 Webhook,直接调用 sendText 即可。
  • 如果你要做一个能和用户在钉钉里对话的机器人,用场景二的 Stream 模式。

抱歉,评论功能暂时关闭!