Closed AntsHere closed 2 years ago
Сейчас попробовал тестовый проект создать. Ошибку воспроизвести не удалось, после установки пакетов из примера документации к php-http/discovery
.
"require": {
"biplane/yandex-direct": "^5.0",
"php-http/curl-client": "^2.2",
"guzzlehttp/psr7": "^2.1",
"php-http/message": "^1.12"
}
<?php
use Biplane\YandexDirect\ReportServiceFactory;
require 'vendor/autoload.php';
$factory = new ReportServiceFactory();
echo 'OK' . PHP_EOL;
Можно попробовать явно указать зависимости для ReportServiceFactory
. Если ошибки не будет, то можно проверить актуальность vendor/autoload.php
.
<?php
use Biplane\YandexDirect\ReportServiceFactory;
use GuzzleHttp\Psr7\HttpFactory;
use Http\Client\Curl\Client;
require 'vendor/autoload.php';
$httpFactory = new HttpFactory();
$httpClient = new Client($httpFactory, $httpFactory);
$factory = new ReportServiceFactory($httpClient, $httpFactory, $httpFactory);
echo 'OK' . PHP_EOL;
Ваш первый пример у меня выдает такую же ошибку, как и раньше.
Второй пимер выдает следующее:
Fatal error: Uncaught Error: Class 'GuzzleHttp\Psr7\HttpFactory' not found in \www\test.php:9 Stack trace: #0 {main} thrown in www\test.php on line 9
А какая версия PHP? И какая версия guzzlehttp/psr7
установлена?
$ composer show guzzlehttp/psr7
Можно попробовать nyholm/psr7
(именно эту реализацию использую в своих проектах), как альтернативу guzzlehttp/psr7
(если нет возможности установить ^2.0
).
Версия PHP - php-7.1.9-Win32-VC14-x86
Результат выполнения команды:
name : guzzlehttp/psr7
descrip. : PSR-7 message implementation that also provides common utility methods
keywords : http, message, psr-7, request, response, stream, uri, url
versions : * 1.8.3
type : library
license : MIT License (MIT) (OSI approved) https://spdx.org/licenses/MIT.html#licenseText
homepage :
source : [git] https://github.com/guzzle/psr7.git 1afdd860a2566ed3c2b0b4a3de6e23434a79ec85
dist : [zip] https://api.github.com/repos/guzzle/psr7/zipball/1afdd860a2566ed3c2b0b4a3de6e23434a79ec85 1afdd860a2566ed3c2b0b4a3de6e23434a79ec85
path : D:\Work\_test\vendor\guzzlehttp\psr7
names : guzzlehttp/psr7, psr/http-message-implementation
support
issues : https://github.com/guzzle/psr7/issues
source : https://github.com/guzzle/psr7/tree/1.8.3
autoload
psr-4
GuzzleHttp\Psr7\ => src/
files
requires
php >=5.4.0
psr/http-message ~1.0
ralouphie/getallheaders ^2.0.5 || ^3.0.0
requires (dev)
ext-zlib *
phpunit/phpunit ~4.8.36 || ^5.7.27 || ^6.5.14 || ^7.5.20 || ^8.5.8 || ^9.3.10
suggests
laminas/laminas-httphandlerrunner Emit PSR-7 responses
provides
psr/http-message-implementation 1.0
Установка nyholm/psr7 помогла. Еще, в процессе поиска решения в интернете, наткнулся на http-interop/http-factory-guzzle - тоже помогает.
Но возникает следующая проблема:
Fatal error: Uncaught Http\Client\Exception\RequestException: SSL certificate problem: unable to get local issuer certificate in www\vendor\php-http\curl-client\src\Client.php:166
Stack trace:
#0 www\vendor\biplane\yandex-direct\src\Api\V5\Reports.php(217): Http\Client\Curl\Client->sendRequest(Object(Nyholm\Psr7\Request))
#1 www\vendor\biplane\yandex-direct\src\Api\V5\Reports.php(74): Biplane\YandexDirect\Api\V5\Reports->doRequest(Object(Nyholm\Psr7\Request))
#2 www\main.php(941): Biplane\YandexDirect\Api\V5\Reports->get(Object(Biplane\YandexDirect\Api\V5\Reports\ReportRequest))
#3 {main}
thrown in www\vendor\php-http\curl-client\src\Client.php on line 166
Помогает в файле vendor\php-http\curl-client\src\Client.php добавить в опции "CURLOPT_SSL_VERIFYPEER => false". Однако это не не правильно с точки зрения безопасности. Можно как-то по-правильному решить эту проблему? В прошлой версии Biplane 4 с SSL проблем не было...
Можно как-то по-правильному решить эту проблему?
Можно отдельно скачать свежий бандл с сертификатами и обновить php.ini
curl.cainfo = <path/to/cacert.pem>
В прошлой версии Biplane 4 с SSL проблем не было...
Видимо, причина в том, что в 4 версии использовался guzzlehttp/guzzle
. Где есть логика определения актуального бандла с сертификатами, Utils::defaultCaBundle()
.
Можно php-http/curl-client
заменить на guzzlehttp/guzzle
. Должно решить проблему с сертификатами.
Можно
php-http/curl-client
заменить наguzzlehttp/guzzle
. Должно решить проблему с сертификатами.
Не помогает. Возвращается прежняя ошибка "Uncaught Http\Discovery\Exception\DiscoveryFailedException: Could not find resource using any discovery strategy.".
curl.cainfo = <path/to/cacert.pem>
Да, это помогает. Но, конечно, интереснее было бы использовать guzzlehttp/guzzle.
Не помогает. Возвращается прежняя ошибка
Нужен guzzlehttp/guzzle
версии 7.x, но эта версия совместима с PHP 7.2 и выше. Для PHP 7.1 устанавливается 6.x (предположение), а для этой версии нужен адаптер - php-http/guzzle6-adapter
.
Да, с адаптером начинает работать, но сваливается в похожую ошибку SSL:
Fatal error: Uncaught GuzzleHttp\Exception\RequestException: cURL error 60: SSL certificate problem: unable to get local issuer certificate (see https://curl.haxx.se/libcurl/c/libcurl-errors.html) in www\vendor\guzzlehttp\guzzle\src\Handler\CurlFactory.php:201
Stack trace:
#0 www\vendor\guzzlehttp\guzzle\src\Handler\CurlFactory.php(155): GuzzleHttp\Handler\CurlFactory::createRejection(Object(GuzzleHttp\Handler\EasyHandle), Array)
#1 www\vendor\guzzlehttp\guzzle\src\Handler\CurlFactory.php(105): GuzzleHttp\Handler\CurlFactory::finishError(Object(GuzzleHttp\Handler\CurlMultiHandler), Object(GuzzleHttp\Handler\EasyHandle), Object(GuzzleHttp\Handler\CurlFactory))
#2 www\vendor\guzzlehttp\guzzle\src\Handler\CurlMultiHandler.php(201): GuzzleHttp\Handler\CurlFactory::finish(Object(GuzzleHttp\Handler\CurlMultiHandler), Object(GuzzleHttp\Handler\EasyHandle), Object(GuzzleHttp\Handler\CurlFactory))
#3 in www\vendor\php-http\guzzle6-adapter\src\Promise.php on line 129
Если в php.ini вернуть опцию с cacert.pem, то начинает работать. То есть получается guzzlehttp/guzzle все равно не работает без cacert.pem в php.ini.
Решение с cacert.pem в целом помогло. Но вот тестирую сегодня работу новой версии Biplane (5) и постоянно сталкиваюсь с проблемами. То долго грузятся ответы. То вообще не загружаются (отваливаются по ограничению выполнения скрипта PHP). Ошибки бывают разными, к примеру:
Fatal error: Uncaught SoapFault exception: [WSDL] SOAP-ERROR: Parsing Schema: can't import schema from 'https://soap.direct.yandex.ru/v5/adextensiontypes.xsd' in \vendor\biplane\yandex-direct\src\Soap\ApiSoapClient.php:70 Stack trace: #0 \vendor\biplane\yandex-direct\src\Soap\ApiSoapClient.php(70): SoapClient->SoapClient('https://api.dir...', Array) #1 \vendor\biplane\yandex-direct\src\Api\ApiSoapClientV5.php(35): Biplane\YandexDirect\Soap\ApiSoapClient->__construct('https://api.dir...', Object(Biplane\YandexDirect\Config), Array) #2 \vendor\biplane\yandex-direct\src\Api\V5\Ads.php(200): Biplane\YandexDirect\Api\ApiSoapClientV5->__construct('https://api.dir...', Object(Biplane\YandexDirect\Config), Array) #3 [internal function]: Biplane\YandexDirect\Api\V5\Ads->__construct(Object(Biplane\YandexDirect\Config), Array) #4 \vendor\biplane\yandex-direct\src\Ap in \vendor\biplane\yandex-direct\src\Soap\ApiSoapClient.php on line 70
Warning: Uncaught SoapFault exception: [WSDL] SOAP-ERROR: Parsing WSDL: Couldn't load from 'https://api.direct.yandex.com/v5/keywordbids?wsdl' : failed to load external entity "https://api.direct.yandex.com/v5/keywordbids?wsdl" in \vendor\biplane\yandex-direct\src\Soap\ApiSoapClient.php:70 Stack trace: #0 \vendor\biplane\yandex-direct\src\Soap\ApiSoapClient.php(70): SoapClient->SoapClient('https://api.dir...', Array) #1 \vendor\biplane\yandex-direct\src\Api\ApiSoapClientV5.php(35): Biplane\YandexDirect\Soap\ApiSoapClient->__construct('https://api.dir...', Object(Biplane\YandexDirect\Config), Array) #2 \vendor\biplane\yandex-direct\src\Api\V5\KeywordBids.php(96): Biplane\YandexDirect\Api\ApiSoapClientV5->__construct('https://api.dir...', Object(Biplane\YandexDirect\Config), Array) #3 [internal function]: Biplane\YandexDirect\Api\V5\KeywordBids->__construct(Object(Biplane\YandexDirect\ in \vendor\biplane\yandex-direct\src\Soap\ApiSoapClient.php on line 70
Fatal error: Maximum execution time of 60 seconds exceeded in \vendor\biplane\yandex-direct\src\Api\ApiSoapClientV5.php on line 35
Вернулся на 4-ю версию. Все летает. Эксперимента ради добавил в файл vendor\php-http\curl-client\src\Client.php опцию "CURLOPT_SSL_VERIFYPEER => false" (уже писал про это выше) - сразу все стало работать быстро, как на 4-й версии.
Получается, решение с cacert.pem в php.ini в целом помогает, но все начинает как-то долго и с перебоями работать. Да, вспомнил, иногда вообще процесс Apache отваливается (тестирую в Windows 10).
То долго грузятся ответы. То вообще не загружаются (отваливаются по ограничению выполнения скрипта PHP).
В предыдущей версии по умолчанию было разрешено кеширование WSDL на диске.
В 5-й версии кеширование не используется по умолчанию. Так как кеширование в памяти работает не стабильно (можно словить segfault), а кеширование на диске без дополнительных настроек в docker-контейнерах малоэффективно.
Включить кеширование можно следующим образом:
use Biplane\YandexDirect\ConfigBuilder;
use Biplane\YandexDirect\Config\SoapOptions;
$soapOptions = SoapOptions::default()
->withWsdlCacheType(WSDL_CACHE_DISK);
$config = ConfigBuilder::create()
->setAccessToken('secret')
->setSoapOptions($soapOptions)
->getConfig();
Получается, решение с cacert.pem в php.ini в целом помогает, но все начинает как-то долго и с перебоями работать.
Если правильно понимаю, тут две независимые проблемы. Проблема с SSL касается сервиса Reports
, а проблема с таймаутами относится к SOAP сервисам.
Включить кеширование можно следующим образом:
Большое спасибо, помогло! Я, правда, пользуюсь new User($options)
, но там в $options
достаточно добавить 'soap_options' => SoapOptions::default()->withWsdlCacheType(WSDL_CACHE_DISK)
.
Если правильно понимаю, тут две независимые проблемы. Проблема с SSL касается сервиса
Reports
, а проблема с таймаутами относится к SOAP сервисам.
Да, согласен. Возможно, глобальное отключение проверки SSL как-то влияло на скорость соединения. Ну или так совпало...
Вообще, у меня есть предложение как-то все это задокументировать. Biplane 4 был удобен тем, что после выполнения composer require biplane/yandex-direct
у пользователя был готовый у рабое иснтрумент. Да, надо было разобраться во всех методах подключения, разобраться с API Яндекса, но сама баблиотека была готова по одной строке в консоли.
Сейчас же, даже имея бекграунд с 4-й версией, 5-я стала некотором испытанием. Её после установки надо вручную дорабатывать напильником. Это не очень удобно. Либо надо как-то на этапе установки предлагать доустановить нужные пакеты (или ставить их сразу), проверять подключение SSL, предалгать включить кеш. Либо все это прописать в иснтрукции по установке.
P.S. Спасибо вам большое за вашу работу! Это действительно очень мощный и удобный инструмент для работы с Директом.
Спасибо за обратную связь!
Что касается конфигурации по умолчанию, этот момент можно пересмотреть. Согласен, включение кеширования WSDL по умолчанию будет оправданным компромиссом.
По поводу http-клиента для сервиса отчетов. Мотивация в абстракции от конкретной реализации была в том, чтобы пользователю дать выбор - была возможность не устанавливать лишние зависимости, дублирующие функционал. Например, на своих проектах все чаще использую symfony/http-client. И могу переиспользовать эту реализацию, вместо установки сбоку ещё и guzzlehttp/guzzle.
Проблема с сертификатами, это наверное вопрос больше к окружению/инфраструктуре (для себя этот момент решаю с помощью конфигурации PHP). Решение на уровне библиотеки/http-клиента не будет являться системным. Завтра на проекте может появиться еще одна зависимость, где будет использоваться curl
и вопрос снова станет актуальным.
Начиная с версии 5.2.0
кеширование WSDL будет включено по умолчанию. Это должно решить проблему с долгим временем ожидания ответа при запросах к API.
Так же добавил в README абзац о том, что http-клиент нужно устанавливать самостоятельно.
Проблема с SSL должна решаться за рамками библиотеки, как мне кажется. Поэтому не знаю даже, как и что тут документировать.
Перешел с версии 4 на 5 (правда пока остался на Biplane\YandexDirect\User). Все работает, кроме загрузки отчетов. Все изменения по коду я внес (вместо Biplane\YandexDirect\Api\V5\Report теперь Biplane\YandexDirect\Api\V5\Reports). Но при попытке загрузить отчет, выдается следующая ошибка:
Сходил по ссылке http://docs.php-http.org/en/latest/discovery.html#common-errors , там предлагается выполнить "composer require php-http/curl-client guzzlehttp/psr7 php-http/message". Выполнил. Текст ошибки немного изменился, но суть вроде бы осталась старой:
Как заставить работать отчеты?