本文目录导读:

将 PHP 项目接入钉钉机器人,主要分为两种场景:
- 群机器人(Webhook):向钉钉群发送消息通知(如报警、日志、订单提醒),最常见。
- 应用机器人(Stream/HTTP):接收并回复用户的消息(类似客服或 ChatBot),交互更复杂。
下面分别提供这两种场景的详细接入步骤和 PHP 代码示例。
群机器人(发送消息)
这是最常用的方式,主要用于将系统事件推送到钉钉群,不需要复杂的认证,操作简单。
创建群机器人
- 步骤:在钉钉目标群里,点击群设置 -> 智能群助手 -> 添加机器人 -> 选择“自定义”(通过 Webhook 接入)。
- 关键信息:
Webhook URL:https://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 模式。