Перестали работать запросы в WordPress: cURL error 60: SSL certificate has expired
C 30 сентября 2021 года на сайтах WordPress, для которых был установлен сертификат Let's Encrypt, могут перестать работать HTTP API запросы.
Например такой запрос будет выдавать ошибку:
$res = wp_remote_get( 'https://wp-kama.ru/' ); if( is_wp_error( $res ) ){ echo $res->get_error_message(); }
Получим:
cURL error 60: SSL certificate problem: certificate has expired
Такую ошибку можно будет увидеть где угодно, например:
- в админке при проверке обновлений WordPress
- при проверке обновлений плагинов
- при обращении к апи любого сервиса. Например, перестанет работать плагин TinyPNG — JPEG, PNG & WebP image compression и куча других, которые используют какие бы то ни было запросы.
Почему мы видим ошибку certificate has expired?
Почему так происходит подробно расписано на хабре.
Если коротко, то в ядре WP есть файл корневых сертификатов /wp-includes/certificates/ca-bundle.crt
который используется для проверки SSL всех запросов созданных через HTTP API. В этом файле просрочен один из корневых сертификатов на основе которого был создан сертификат для вашего сайта. Поэтому запрос не может пройти проверку и выдается такая ошибка.
С очередными обновлениями WP эта ошибка должна пропасть, но вот что делать если решение нужно уже сегодня, или если вы не планируете обновлять WordPress, а рабочие HTTP запросы нужны.
Решение ошибки: cURL error 60: SSL certificate has expired
Вариант 1
Нужно обновить контент файла /wp-includes/certificates/ca-bundle.crt
изменить его на контент этого файла https://curl.haxx.se/ca/cacert.pem.
Изменять в данном случае файл ядра допустимо, потому что при следующем обновлении WP проблема исчезнет. См. соответствующий коммит на GitHub.
Это можно сделать вручную:
- Скачайте файл по ссылке https://curl.haxx.se/ca/cacert.pem.
- Обновите контент
/wp-includes/certificates/ca-bundle.crt
контентом из скаченного файла.
Или используйте следующий код
Использовать код удобно, когда у вас есть возможность запустить код из админки или как-то еще, например через плагин Code Snippets.
Добавьте следующий код куда угодно и перейдите на страницу http://ВАШСАЙТ.com/?update-wp-ca-bundle
.
/** * Goto http://yoursite.com/?update-wp-ca-bundle */ if( isset( $_GET['update-wp-ca-bundle'] ) ){ $crt_file = ABSPATH . WPINC . '/certificates/ca-bundle.crt'; $new_crt_url = 'https://curl.haxx.se/ca/cacert.pem'; if( is_writable( $crt_file ) ){ $new_str = file_get_contents( $new_crt_url ); if( $new_str && strpos( $new_str, 'Bundle of CA Root Certificates' ) ){ $up = file_put_contents( $crt_file, $new_str ); echo $up ? 'OK: ca-bundle.crt updated' : 'ERROR: can`t put data to ca-bundle.crt'; } else { echo 'ERROR: cant download https://curl.haxx.se/ca/cacert.pem'; } } else { echo 'ERROR: ca-bundle.crt not writable'; } exit; }
После использования, код нужно удалить.
Вариант 2
Решить проблему можно через хук http_request_args. Этот хук нужно использовать в MU плагине.
-
Создайте файл
loader.php
в папкеwp-content/mu-plugins
(если такой папки у вас нет, создайте её). -
Добавьте следующий код в этот файл:
<?php require_once __DIR__ .'/fix-wp-ca-bundle/main.php';
-
Создайте папку
wp-content/mu-plugins/fix-wp-ca-bundle
. -
Создайте файлы:
main.php
иca-bundle.crt
в папкеfix-wp-ca-bundle
.Добавьте следующий код в эти файлы.
Код файла
main.php
:<?php defined( 'ABSPATH' ) || exit; /** * Update the path to the WordPress trusted root certificates. * * Actual certificates can be downloaded at this link: http://curl.haxx.se/ca/cacert.pem */ add_filter( 'http_request_args', 'http_request_change_sslsertificates' ); function http_request_change_sslsertificates( $parsed_args ){ $parsed_args[ 'sslcertificates' ] = __DIR__ . '/ca-bundle.crt'; return $parsed_args; }
Контент файла
ca-bundle.crt
:Скопируйте контент этого файла http://curl.haxx.se/ca/cacert.pem
Должна получится такая структура:
![](/wp-content/uploads/2021/10/clipboard-image-595992.png)
Готово! Теперь все должно работать как и прежде.