@Prosciutto
Постигаю

Почему cURL отправляет файл сертификата для Telegram-бота через терминал и через php по-разному?

Есть ТГ-бот, к которому я хочу прикрепить обработчик через веб-хук (метод setWebhook). Это можно сделать только используя защищенный протокол https. В качестве параметра метода нужно указать URL обработчика, и этого будет достаточно, если на стороне обработчика стоит SSL-сертификат, которому все доверяют. В моем случае я создал сам корневой CA, добавил у себя в ОС его в список доверенных корневых сертификатов и после чего подписал им уже частный сертификат для моего домена. Поэтому в моем случае в качестве параметра метода setWebhook нужно указать не тольок URL обработчика, но и отправить публичный ключ корневого CA в качестве параметра прям в виде файла, чтобы бот доверял серверу, где крутится обработчик.

Итак, делаю это при помощи командной строки и утилиты cURL:

curl -k -F "url=https://<MY_DOMAIN>/<HANDLER.php>" -F "certificate=@ca.pem" "https://api.telegram.org/bot**...**/setWebhook"

В качестве ответа получаю, что все ок. И все работает как надо. Проверяем, что SSL сертификат верифицируется:
https://api.telegram.org/bot**...**/getWebhookInfo
В ответ получаю
{"ok":true,"result":{"url":"https://<MY_DOMAIN>/<HANDLER.php>","has_custom_certificate":true,"pending_update_count":0,"max_connections":40,"ip_address":"176.226.195.198"}}


Но когда мне эту же процедуру нужно сделать при помощи php и модуля cURL, то возникает проблема:
<?php
echo '<pre>';

$result = setWebhook();
print_r($result);

echo '<pre>';

function setWebhook()
{
    $tgMethod = 'https://api.telegram.org/bot**...**/setWebhook';
    $urlHandler = 'https://<MY_DOMAIN>/<HANDLER.php>';
    $certPath = '../../ssl/ca.pem';
    $params = [
        'url' => $tgMethod,
        'certificate' => new CURLFile($certPath)
    ];
    $ch = curl_init();
    $options = [
        CURLOPT_URL => $tgMethod,
        CURLOPT_POST => true,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_HEADER => false,
        CURLOPT_POSTFIELDS => $params
    ];
    curl_setopt_array($ch, $options);
    $result = curl_exec($ch);

    return $result;
}


В ответ получаю, что все ок, но по факту не срабатывает вебхук. Получаем подробную инфу по вебхуку так же:
https://api.telegram.org/bot**...**/getWebhookInfo

В ответ получаем:
{"ok":true,"result":{"url":"https://api.telegram.org/bot**...**/setWebhook","has_custom_certificate":true,"pending_update_count":0,"last_error_date":1667813875,"last_error_message":"SSL error {error:0A000086:SSL routines::certificate verify failed}","max_connections":40,"ip_address":"149.154.167.220"}}


Т.е видно, что в обоих случаях сам файл подгружается, но отправленный через php SSL-серт не верифицируется.

У меня пока что сложилось такое впечатление, что проблема проистекает из символа "@", который ставится перед путем к отправляемому файлу. В документации указано, что при отправке самоподписанных сертификатов нужно ставить символ "@". И если его убрать от туда (из командной строки), то будет такая же ошибка, как при отправке через php (т.е ошибка верификации)! НО, БЛИН, как поставить этот символ внутрь объекта CURLFile, который обертывает файл для отправки по HTTP? Этот класс появился => PHP 5.6. Если "насильно" вставить в строку этот символ, то curl_exec() вернет false, т.е не сработает.
Есть ли у кого мысли на этот счет?
  • Вопрос задан
  • 1000 просмотров
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы