PHP 怎么对接钉钉通知

wen PHP项目 2

本文目录导读:

PHP 怎么对接钉钉通知

  1. 钉钉自定义机器人 Webhook(最常用)
  2. 企业微信/钉钉应用消息推送
  3. 使用 Guzzle HTTP 客户端(更现代的方式)
  4. 消息模板示例
  5. 异常处理与日志记录
  6. 注意事项

我来详细介绍 PHP 对接钉钉通知的几种方式:

钉钉自定义机器人 Webhook(最常用)

基础配置

首先在钉钉群中添加自定义机器人,获取 Webhook 地址和加签密钥。

签名算法实现

<?php
class DingTalkRobot
{
    private $webhook;
    private $secret;
    public function __construct($webhook, $secret = '')
    {
        $this->webhook = $webhook;
        $this->secret = $secret;
    }
    /**
     * 生成签名
     */
    private function getSign()
    {
        if (empty($this->secret)) {
            return '';
        }
        $timestamp = time() * 1000;
        $stringToSign = $timestamp . "\n" . $this->secret;
        $sign = base64_encode(hash_hmac('sha256', $stringToSign, $this->secret, true));
        $urlEncodeSign = urlencode($sign);
        return "&timestamp={$timestamp}&sign={$urlEncodeSign}";
    }
    /**
     * 发送消息
     */
    public function sendMessage($content, $type = 'text')
    {
        $url = $this->webhook . $this->getSign();
        switch ($type) {
            case 'text':
                $data = [
                    'msgtype' => 'text',
                    'text' => [
                        'content' => $content
                    ]
                ];
                break;
            case 'markdown':
                $data = [
                    'msgtype' => 'markdown',
                    'markdown' => [
                        'title' => '消息通知',
                        'text' => $content
                    ]
                ];
                break;
            default:
                return false;
        }
        return $this->httpRequest($url, $data);
    }
    /**
     * HTTP 请求
     */
    private function httpRequest($url, $data)
    {
        $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;charset=utf-8'
        ]);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_TIMEOUT, 10);
        $response = curl_exec($ch);
        $error = curl_error($ch);
        curl_close($ch);
        if ($error) {
            return ['success' => false, 'error' => $error];
        }
        return json_decode($response, true);
    }
    /**
     * 发送文本消息
     */
    public function sendText($content, $atMobiles = [], $isAtAll = false)
    {
        $data = [
            'msgtype' => 'text',
            'text' => [
                'content' => $content
            ],
            'at' => [
                'atMobiles' => $atMobiles,
                'isAtAll' => $isAtAll
            ]
        ];
        $url = $this->webhook . $this->getSign();
        return $this->httpRequest($url, $data);
    }
    /**
     * 发送 Markdown 消息
     */
    public function sendMarkdown($title, $markdownText, $atMobiles = [], $isAtAll = false)
    {
        $data = [
            'msgtype' => 'markdown',
            'markdown' => [
                'title' => $title,
                'text' => $markdownText
            ],
            'at' => [
                'atMobiles' => $atMobiles,
                'isAtAll' => $isAtAll
            ]
        ];
        $url = $this->webhook . $this->getSign();
        return $this->httpRequest($url, $data);
    }
}

使用示例

// 基础使用
$webhook = 'https://oapi.dingtalk.com/robot/send?access_token=XXXXX';
$secret = 'SECxxxxx'; // 如果有加签则填写
$ding = new DingTalkRobot($webhook, $secret);
// 发送普通文本
$result = $ding->sendText('你好,这是一条测试消息!');
// 发送@某人的消息
$result = $ding->sendText('任务完成,请查看', ['13800138000'], false);
// 发送 Markdown 消息
$markdown = "### 系统告警\n" .
            "> **服务器**: 192.168.1.1\n" .
            "> **CPU使用率**: 95%\n" .
            "> **内存使用率**: 89%\n" .
            "> 请尽快处理!";
$result = $ding->sendMarkdown('告警通知', $markdown);
// 检查发送结果
if (isset($result['errcode']) && $result['errcode'] === 0) {
    echo "发送成功";
} else {
    echo "发送失败:" . json_encode($result);
}

企业微信/钉钉应用消息推送

如果需要在应用内部推送,可以使用钉钉开放平台的 API:

<?php
class DingTalkApp {
    private $appKey;
    private $appSecret;
    private $agentId;
    public function __construct($appKey, $appSecret, $agentId)
    {
        $this->appKey = $appKey;
        $this->appSecret = $appSecret;
        $this->agentId = $agentId;
    }
    /**
     * 获取 access_token
     */
    public function getAccessToken()
    {
        $url = 'https://oapi.dingtalk.com/gettoken';
        $params = [
            'appkey' => $this->appKey,
            'appsecret' => $this->appSecret
        ];
        $response = $this->httpGet($url, $params);
        if ($response['errcode'] === 0) {
            return $response['access_token'];
        }
        return false;
    }
    /**
     * 发送工作通知消息
     */
    public function sendWorkNotification($userId, $content)
    {
        $accessToken = $this->getAccessToken();
        if (!$accessToken) {
            return false;
        }
        $url = 'https://oapi.dingtalk.com/topapi/message/corpconversation/asyncsend_v2?access_token=' . $accessToken;
        $data = [
            'agent_id' => $this->agentId,
            'userid_list' => $userId,
            'msg' => [
                'msgtype' => 'text',
                'text' => [
                    'content' => $content
                ]
            ]
        ];
        return $this->httpPost($url, $data);
    }
    // HTTP 请求方法实现...
}

使用 Guzzle HTTP 客户端(更现代的方式)

<?php
use GuzzleHttp\Client;
class DingTalkNotifier {
    private $webhook;
    private $client;
    public function __construct($webhook)
    {
        $this->webhook = $webhook;
        $this->client = new Client([
            'timeout' => 10,
            'verify' => false
        ]);
    }
    /**
     * 发送通知
     */
    public function send($message, $type = 'text', $atAll = false)
    {
        try {
            $payload = [
                'msgtype' => $type,
                $type => [
                    'content' => $message
                ]
            ];
            if ($atAll) {
                $payload['at'] = ['isAtAll' => true];
            }
            $response = $this->client->post($this->webhook, [
                'json' => $payload
            ]);
            $result = json_decode($response->getBody(), true);
            return $result['errcode'] === 0;
        } catch (\Exception $e) {
            return false;
        }
    }
}
// 使用
$notifier = new DingTalkNotifier('https://oapi.dingtalk.com/robot/send?access_token=XXXX');
$notifier->send('部署完成', 'text');

消息模板示例

<?php
class MessageBuilder {
    /**
     * 构建部署通知
     */
    public static function buildDeployMessage($project, $env, $status)
    {
        $color = $status === '成功' ? 'green' : 'red';
        return "### 构建通知\n" .
               "> **项目**: $project\n" .
               "> **环境**: $env\n" .
               "> **状态**: <font color='$color'>$status</font>\n" .
               "> **时间**: " . date('Y-m-d H:i:s');
    }
    /**
     * 构建系统告警
     */
    public static function buildAlertMessage($server, $metrics)
    {
        $text = "### 🚨 系统告警\n";
        foreach ($metrics as $key => $value) {
            $text .= "> **{$key}**: {$value}\n";
        }
        return $text;
    }
}

异常处理与日志记录

<?php
class DingTalkService {
    public function sendWithRetry($message, $maxRetries = 3)
    {
        $retries = 0;
        while ($retries < $maxRetries) {
            try {
                $result = $this->send($message);
                if ($result) {
                    $this->log('success', $message);
                    return true;
                }
            } catch (\Exception $e) {
                $this->log('error', $e->getMessage());
            }
            $retries++;
            sleep(2); // 等待2秒后重试
        }
        return false;
    }
    private function log($level, $message)
    {
        $log = sprintf("[%s] [%s] %s\n", date('Y-m-d H:i:s'), $level, $message);
        file_put_contents('/var/log/dingtalk.log', $log, FILE_APPEND);
    }
}

注意事项

  1. 安全限制:不要将 Webhook 地址暴露在公开代码中
  2. 频率限制:每个机器人每分钟最多发送 20 条消息
  3. 消息长度:文本消息不超过 5000 字符
  4. 敏感信息:不要在消息中发送敏感信息

就是 PHP 对接钉钉通知的主要方式,可以根据实际需求选择合适的方法。

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