From a8616655b1cf482a9c357fdd9ba85342c9880cee Mon Sep 17 00:00:00 2001 From: ellynoize Date: Wed, 19 Aug 2026 15:24:56 +0300 Subject: [PATCH 1/4] channels were added --- .../References/SubscriptionsEditRequest.php | 44 ++++++++++++ src/ResourceGroup/References.php | 69 +++++++++++++++++++ tests/src/ResourceGroup/ReferencesTest.php | 31 +++++++++ 3 files changed, 144 insertions(+) create mode 100644 src/Model/Request/References/SubscriptionsEditRequest.php diff --git a/src/Model/Request/References/SubscriptionsEditRequest.php b/src/Model/Request/References/SubscriptionsEditRequest.php new file mode 100644 index 000000000..b65e7d45f --- /dev/null +++ b/src/Model/Request/References/SubscriptionsEditRequest.php @@ -0,0 +1,44 @@ +subscription = $subscription; + } + } +} diff --git a/src/ResourceGroup/References.php b/src/ResourceGroup/References.php index a2b943eb2..8123678a6 100644 --- a/src/ResourceGroup/References.php +++ b/src/ResourceGroup/References.php @@ -26,6 +26,7 @@ use RetailCrm\Api\Model\Request\References\SitesEditRequest; use RetailCrm\Api\Model\Request\References\StatusesEditRequest; use RetailCrm\Api\Model\Request\References\StoresEditRequest; +use RetailCrm\Api\Model\Request\References\SubscriptionsEditRequest; use RetailCrm\Api\Model\Request\References\UnitsEditRequest; use RetailCrm\Api\Model\Response\IdResponse; use RetailCrm\Api\Model\Response\References\CostGroupsResponse; @@ -2166,6 +2167,74 @@ public function storesEdit(string $code, StoresEditRequest $request): SuccessRes return $response; } + /** + * Makes POST "/api/v5/reference/subscriptions/{channel}/{code}/edit" request. + * + * Example: + * ```php + * use RetailCrm\Api\Factory\SimpleClientFactory; + * use RetailCrm\Api\Interfaces\ApiExceptionInterface; + * use RetailCrm\Api\Model\Entity\Customers\SubscriptionCategory; + * use RetailCrm\Api\Model\Request\References\SubscriptionsEditRequest; + * + * $client = SimpleClientFactory::createClient('https://test.retailcrm.pro', 'apiKey'); + * + * $entity = new SubscriptionCategory(); + * $entity->name = 'Новости'; + * $entity->active = true; + * $entity->autoSubscribe = false; + * $entity->ordering = 10; + * + * try { + * $response = $client->references->subscriptionsEdit( + * 'email', + * 'news', + * new SubscriptionsEditRequest($entity) + * ); + * } catch (ApiExceptionInterface $exception) { + * echo sprintf( + * 'Error from RetailCRM API (status code: %d): %s', + * $exception->getStatusCode(), + * $exception->getMessage() + * ); + * + * if (count($exception->getErrorResponse()->errors) > 0) { + * echo PHP_EOL . 'Errors: ' . implode(', ', $exception->getErrorResponse()->errors); + * } + * + * return; + * } + * + * echo 'Created subscription category with ID: ' . $response->id; + * ``` + * + * @param string $channel + * @param string $code + * @param \RetailCrm\Api\Model\Request\References\SubscriptionsEditRequest $request + * + * @return \RetailCrm\Api\Model\Response\IdResponse + * @throws \RetailCrm\Api\Interfaces\ApiExceptionInterface + * @throws \RetailCrm\Api\Interfaces\ClientExceptionInterface + * @throws \RetailCrm\Api\Exception\Api\AccountDoesNotExistException + * @throws \RetailCrm\Api\Exception\Api\ApiErrorException + * @throws \RetailCrm\Api\Exception\Api\MissingCredentialsException + * @throws \RetailCrm\Api\Exception\Api\MissingParameterException + * @throws \RetailCrm\Api\Exception\Api\ValidationException + * @throws \RetailCrm\Api\Exception\Client\HandlerException + * @throws \RetailCrm\Api\Exception\Client\HttpClientException + */ + public function subscriptionsEdit(string $channel, string $code, SubscriptionsEditRequest $request): IdResponse + { + /** @var IdResponse $response */ + $response = $this->sendRequest( + RequestMethod::POST, + 'reference/subscriptions/' . $channel . '/' . $code . '/edit', + $request, + IdResponse::class + ); + return $response; + } + /** * Makes GET "/api/v5/reference/units" request. * diff --git a/tests/src/ResourceGroup/ReferencesTest.php b/tests/src/ResourceGroup/ReferencesTest.php index eb96d07cc..93764c286 100644 --- a/tests/src/ResourceGroup/ReferencesTest.php +++ b/tests/src/ResourceGroup/ReferencesTest.php @@ -15,6 +15,7 @@ use RetailCrm\Api\Enum\RequestMethod; use RetailCrm\Api\Model\Callback\Entity\Delivery\SerializedStoreWeekOpeningHours; use RetailCrm\Api\Model\Callback\Entity\Delivery\StoreWorkTime; +use RetailCrm\Api\Model\Entity\Customers\SubscriptionCategory; use RetailCrm\Api\Model\Entity\Orders\Delivery\CourierPhone; use RetailCrm\Api\Model\Entity\References\CostGroup; use RetailCrm\Api\Model\Entity\References\CostItem; @@ -51,6 +52,7 @@ use RetailCrm\Api\Model\Request\References\SitesEditRequest; use RetailCrm\Api\Model\Request\References\StatusesEditRequest; use RetailCrm\Api\Model\Request\References\StoresEditRequest; +use RetailCrm\Api\Model\Request\References\SubscriptionsEditRequest; use RetailCrm\Api\Model\Request\References\UnitsEditRequest; use RetailCrm\TestUtils\Factory\TestClientFactory; use RetailCrm\TestUtils\TestCase\AbstractApiResourceGroupTestCase; @@ -3712,6 +3714,35 @@ public function testStoresEdit(): void self::assertModelEqualsToResponse($json, $response); } + public function testSubscriptionsEdit(): void + { + $json = <<<'EOF' +{ + "success": true, + "id": 18 +} +EOF; + + $entity = new SubscriptionCategory(); + $entity->name = 'Новости'; + $entity->active = true; + $entity->autoSubscribe = false; + $entity->ordering = 10; + + $request = new SubscriptionsEditRequest($entity); + + $mock = static::createApiMockBuilder('reference/subscriptions/email/news/edit'); + $mock->matchMethod(RequestMethod::POST) + ->matchBody(self::encodeForm($request)) + ->reply(201) + ->withBody($json); + + $client = TestClientFactory::createClient($mock->getClient()); + $response = $client->references->subscriptionsEdit('email', 'news', $request); + + self::assertModelEqualsToResponse($json, $response); + } + public function testUnits(): void { $json = <<<'EOF' From d00c7e51c49b49fe59a89378fe6e48d5b84c3a98 Mon Sep 17 00:00:00 2001 From: ellynoize Date: Wed, 19 Aug 2026 15:33:39 +0300 Subject: [PATCH 2/4] fix param --- src/ResourceGroup/References.php | 5 +++++ tests/src/ResourceGroup/ReferencesTest.php | 9 ++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/ResourceGroup/References.php b/src/ResourceGroup/References.php index 8123678a6..8debf89d6 100644 --- a/src/ResourceGroup/References.php +++ b/src/ResourceGroup/References.php @@ -2180,6 +2180,7 @@ public function storesEdit(string $code, StoresEditRequest $request): SuccessRes * $client = SimpleClientFactory::createClient('https://test.retailcrm.pro', 'apiKey'); * * $entity = new SubscriptionCategory(); + * $entity->channel = 'email'; * $entity->name = 'Новости'; * $entity->active = true; * $entity->autoSubscribe = false; @@ -2225,6 +2226,10 @@ public function storesEdit(string $code, StoresEditRequest $request): SuccessRes */ public function subscriptionsEdit(string $channel, string $code, SubscriptionsEditRequest $request): IdResponse { + if (null !== $request->subscription) { + $request->subscription->channel = $channel; + } + /** @var IdResponse $response */ $response = $this->sendRequest( RequestMethod::POST, diff --git a/tests/src/ResourceGroup/ReferencesTest.php b/tests/src/ResourceGroup/ReferencesTest.php index 93764c286..59263ae3c 100644 --- a/tests/src/ResourceGroup/ReferencesTest.php +++ b/tests/src/ResourceGroup/ReferencesTest.php @@ -3730,10 +3730,17 @@ public function testSubscriptionsEdit(): void $entity->ordering = 10; $request = new SubscriptionsEditRequest($entity); + $expectedEntity = new SubscriptionCategory(); + $expectedEntity->channel = 'email'; + $expectedEntity->name = 'Новости'; + $expectedEntity->active = true; + $expectedEntity->autoSubscribe = false; + $expectedEntity->ordering = 10; + $expectedRequest = new SubscriptionsEditRequest($expectedEntity); $mock = static::createApiMockBuilder('reference/subscriptions/email/news/edit'); $mock->matchMethod(RequestMethod::POST) - ->matchBody(self::encodeForm($request)) + ->matchBody(self::encodeForm($expectedRequest)) ->reply(201) ->withBody($json); From 76fef1f7aaaab303d9d432f1dc7543a4d48f9a5c Mon Sep 17 00:00:00 2001 From: ellynoize Date: Thu, 20 Aug 2026 14:29:20 +0300 Subject: [PATCH 3/4] get method --- .../References/SubscriptionsResponse.php | 30 +++++++++++ src/ResourceGroup/References.php | 53 +++++++++++++++++++ tests/src/ResourceGroup/ReferencesTest.php | 39 ++++++++++++++ 3 files changed, 122 insertions(+) create mode 100644 src/Model/Response/References/SubscriptionsResponse.php diff --git a/src/Model/Response/References/SubscriptionsResponse.php b/src/Model/Response/References/SubscriptionsResponse.php new file mode 100644 index 000000000..678367576 --- /dev/null +++ b/src/Model/Response/References/SubscriptionsResponse.php @@ -0,0 +1,30 @@ +") + * @JMS\SerializedName("subscriptions") + */ + public $subscriptions; +} diff --git a/src/ResourceGroup/References.php b/src/ResourceGroup/References.php index 8debf89d6..71b7ea603 100644 --- a/src/ResourceGroup/References.php +++ b/src/ResourceGroup/References.php @@ -48,6 +48,7 @@ use RetailCrm\Api\Model\Response\References\StatusesResponse; use RetailCrm\Api\Model\Response\References\StatusGroupsResponse; use RetailCrm\Api\Model\Response\References\StoresResponse; +use RetailCrm\Api\Model\Response\References\SubscriptionsResponse; use RetailCrm\Api\Model\Response\References\UnitsResponse; use RetailCrm\Api\Model\Response\SuccessResponse; @@ -2167,6 +2168,58 @@ public function storesEdit(string $code, StoresEditRequest $request): SuccessRes return $response; } + /** + * Makes GET "/api/v5/reference/subscriptions" request. + * + * Example: + * ```php + * use RetailCrm\Api\Factory\SimpleClientFactory; + * use RetailCrm\Api\Interfaces\ApiExceptionInterface; + * + * $client = SimpleClientFactory::createClient('https://test.retailcrm.pro', 'apiKey'); + * + * try { + * $response = $client->references->subscriptions(); + * } catch (ApiExceptionInterface $exception) { + * echo sprintf( + * 'Error from RetailCRM API (status code: %d): %s', + * $exception->getStatusCode(), + * $exception->getMessage() + * ); + * + * if (count($exception->getErrorResponse()->errors) > 0) { + * echo PHP_EOL . 'Errors: ' . implode(', ', $exception->getErrorResponse()->errors); + * } + * + * return; + * } + * + * echo 'Subscriptions: ' . print_r($response->subscriptions, true); + * ``` + * + * @return \RetailCrm\Api\Model\Response\References\SubscriptionsResponse + * @throws \RetailCrm\Api\Interfaces\ApiExceptionInterface + * @throws \RetailCrm\Api\Interfaces\ClientExceptionInterface + * @throws \RetailCrm\Api\Exception\Api\AccountDoesNotExistException + * @throws \RetailCrm\Api\Exception\Api\ApiErrorException + * @throws \RetailCrm\Api\Exception\Api\MissingCredentialsException + * @throws \RetailCrm\Api\Exception\Api\MissingParameterException + * @throws \RetailCrm\Api\Exception\Api\ValidationException + * @throws \RetailCrm\Api\Exception\Client\HandlerException + * @throws \RetailCrm\Api\Exception\Client\HttpClientException + */ + public function subscriptions(): SubscriptionsResponse + { + /** @var SubscriptionsResponse $response */ + $response = $this->sendRequest( + RequestMethod::GET, + 'reference/subscriptions', + null, + SubscriptionsResponse::class + ); + return $response; + } + /** * Makes POST "/api/v5/reference/subscriptions/{channel}/{code}/edit" request. * diff --git a/tests/src/ResourceGroup/ReferencesTest.php b/tests/src/ResourceGroup/ReferencesTest.php index 59263ae3c..1904dfdaf 100644 --- a/tests/src/ResourceGroup/ReferencesTest.php +++ b/tests/src/ResourceGroup/ReferencesTest.php @@ -3714,6 +3714,45 @@ public function testStoresEdit(): void self::assertModelEqualsToResponse($json, $response); } + public function testSubscriptions(): void + { + $json = <<<'EOF' +{ + "success": true, + "subscriptions": [ + { + "id": 2, + "channel": "email", + "name": "Без тематики", + "code": "default_marketing", + "active": true, + "autoSubscribe": true, + "ordering": 1 + }, + { + "id": 4, + "channel": "waba", + "name": "Новости", + "code": "news", + "active": true, + "autoSubscribe": false, + "ordering": 10 + } + ] +} +EOF; + + $mock = static::createApiMockBuilder('reference/subscriptions'); + $mock->matchMethod(RequestMethod::GET) + ->reply(200) + ->withBody($json); + + $client = TestClientFactory::createClient($mock->getClient()); + $response = $client->references->subscriptions(); + + self::assertModelEqualsToResponse($json, $response); + } + public function testSubscriptionsEdit(): void { $json = <<<'EOF' From ed37485b11f86fe0efde953b4268969e17ddb367 Mon Sep 17 00:00:00 2001 From: ellynoize Date: Thu, 20 Aug 2026 14:33:25 +0300 Subject: [PATCH 4/4] fix --- src/ResourceGroup/References.php | 8 ++++++-- tests/src/ResourceGroup/ReferencesTest.php | 1 + 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/ResourceGroup/References.php b/src/ResourceGroup/References.php index 71b7ea603..f810547d3 100644 --- a/src/ResourceGroup/References.php +++ b/src/ResourceGroup/References.php @@ -2279,15 +2279,19 @@ public function subscriptions(): SubscriptionsResponse */ public function subscriptionsEdit(string $channel, string $code, SubscriptionsEditRequest $request): IdResponse { + $sendRequest = $request; + if (null !== $request->subscription) { - $request->subscription->channel = $channel; + $subscription = clone $request->subscription; + $subscription->channel = $channel; + $sendRequest = new SubscriptionsEditRequest($subscription); } /** @var IdResponse $response */ $response = $this->sendRequest( RequestMethod::POST, 'reference/subscriptions/' . $channel . '/' . $code . '/edit', - $request, + $sendRequest, IdResponse::class ); return $response; diff --git a/tests/src/ResourceGroup/ReferencesTest.php b/tests/src/ResourceGroup/ReferencesTest.php index 1904dfdaf..aa403e4a4 100644 --- a/tests/src/ResourceGroup/ReferencesTest.php +++ b/tests/src/ResourceGroup/ReferencesTest.php @@ -3787,6 +3787,7 @@ public function testSubscriptionsEdit(): void $response = $client->references->subscriptionsEdit('email', 'news', $request); self::assertModelEqualsToResponse($json, $response); + self::assertNull($request->subscription->channel); } public function testUnits(): void