#php #laravel #guzzle
#php #laravel #guzzle
Вопрос:
Я создал простую оболочку вокруг REST api Shopify (частное приложение, использующее базовую аутентификацию), подобную этой, используя Guzzle:
<?php
namespace AppServices;
use stdClass;
use Exception;
use GuzzleHttpClient as GuzzleClient;
/**
* Class ShopifyService
* @package AppServices
*/
class ShopifyService
{
/**
* @var array $config
*/
private $config = [];
/**
* @var GuzzleClient$guzzleClient
*/
private $guzzleClient;
/**
* ShopifyService constructor.
*/
public function __construct()
{
$this->config = config('shopify');
}
/**
* @return ShopifyService
*/
public function Retail(): ShopifyService
{
return $this->initGuzzleClient(__FUNCTION__);
}
/**
* @return ShopifyService
*/
public function Trade(): ShopifyService
{
return $this->initGuzzleClient(__FUNCTION__);
}
/**
* @param string $uri
* @return stdClass
* @throws GuzzleHttpExceptionGuzzleException
* @throws Exception
*/
public function Get(string $uri): stdClass
{
$this->checkIfGuzzleClientInitiated();;
$result = $this->guzzleClient->request('GET', $uri);
return GuzzleHttpjson_decode($result->getBody());
}
/**
* @throws Exception
*/
private function checkIfGuzzleClientInitiated(): void
{
if (!$this->guzzleClient) {
throw new Exception('Guzzle Client Not Initiated');
}
}
/**
* @param string $storeName
* @return ShopifyService
*/
private function initGuzzleClient(string $storeName): ShopifyService
{
if (!$this->guzzleClient) {
$this->guzzleClient = new GuzzleClient([
'base_url' => $this->config[$storeName]['baseUrl'],
'auth' => [
$this->config[$storeName]['username'],
$this->config[$storeName]['password'],
],
'timeout' => 30,
]);
}
return $this;
}
}
Где config/shopify.php
выглядит так:
<?php
use ConstantsSystem;
return [
System::STORE_RETAIL => [
'baseUrl' => env('SHOPIFY_API_RETAIL_BASE_URL'),
'username' => env('SHOPIFY_API_RETAIL_USERNAME'),
'password' => env('SHOPIFY_API_RETAIL_PASSWORD'),
],
System::STORE_TRADE => [
'baseUrl' => env('SHOPIFY_API_TRADE_BASE_URL'),
'username' => env('SHOPIFY_API_TRADE_USERNAME'),
'password' => env('SHOPIFY_API_TRADE_PASSWORD'),
],
];
Когда я использую сервис, подобный этому:
$retailShopifySerice = app()->make(AppServicesShopifyService::class);
dd($retailShopifySerice->Retail()->Get('/products/1234567890.json'));
Я получаю следующую ошибку:
Ошибка 3 cURL GuzzleHttp Exception RequestException: (см. https://curl.haxx.se/libcurl/c/libcurl-errors.html )
Как вы можете видеть, я создаю простой http-клиент guzzle с опцией по умолчанию (для базового uri basic auth) и делаю последующий запрос GET.
Теоретически это должно работать, но я не могу понять, почему он выдает эту ошибку?
Я уже проверил правильность конфигурации (т. Е. Она Имеет ожидаемые значения) и попытался также очистить весь кеш laravel.
Есть идеи, что здесь может быть не так?
Комментарии:
1. Константы определяются следующим образом:
<?php namespace Constants; class System { const STORE_RETAIL = 'Retail'; const STORE_TRADE = 'Trade';
Ответ №1:
По какой-то причине я не смог получить base_url
опцию для работы GuzzleClient
, поэтому решил ее по-другому:
<?php
namespace AppServices;
use Exception;
use AppDTOsShopifyResult;
use GuzzleHttpClient as GuzzleClient;
use GuzzleHttpExceptionGuzzleException;
/**
* Class ShopifyService
* @package AppServices
*/
class ShopifyService
{
const REQUEST_TYPE_GET = 'GET';
const REQUEST_TYPE_POST = 'POST';
const REQUEST_TIMEOUT = 30;
/**
* @var array $shopifyConfig
*/
private $shopifyConfig = [];
/**
* ShopifyService constructor.
*/
public function __construct()
{
$this->shopifyConfig = config('shopify');
}
/**
* @param string $storeName
* @param string $requestUri
* @return ShopifyResult
* @throws GuzzleException
*/
public function Get(string $storeName, string $requestUri): ShopifyResult
{
return $this->guzzleRequest(
self::REQUEST_TYPE_GET,
$storeName,
$requestUri
);
}
/**
* @param string $storeName
* @param string $requestUri
* @param array $requestPayload
* @return ShopifyResult
* @throws GuzzleException
*/
public function Post(string $storeName, string $requestUri, array $requestPayload = []): ShopifyResult
{
return $this->guzzleRequest(
self::REQUEST_TYPE_POST,
$storeName,
$requestUri,
$requestPayload
);
}
/**
* @param string $requestType
* @param string $storeName
* @param $requestUri
* @param array $requestPayload
* @return ShopifyResult
* @throws GuzzleException
* @throws Exception
*/
private function guzzleRequest(string $requestType, string $storeName, $requestUri, array $requestPayload = []): ShopifyResult
{
$this->validateShopifyConfig($storeName);
$guzzleClient = new GuzzleClient();
$requestOptions = [
'auth' => [
$this->shopifyConfig[$storeName]['username'],
$this->shopifyConfig[$storeName]['password']
],
'timeout' => self::REQUEST_TIMEOUT,
];
if (count($requestPayload)) {
$requestOptions['json'] = $requestPayload;
}
$response = $guzzleClient->request(
$requestType,
$this->shopifyConfig[$storeName]['baseUrl'] . $requestUri,
$requestOptions
);
list ($usedApiCall, $totalApiCallAllowed) = explode(
'/',
$response->getHeader('X-Shopify-Shop-Api-Call-Limit')[0]
);
$shopifyResult = new ShopifyResult(
$response->getStatusCode(),
$response->getReasonPhrase(),
((int) $totalApiCallAllowed - (int) $usedApiCall),
GuzzleHttpjson_decode($response->getBody()->getContents())
);
$guzzleClient = null;
unset($guzzleClient);
return $shopifyResult;
}
/**
* @param string $storeName
* @throws Exception
*/
private function validateShopifyConfig(string $storeName): void
{
if (!array_key_exists($storeName, $this->shopifyConfig)) {
throw new Exception("Invalid shopify store {$storeName}");
}
foreach (['baseUrl', 'username', 'password'] as $configFieldName) {
if (!array_key_exists($configFieldName, $this->shopifyConfig[$storeName])) {
throw new Exception("Shopify config missing {$configFieldName} for store {$storeName}");
}
}
}
}