If you copy $FinalURL and use curl to send it from a command line does it successfully send the message in Telegram?
400 errors are “bad request”, usually meaning the request URL is malformed.
When I copy the URL generated in the log and use it both in the browser and with curl, the sending works normally.
However, when passing the commands to the “fetch” instruction, the 400 error occurs.
I have the impression that some characters are not accepted in the “fetch” instruction and, as a result, are not correctly sent to the Telegram API.
Do you have any documentation about the Telegram API and how the request is supposed to be created? If you do a little research we may be able to help, but just asking ChatCCP isn’t going to get you any closer to an answer.
This is the format accepted by the Telegram API. In the Mikrotik script, just for testing, I made this code and it worked:
:local CHID "1215501525";
:local BotID "1450359051:AAFn4kwwwQ0LSl1xhqSFsxwPruiKWepexx0";
:local Message "Boss, ok RB 1!";
/tool fetch url="https://api.telegram.org/bot$BotID/sendmessage\?chat_id=$CHID&text=$Message" keep-result=no;
The strangest part is that when generating the log with :log info ("Final URL for sending: " . $FinalURL);, the Telegram API responds correctly.
This statement is just printing $FinalURL into the Mikrotik log. The “Telegram API” is not contacted, and does not reply to anything. Telegram is only contacted in the “fetch” statement.
Correct, I had the $FinalURL printed in the log to identify the possible issue. When I copied and pasted the URL generated in $FinalURL into the browser, with the correctly formatted data, it worked perfectly.
However, when the $FinalURL is passed to the “fetch” command, the 400 error occurs.
So, I decided to try a different approach to see if it would work, and it did. I received the message from Telegram with the code below. However, this method is more complex than what could be done directly with the Mikrotik script:
script Mikrotik
# Definir constantes
:local ServerURL "https://mydomain.com/api/telegram.php";
:local DeviceName [/system identity get name];
:local InstVer [/system package update get installed-version];
:local LatVer [/system package update get latest-version];
:local Chan [/system package update get channel];
:local postData "{ \"instVer\": \"$InstVer\", \"latVer\": \"$LatVer\", \"chan\": \"$Chan\", \"deviceName\": \"$DeviceName\" }";
/tool fetch url=$ServerURL http-method=post http-header-field="Content-Type: application/json" http-data=$postData keep-result=no;
:log info ("Dados enviados para servidor PHP: Versão instalada: " . $InstVer . ", Versão disponível: " . $LatVer . ", Canal: " . $Chan);
PHP Code telegram.php
<?php
$data = json_decode(file_get_contents("php://input"), true);
if (!$data || !isset($data["instVer"]) || !isset($data["latVer"]) || !isset($data["chan"]) || !isset($data["deviceName"])) {
http_response_code(400);
echo json_encode(["status" => "error", "message" => "Dados inválidos"]);
exit;
}
$instVer = $data["instVer"];
$latVer = $data["latVer"];
$chan = $data["chan"];
$deviceName = $data["deviceName"];
$jsonFile = $deviceName . '_data.json';
$botToken = "BOTID AQUI";
$chatID = "CHATID AQUI";
function updateOrCreateJsonFile($jsonFile, $data) {
if (file_exists($jsonFile)) {
$fileData = json_decode(file_get_contents($jsonFile), true);
} else {
$fileData = [];
}
if (isset($fileData['data'])) {
$deviceData = $fileData['data'];
if ($deviceData['instVer'] !== $data['instVer'] || $deviceData['latVer'] !== $data['latVer']) {
$data['expiration'] = date('Y-m-d H:i:s', strtotime('+0 seconds'));
} else {
if (strtotime($deviceData['expiration']) > time()) {
return false;
}
}
} else {
$data['expiration'] = date('Y-m-d H:i:s', strtotime('+24 hours'));
}
$fileData['data'] = [
'instVer' => $data['instVer'],
'latVer' => $data['latVer'],
'chan' => $data['chan'],
'deviceName' => $data['deviceName'],
'expiration' => $data['expiration']
];
file_put_contents($jsonFile, json_encode($fileData, JSON_PRETTY_PRINT));
return true;
}
if (updateOrCreateJsonFile($jsonFile, $data)) {
$message = "️[" . $deviceName . "]: ";
if ($instVer === $latVer) {
$message .= "O sistema já está atualizado. Changelogs: https://mikrotik.com/download/changelogs [Versão instalada: " . $instVer . ", Canal: " . $chan . "]";
} else {
$message .= "Nova versão " . $latVer . " disponível! Changelogs: https://mikrotik.com/download/changelogs [Versão instalada: " . $instVer . ", Canal: " . $chan . "]";
}
$url = "https://api.telegram.org/bot$botToken/sendMessage?chat_id=$chatID&text=" . urlencode($message);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode == 200) {
echo json_encode(["status" => "success", "message" => "Mensagem enviada com sucesso"]);
} else {
echo json_encode(["status" => "error", "message" => "Falha ao enviar mensagem"]);
}
} else {
echo json_encode(["status" => "success", "message" => "Mensagem não enviada. O sistema já está atualizado e a expiração ainda não passou."]);
}
?>