From f8baf02ee46b93edd88e7523a23b21d5bf9e016a Mon Sep 17 00:00:00 2001 From: Eugene Ivanov <93479789+evgeek@users.noreply.github.com> Date: Sat, 30 Sep 2023 14:22:26 +0300 Subject: [PATCH] New Moysklad API endpoint and gzip compression (#33) --- CHANGELOG.md | 6 ++++++ README.md | 4 ++-- src/Api/Query/QueryBuilder.php | 2 +- src/Http/ApiClient.php | 5 ++++- src/Services/Url.php | 2 +- tests/Feature/Api/Query/ApiTestCase.php | 1 + tests/Unit/Formatters/ArrayFormatTest.php | 4 ++-- tests/Unit/Formatters/MultiDecoderTestCase.php | 4 ++-- tests/Unit/Formatters/RecordFormatTest.php | 18 +++++++++--------- tests/Unit/Formatters/StdClassFormatTest.php | 4 ++-- tests/Unit/Http/ApiClientTest.php | 9 +++++---- tests/Unit/Http/GuzzleSenderTest.php | 2 +- tests/Unit/Services/UrlTest.php | 2 +- 13 files changed, 37 insertions(+), 26 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 70c83ae1..eb1cd37e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,12 @@ Все существенные изменения в проекте будут задокументированы в этом файле. Формат основан на [Keep a Changelog](https://keepachangelog.com/), и этот проект придерживается семантического версионирования ([semver](https://semver.org/)). +## v0.9.0 + +### Changed + +- В связи с [переездом API Моего Склада на новый домен](https://dev.moysklad.ru/doc/api/remap/1.2/#mojsklad-json-api-obschie-swedeniq-rekomendacii-po-pereezdu-na-nowyj-domen) внесены все необходимые правки: изменён url API, в заголовки добавлено gzip-сжатие. Пользователям библиотеки вносить какие-либо изменения в код в связи с этим не требуется. До 1 декабря 2023 года обновите версию библиотеки до `v0.9.0` или выше согласно [Upgrade guide](/UPGRADE.md). + ## v0.8.2 ### Fixed diff --git a/README.md b/README.md index c3d023d3..bcbf2664 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ $product->get(); $product = Product::make($ms, ['id' => '25cf41f2-b068-11ed-0a80-0e9700500d7e'])->get(); ``` -## Документация +## Полная документация * [Настройка клиента](/docs/setup.md) * [Взаимодействие с API](/docs/api_interaction.md) @@ -78,7 +78,7 @@ Product::collection($ms) ![autocomplete](/docs/autocomplete.gif) -### Документация +### Встроенная документация Публичные методы тщательно документированы: описание, примеры кода, ссылки на документацию API. diff --git a/src/Api/Query/QueryBuilder.php b/src/Api/Query/QueryBuilder.php index 2ab46a9a..83fec2cd 100644 --- a/src/Api/Query/QueryBuilder.php +++ b/src/Api/Query/QueryBuilder.php @@ -25,7 +25,7 @@ public function __construct(ApiClient $api) * Если $withParams === true, конструктор сохранит параметры из url, иначе - отбросит. * * - * $productUrl = "https://online.moysklad.ru/api/remap/1.2/entity/product/3aba2611-c64f-11ed-0a80-108a00230a9c?expand=image"; + * $productUrl = "https://api.moysklad.ru/api/remap/1.2/entity/product/3aba2611-c64f-11ed-0a80-108a00230a9c?expand=image"; * $product = $ms->query() * ->fromUrl($productUrl, true) * ->get(); diff --git a/src/Http/ApiClient.php b/src/Http/ApiClient.php index 54c785f0..53ebacda 100644 --- a/src/Http/ApiClient.php +++ b/src/Http/ApiClient.php @@ -16,7 +16,10 @@ class ApiClient { - private array $headers = ['Content-Type' => 'application/json']; + private array $headers = [ + 'Content-Type' => 'application/json', + 'Accept-Encoding' => 'gzip', + ]; public function __construct( array $credentials, diff --git a/src/Services/Url.php b/src/Services/Url.php index 9b4d34f8..0a36e125 100644 --- a/src/Services/Url.php +++ b/src/Services/Url.php @@ -10,7 +10,7 @@ final class Url { - public const API = 'https://online.moysklad.ru/api/remap/1.2'; + public const API = 'https://api.moysklad.ru/api/remap/1.2'; public static function convertMixedValueToString(string|int|float|bool $value): string { diff --git a/tests/Feature/Api/Query/ApiTestCase.php b/tests/Feature/Api/Query/ApiTestCase.php index ebc4b798..dae96d77 100644 --- a/tests/Feature/Api/Query/ApiTestCase.php +++ b/tests/Feature/Api/Query/ApiTestCase.php @@ -63,6 +63,7 @@ protected function makeExpectedDebug(array $path, HttpMethod $method = HttpMetho 'url_encoded' => $url, 'headers' => [ 'Content-Type' => 'application/json', + 'Accept-Encoding' => 'gzip', 'Authorization' => 'Bearer ' . static::TOKEN, ], 'body' => $body ?? [], diff --git a/tests/Unit/Formatters/ArrayFormatTest.php b/tests/Unit/Formatters/ArrayFormatTest.php index 80213329..324d4874 100644 --- a/tests/Unit/Formatters/ArrayFormatTest.php +++ b/tests/Unit/Formatters/ArrayFormatTest.php @@ -17,13 +17,13 @@ public static function getEncodedObject(): array return [ 'param' => 'test_param', 'meta' => [ - 'href' => 'https://online.moysklad.ru/api/remap/1.2/endpoint/segment', + 'href' => 'https://api.moysklad.ru/api/remap/1.2/endpoint/segment', 'type' => 'product', ], 'context' => [ 'employee' => [ 'meta' => [ - 'href' => 'https://online.moysklad.ru/api/remap/1.2/context/employee', + 'href' => 'https://api.moysklad.ru/api/remap/1.2/context/employee', 'type' => 'employee', ], ], diff --git a/tests/Unit/Formatters/MultiDecoderTestCase.php b/tests/Unit/Formatters/MultiDecoderTestCase.php index e4ad79b5..e62d8105 100644 --- a/tests/Unit/Formatters/MultiDecoderTestCase.php +++ b/tests/Unit/Formatters/MultiDecoderTestCase.php @@ -14,8 +14,8 @@ abstract class MultiDecoderTestCase extends TestCase { protected const OBJECT_JSON_STRING = '{"param":"test_param","meta":{"href":' . - '"https:\/\/online.moysklad.ru\/api\/remap\/1.2\/endpoint\/segment","type":"product"},"context":' . - '{"employee":{"meta":{"href":"https:\/\/online.moysklad.ru\/api\/remap\/1.2\/context\/employee","type":"employee"}}},' . + '"https:\/\/api.moysklad.ru\/api\/remap\/1.2\/endpoint\/segment","type":"product"},"context":' . + '{"employee":{"meta":{"href":"https:\/\/api.moysklad.ru\/api\/remap\/1.2\/context\/employee","type":"employee"}}},' . '"rows":[{"id":"id1","value":true},{"id":"id2","value":0},{"id":"id3","value":null},{"id":"id4","value":123.45}]}'; protected const ARRAYS_JSON_STRING = '[{"param":"value1","meta":"meta1"},{"param":"value2","meta":"meta2"}]'; protected const EMPTY_JSON_STRING = ''; diff --git a/tests/Unit/Formatters/RecordFormatTest.php b/tests/Unit/Formatters/RecordFormatTest.php index 739a207f..67fe6c66 100644 --- a/tests/Unit/Formatters/RecordFormatTest.php +++ b/tests/Unit/Formatters/RecordFormatTest.php @@ -25,13 +25,13 @@ class RecordFormatTest extends StdClassFormatTest private const COMPLEX_CASE = [ [ 'meta' => [ - 'href' => 'https://online.moysklad.ru/api/remap/1.2/entity/product', + 'href' => 'https://api.moysklad.ru/api/remap/1.2/entity/product', 'type' => 'product', ], 'context' => [ 'employee' => [ 'meta' => [ - 'href' => 'https://online.moysklad.ru/api/remap/1.2/context/employee', + 'href' => 'https://api.moysklad.ru/api/remap/1.2/context/employee', 'type' => 'employee', ], ], @@ -39,20 +39,20 @@ class RecordFormatTest extends StdClassFormatTest 'rows' => [ [ 'meta' => [ - 'href' => 'https://online.moysklad.ru/api/remap/1.2/entity/product', + 'href' => 'https://api.moysklad.ru/api/remap/1.2/entity/product', 'type' => 'product', ], 'id' => '25cf41f2-b068-11ed-0a80-0e9700500d7e', 'type' => 'unknown', 'owner' => [ 'meta' => [ - 'href' => 'https://online.moysklad.ru/api/remap/1.2/entity/employee', + 'href' => 'https://api.moysklad.ru/api/remap/1.2/entity/employee', 'type' => 'employee', ], ], 'fake_collection' => [ 'meta' => [ - 'href' => 'https://online.moysklad.ru/api/remap/1.2/entity/fake_entity', + 'href' => 'https://api.moysklad.ru/api/remap/1.2/entity/fake_entity', 'type' => 'fake_entity', ], 'rows' => [ @@ -65,7 +65,7 @@ class RecordFormatTest extends StdClassFormatTest ], [ 'meta' => [ - 'href' => 'https://online.moysklad.ru/api/remap/1.2/entity/fake_entity', + 'href' => 'https://api.moysklad.ru/api/remap/1.2/entity/fake_entity', 'type' => 'fake_entity', ], 'id' => 'f731148b-a93d-11ed-0a80-0fba0011a6c6', @@ -115,7 +115,7 @@ public static function arrayInputDataProvider(): array [ [ 'meta' => [ - 'href' => 'https://online.moysklad.ru/api/remap/1.2/context/employee', + 'href' => 'https://api.moysklad.ru/api/remap/1.2/context/employee', 'type' => 'employee', ], ], @@ -123,7 +123,7 @@ public static function arrayInputDataProvider(): array [ [[ 'meta' => [ - 'href' => 'https://online.moysklad.ru/api/remap/1.2/context/employee', + 'href' => 'https://api.moysklad.ru/api/remap/1.2/context/employee', 'type' => 'employee', ], ]], @@ -131,7 +131,7 @@ public static function arrayInputDataProvider(): array [ [ 'meta' => [ - 'href' => 'https://online.moysklad.ru/api/remap/1.2/entity/product', + 'href' => 'https://api.moysklad.ru/api/remap/1.2/entity/product', 'type' => 'product', ], 'rows' => [], diff --git a/tests/Unit/Formatters/StdClassFormatTest.php b/tests/Unit/Formatters/StdClassFormatTest.php index ae9b080f..95010ca0 100644 --- a/tests/Unit/Formatters/StdClassFormatTest.php +++ b/tests/Unit/Formatters/StdClassFormatTest.php @@ -27,13 +27,13 @@ protected static function getEncodedObject(): stdClass return (object) [ 'param' => 'test_param', 'meta' => (object) [ - 'href' => 'https://online.moysklad.ru/api/remap/1.2/endpoint/segment', + 'href' => 'https://api.moysklad.ru/api/remap/1.2/endpoint/segment', 'type' => 'product', ], 'context' => (object) [ 'employee' => (object) [ 'meta' => (object) [ - 'href' => 'https://online.moysklad.ru/api/remap/1.2/context/employee', + 'href' => 'https://api.moysklad.ru/api/remap/1.2/context/employee', 'type' => 'employee', ], ], diff --git a/tests/Unit/Http/ApiClientTest.php b/tests/Unit/Http/ApiClientTest.php index abc1c460..5980e6ce 100644 --- a/tests/Unit/Http/ApiClientTest.php +++ b/tests/Unit/Http/ApiClientTest.php @@ -76,8 +76,8 @@ public function testSendCreatesRequestAndReturnsFormattedResponse(): void fn (RequestInterface $request) => strtolower($request->getMethod()) === 'post' && $request->getHeader('content-type')[0] === 'application/json' && $request->getUri()->getScheme() === 'https' - && $request->getHeader('host')[0] === 'online.moysklad.ru' - && $request->getUri()->getHost() === 'online.moysklad.ru' + && $request->getHeader('host')[0] === 'api.moysklad.ru' + && $request->getUri()->getHost() === 'api.moysklad.ru' && $request->getHeader('authorization')[0] === self::TOKEN_HEADER && $request->getUri()->getPath() === '/api/remap/1.2/entity/product' && $request->getUri()->getQuery() === http_build_query(self::PARAMS) @@ -198,14 +198,15 @@ public static function limitOffsetDataProvider(): array public function testDebug(): void { $payload = new Payload(HttpMethod::GET, self::PATH, self::PARAMS, self::BODY); - $url = 'https://online.moysklad.ru/api/remap/1.2/entity/product?limit=1&filter=filter_param_1=filter_value_1;filter_param_2=true'; - $urlEncoded = 'https://online.moysklad.ru/api/remap/1.2/entity/product?limit=1&filter=filter_param_1%3Dfilter_value_1%3Bfilter_param_2%3Dtrue'; + $url = 'https://api.moysklad.ru/api/remap/1.2/entity/product?limit=1&filter=filter_param_1=filter_value_1;filter_param_2=true'; + $urlEncoded = 'https://api.moysklad.ru/api/remap/1.2/entity/product?limit=1&filter=filter_param_1%3Dfilter_value_1%3Bfilter_param_2%3Dtrue'; $expected = [ 'method' => 'GET', 'url' => $url, 'url_encoded' => $urlEncoded, 'headers' => [ 'Content-Type' => 'application/json', + 'Accept-Encoding' => 'gzip', 'Authorization' => self::TOKEN_HEADER, ], 'body' => self::BODY, diff --git a/tests/Unit/Http/GuzzleSenderTest.php b/tests/Unit/Http/GuzzleSenderTest.php index fb179b45..e2ac0b14 100644 --- a/tests/Unit/Http/GuzzleSenderTest.php +++ b/tests/Unit/Http/GuzzleSenderTest.php @@ -22,7 +22,7 @@ public function testSenderUsesPassedClient(): void ->with($this->callback( fn (RequestInterface $request) => $request->getMethod() === 'GET' && $request->getUri()->getScheme() === 'https' - && $request->getUri()->getHost() === 'online.moysklad.ru' + && $request->getUri()->getHost() === 'api.moysklad.ru' && $request->getUri()->getPath() === '/api/remap/1.2' && $request->getUri()->getQuery() === '' && $request->getUri()->getFragment() === '' diff --git a/tests/Unit/Services/UrlTest.php b/tests/Unit/Services/UrlTest.php index f1489bbf..c50835ab 100644 --- a/tests/Unit/Services/UrlTest.php +++ b/tests/Unit/Services/UrlTest.php @@ -12,7 +12,7 @@ /** @covers \Evgeek\Moysklad\Services\Url */ class UrlTest extends TestCase { - private const API_URL = 'https://online.moysklad.ru/api/remap/1.2'; + private const API_URL = 'https://api.moysklad.ru/api/remap/1.2'; private const GUID1 = '25cf41f2-b068-11ed-0a80-0e9700500d7e'; private const GUID2 = 'f731148b-a93d-11ed-0a80-0fba0011a6c6';