前言

此文章适用于QQ官方机器人,如果没有机器人的可以在QQ缩放平台申请一个☝🏻️🤓


代码配置

将下方代码编辑好后上传至任意站点目录,命中名为notify.php

<?php
define('BOT_APPID',     '123456789'); //机器人ID ( AppID )
define('BOT_SECRET',    '123456789'); //机器人密钥 ( AppSecret)
define('GROUP_OPENID',  '123456789'); //群号( 机器人加密过的 )

define('DEBUG_FILE', __DIR__ . '/push_debug.log'); //发送日志

header('Content-Type: application/json; charset=utf-8');

function curlPostJson(string $url, array $data, array $header = []): array {
    $ch = curl_init($url);
    $json = json_encode($data, JSON_UNESCAPED_UNICODE);
    $baseHeader = ["Content-Type: application/json; charset=utf-8"];
    curl_setopt_array($ch, [
        CURLOPT_POST           => true,
        CURLOPT_POSTFIELDS     => $json,
        CURLOPT_HTTPHEADER     => array_merge($baseHeader, $header),
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_SSL_VERIFYPEER => false,
        CURLOPT_SSL_VERIFYHOST => false,
        CURLOPT_TIMEOUT        => 15
    ]);
    $resp = curl_exec($ch);
    $err = curl_error($ch);
    curl_close($ch);
    if ($err) return ['error' => $err];
    return json_decode($resp, true) ?: [];
}

function getAccessToken(): string {
    $api = "https://bots.qq.com/app/getAppAccessToken";
    $ret = curlPostJson($api, [
        'appId'        => BOT_APPID,
        'clientSecret' => BOT_SECRET
    ]);
    file_put_contents(DEBUG_FILE, "[" . date('Y-m-d H:i:s') . "] 获取token: " . json_encode($ret, JSON_UNESCAPED_UNICODE) . "\n", FILE_APPEND | LOCK_EX);
    return $ret['access_token'] ?? '';
}

function sendMarkdownMsg(string $token, string $groupOpenid, string $content): array {
    $msgApiUrl = "https://api.sgroup.qq.com/v2/groups/";
    $authHeader = ["Authorization: QQBot {$token}"];
    $msgSeq = 16;
    $postData = [
        'msg_type' => 2,
        'msg_seq'  => $msgSeq,
        'markdown' => ['content' => $content]
    ];
    $result = curlPostJson($msgApiUrl . "{$groupOpenid}/messages", $postData, $authHeader);
    file_put_contents(DEBUG_FILE, "[" . date('Y-m-d H:i:s') . "] 发送结果: " . json_encode($result, JSON_UNESCAPED_UNICODE) . "\n", FILE_APPEND | LOCK_EX);
    return $result;
}

if (($_GET['type'] ?? '') !== '1' || $_SERVER['REQUEST_METHOD'] !== 'POST') {
    echo json_encode(['code' => 0, 'msg' => '请使用 POST ?type=1'], JSON_UNESCAPED_UNICODE);
    exit;
}

$rawData = file_get_contents('php://input');
if (empty($rawData)) {
    echo json_encode(['code' => 0, 'msg' => '无数据'], JSON_UNESCAPED_UNICODE);
    exit;
}

$notification = json_decode($rawData, true);
if (json_last_error() !== JSON_ERROR_NONE) {
    echo json_encode(['code' => 0, 'msg' => 'JSON格式错误'], JSON_UNESCAPED_UNICODE);
    exit;
}

$msg = $notification['msg'] ?? '';
$msg = strip_tags($msg);
$msg = preg_replace('/\n\s*\n/', "\n\n", $msg);

$token = getAccessToken();
if (!$token) {
    echo json_encode(['code' => 0, 'msg' => 'access_token 获取失败'], JSON_UNESCAPED_UNICODE);
    exit;
}

$pushResult = sendMarkdownMsg($token, GROUP_OPENID, $msg);

echo json_encode([
    'code' => 1,
    'msg'  => '已发送',
    'result' => $pushResult
], JSON_UNESCAPED_UNICODE);



宝塔配置

进入宝塔面板点击设置->警告设置->自定义消息通道->添加
名称:随意填
URL:https://你的路径/notify.php?type=1
请求方式:POST
参数格式:application/json
自定义参数:不用填
请求头:不用填


注意事项

1.请先在QQ开放平台把服务器IP添加到IP白名单
2.如果没接收到消息可查看push_debug.log文件,此文件为发送日志