API Т‑Банка и сертификаты Минцифры: как использовать без установки на сервере
У меня есть Tg-бот, в нём я подключил оплату через платёжные ссылки Т-Банка. В какой-то момент ссылки перестали создаваться, в логах ошибка:
SSL certificate OpenSSL verify result: self-signed certificate in certificate chain (19)
Причина: Т и другие российские банки стали переходить на отечественные сертификаты, ибо зарубежные удостоверяющие центры стали отзывать свои сертификаты.
Варианты действий:
Подключить другую платёжку, которая (пока) не импортозаместила сертификаты.
Установить сертификаты на сервер (инструкция).
Вам потребуется определённая степень доверия родному государству.
На виртуальном хостинге так и вовсе может быть невозможно.
Собрать свою цепочку из сертификатов и использовать её только при запросах к API российских банков.
Подходит для виртуального хостинга.
Третьему варианту меня научила нейронка, вот порядок действий:
Скачать сертификаты.
Распаковать два архива и загрузить на сервер вот эти файлы:
russian_trusted_root_ca_pem.crt
russian_trusted_sub_ca_pem.crt
russian_trusted_sub_ca_2024_pem.crt
На сервере (у меня Ubuntu) скачать набор сертификатов от Mozilla:
curl -fsSL -o cacert.pem https://curl.se/ca/cacert.pem
Собрать объединённую цепочку:
cat \
cacert.pem \
russian_trusted_root_ca_pem.crt \
russian_trusted_sub_ca_pem.crt \
russian_trusted_sub_ca_2024_pem.crt \
> ru-ca-bundle.pem
Проверить, что работает:
curl -v --cacert ru-ca-bundle.pem https://mddc.tbank.ru/
Посмотреть сроки действия сертификатов:
openssl x509 -in russian_trusted_root_ca_pem.crt -noout -subject -issuer -dates
openssl x509 -in russian_trusted_sub_ca_pem.crt -noout -subject -issuer -dates
openssl x509 -in russian_trusted_sub_ca_2024_pem.crt -noout -subject -issuer -dates
Выбрать минимальную из дат и поставить себе напоминалку, чтобы обновить их.
Добавить использование этой цепочки в коде запросов к российским банкам.
У меня на php это выглядит так:
$caBundlePath = __DIR__ . '/ru-ca-bundle.pem';
if (!is_readable($caBundlePath)) {
myerror("Tinkoff CA bundle is not readable", ['path' => $caBundlePath]);
return false;
}
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => TINKOFF_INIT_URL,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $postDataJson,
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'Content-Length: ' . strlen($postDataJson),
],
CURLOPT_SSL_VERIFYPEER => true,
CURLOPT_SSL_VERIFYHOST => 2,
CURLOPT_CAINFO => $caBundlePath,
]);
$output = curl_exec($ch);
Таким образом, запросы к банку будут отправляться с использованием российских сертификатов, а все остальные — как и раньше, с использованием глобальных.