diff --git a/README.md b/README.md index 09e5cf56..0f8325a5 100644 --- a/README.md +++ b/README.md @@ -130,39 +130,41 @@ $leadsService = $apiClient->leads(); В данный момент доступны следующие сервисы: -| Сервис | Цель сервиса | -|-------------------|-------------------------------| -| notes | Примечание сущности | -| tags | Теги сущностей | -| tasks | Задачи | -| leads | Сделки | -| contacts | Контакты | -| companies | Компании | -| catalogs | Каталоги | -| catalogElements | Элементы каталогов | -| customFields | Пользовательские поля | -| customFieldGroups | Группы пользовательских полей | -| account | Информация об аккаунте | -| roles | Роли пользователей | -| users | Роли юзеров | -| customersSegments | Сегменты покупателей | -| events | Список событий | -| webhooks | Вебхуки | -| unsorted | Неразобранное | -| pipelines | Воронки сделок | -| statuses | Статусы сделок | -| widgets | Виджеты | -| lossReason | Причины отказа | -| transactions | Покупки покупателей | -| customers | Покупатели | -| customersStatuses | Сегменты покупателя | +| Сервис | Цель сервиса | +|----------------------|-------------------------------| +| notes | Примечание сущности | +| tags | Теги сущностей | +| tasks | Задачи | +| leads | Сделки | +| contacts | Контакты | +| companies | Компании | +| catalogs | Каталоги | +| catalogElements | Элементы каталогов | +| customFields | Пользовательские поля | +| customFieldGroups | Группы пользовательских полей | +| account | Информация об аккаунте | +| roles | Роли пользователей | +| users | Роли юзеров | +| customersSegments | Сегменты покупателей | +| events | Список событий | +| webhooks | Вебхуки | +| unsorted | Неразобранное | +| pipelines | Воронки сделок | +| statuses | Статусы сделок | +| widgets | Виджеты | +| lossReason | Причины отказа | +| transactions | Покупки покупателей | +| customers | Покупатели | +| customersStatuses | Сегменты покупателя | | customersBonusPoints | Бонусные баллы покупателя | -| calls | Звонки | -| products | Товары | -| links | Массовая привязка сущностей | -| shortLinks | Короткие ссылки | -| getOAuthClient | oAuth сервис | -| getRequest | Голый запросы | +| calls | Звонки | +| products | Товары | +| links | Массовая привязка сущностей | +| shortLinks | Короткие ссылки | +| talks | Беседы | +| entitySubscriptions | Подписчики сущности | +| getOAuthClient | oAuth сервис | +| getRequest | Голый запросы | #### Для большинства сервисов есть базовый набор методов: @@ -362,7 +364,7 @@ $leadsService = $apiClient->leads(); redeemPoints(BonusPointsActionModel $bonusPointsActionModel) ``` -#### Методы доступные в сервисе ```notes```: +#### Методы доступные в сервисе ```notes```, ```entitySubscriptions```: 1. getByParentId Получение данных по ID родительской сущности 1. parentId - ID родительской сущности 2. filter (BaseEntityFilter) - фильтр @@ -473,6 +475,13 @@ $leadsService = $apiClient->leads(); updateSettings(ProductsSettingsModel $productsSettings); ``` +#### Методы, доступные в сервисе ```talks``` +2. close + 1. model (TalkCloseActionModel) - модель для закрытия беседы + 2. Результатом выполнения - является закрытие беседы или запуск NPS-бота для последующего закрытия беседы + ```php + close(TalkCloseActionModel $closeAction) + ``` ## Обработка ошибок diff --git a/examples/subscriptions_actions.php b/examples/subscriptions_actions.php new file mode 100644 index 00000000..4b3ac646 --- /dev/null +++ b/examples/subscriptions_actions.php @@ -0,0 +1,50 @@ +setAccessToken($accessToken) + ->setAccountBaseDomain($accessToken->getValues()['baseDomain']) + ->onAccessTokenRefresh( + function (AccessTokenInterface $accessToken, string $baseDomain) { + saveToken( + [ + 'accessToken' => $accessToken->getToken(), + 'refreshToken' => $accessToken->getRefreshToken(), + 'expires' => $accessToken->getExpires(), + 'baseDomain' => $baseDomain, + ] + ); + } + ); + +$subscriptionsService = $apiClient->entitySubscriptions(EntityTypesInterface::LEADS); + +try { + $filer = (new PagesFilter()) + ->setLimit(3); + $subscriptions = $subscriptionsService->getByParentId(667999631, $filer); +} catch (AmoCRMApiException $exception) { + printError($exception); + die; +} + +var_dump($subscriptions->toArray()); + +try { + $nextSubscriptions = $subscriptionsService->nextPage($subscriptions); +} catch (AmoCRMApiException $exception) { + printError($exception); + die; +} + +var_dump($nextSubscriptions->toArray()); diff --git a/examples/talks_actions.php b/examples/talks_actions.php new file mode 100644 index 00000000..fb06fb46 --- /dev/null +++ b/examples/talks_actions.php @@ -0,0 +1,43 @@ +setAccessToken($accessToken) + ->setAccountBaseDomain($accessToken->getValues()['baseDomain']) + ->onAccessTokenRefresh( + function (AccessTokenInterface $accessToken, string $baseDomain) { + saveToken( + [ + 'accessToken' => $accessToken->getToken(), + 'refreshToken' => $accessToken->getRefreshToken(), + 'expires' => $accessToken->getExpires(), + 'baseDomain' => $baseDomain, + ] + ); + } + ); + +$talksService = $apiClient->talks(); + +try { + $talk = $talksService->getOne('114'); +} catch (AmoCRMApiException $exception) { + printError($exception); + die; +} + +try { + $talksService->close(new TalkCloseActionModel($talk->getTalkId(), true)); +} catch (AmoCRMApiException $exception) { + printError($exception); + die; +} diff --git a/src/AmoCRM/Client/AmoCRMApiClient.php b/src/AmoCRM/Client/AmoCRMApiClient.php index 65ffdcc7..e480f0a7 100644 --- a/src/AmoCRM/Client/AmoCRMApiClient.php +++ b/src/AmoCRM/Client/AmoCRMApiClient.php @@ -3,6 +3,7 @@ namespace AmoCRM\Client; use AmoCRM\EntitiesServices\Customers\BonusPoints; +use AmoCRM\EntitiesServices\EntitySubscriptions; use AmoCRM\EntitiesServices\Links; use AmoCRM\EntitiesServices\Products; use AmoCRM\EntitiesServices\Calls; @@ -25,6 +26,7 @@ use AmoCRM\EntitiesServices\Roles; use AmoCRM\EntitiesServices\Segments; use AmoCRM\EntitiesServices\ShortLinks; +use AmoCRM\EntitiesServices\Talks; use AmoCRM\EntitiesServices\Tasks; use AmoCRM\EntitiesServices\Unsorted; use AmoCRM\EntitiesServices\Users; @@ -588,6 +590,17 @@ public function products(): Products return new Products($request); } + public function talks(): Talks + { + return new Talks($this->buildRequest()); + } + + public function entitySubscriptions(string $entityType): EntitySubscriptions + { + return (new EntitySubscriptions($this->buildRequest())) + ->setEntityType($entityType); + } + /** * Метод вернет объект запроса для любых запросов в amoCRM с текущим Access Token * diff --git a/src/AmoCRM/Collections/SubscriptionsCollection.php b/src/AmoCRM/Collections/SubscriptionsCollection.php new file mode 100644 index 00000000..1c19b284 --- /dev/null +++ b/src/AmoCRM/Collections/SubscriptionsCollection.php @@ -0,0 +1,25 @@ + $closeAction->isForceClose()]; + /** @noinspection UnusedFunctionResultInspection */ + $this->request->post($this->getMethod() . '/' . $closeAction->getTalkId() . '/close', $body); + } +} diff --git a/src/AmoCRM/Helpers/EntityTypesInterface.php b/src/AmoCRM/Helpers/EntityTypesInterface.php index 1619d216..6cc177d4 100644 --- a/src/AmoCRM/Helpers/EntityTypesInterface.php +++ b/src/AmoCRM/Helpers/EntityTypesInterface.php @@ -37,7 +37,8 @@ interface EntityTypesInterface public const SETTINGS = 'settings'; public const SHORT_LINKS = 'short_links'; public const LINKS = 'links'; - + public const TALKS = 'talks'; + public const SUBSCRIPTIONS = 'subscriptions'; public const CUSTOM_FIELDS = 'custom_fields'; public const CUSTOM_FIELD_GROUPS = 'custom_field_groups'; diff --git a/src/AmoCRM/Models/SubscriptionModel.php b/src/AmoCRM/Models/SubscriptionModel.php new file mode 100644 index 00000000..162b3b65 --- /dev/null +++ b/src/AmoCRM/Models/SubscriptionModel.php @@ -0,0 +1,86 @@ +setSubscriberId((int)$subscription['subscriber_id']) + ->setType((string)$subscription['type']); + } + + public function getSubscriberId(): int + { + return $this->subscriberId; + } + + public function setSubscriberId(int $subscriberId): self + { + $this->subscriberId = $subscriberId; + + return $this; + } + + public function getType(): string + { + return $this->type; + } + + public function setType(string $type): self + { + $this->type = $type; + + return $this; + } + + public function isUser(): bool + { + return $this->getType() === self::TYPE_USER; + } + + public function isGroup(): bool + { + return $this->getType() === self::TYPE_GROUP; + } + + /** + * @inheritDoc + */ + public function toArray(): array + { + return [ + 'subscriber_id' => $this->getSubscriberId(), + 'type' => $this->getType(), + ]; + } + + /** + * @param string|null $requestId + * + * @return array + * @throws NotAvailableForActionException + */ + public function toApi(?string $requestId = "0"): array + { + throw new NotAvailableForActionException(); + } +} diff --git a/src/AmoCRM/Models/TalkModel.php b/src/AmoCRM/Models/TalkModel.php new file mode 100644 index 00000000..4946020b --- /dev/null +++ b/src/AmoCRM/Models/TalkModel.php @@ -0,0 +1,250 @@ +setTalkId((int)$talk['talk_id']) + ->setCreatedAt((int)$talk['created_at']) + ->setUpdatedAt((int)$talk['updated_at']) + ->setRate((int)$talk['rate']) + ->setContactId((int)$talk['contact_id']) + ->setChatId(empty($talk['chat_id']) ? null : (string)$talk['chat_id']) + ->setEntityId(empty($talk['entity_id']) ?: (int)$talk['entity_id']) + ->setEntityType(empty($talk['entity_type']) ?: (string)$talk['entity_type']) + ->setIsInWork(!empty($talk['is_in_work'])) + ->setIsRead(!empty($talk['is_read'])) + ->setOrigin((string)($talk['origin'] ?? '')) + ->setMissedAt(empty($talk['missed_at']) ? null : (int)$talk['missed_at']) + ->setAccountId((int)$talk['account_id']); + } + + public function getTalkId(): int + { + return $this->talkId; + } + + public function setTalkId(int $talkId): self + { + $this->talkId = $talkId; + + return $this; + } + + public function getCreatedAt(): int + { + return $this->createdAt; + } + + public function setCreatedAt(int $createdAt): self + { + $this->createdAt = $createdAt; + + return $this; + } + + public function getUpdatedAt(): int + { + return $this->updatedAt; + } + + public function setUpdatedAt(int $updatedAt): self + { + $this->updatedAt = $updatedAt; + + return $this; + } + + public function getRate(): int + { + return $this->rate; + } + + public function setRate(int $rate): self + { + $this->rate = $rate; + + return $this; + } + + public function getContactId(): int + { + return $this->contactId; + } + + public function setContactId(int $contactId): self + { + $this->contactId = $contactId; + + return $this; + } + + public function getChatId(): ?string + { + return $this->chatId; + } + + public function setChatId(?string $chatId): self + { + $this->chatId = $chatId; + + return $this; + } + + public function getEntityId(): ?int + { + return $this->entityId; + } + + public function setEntityId(?int $entityId): self + { + $this->entityId = $entityId; + + return $this; + } + + public function getEntityType(): ?string + { + return $this->entityType; + } + + public function setEntityType(?string $entityType): self + { + $this->entityType = $entityType; + + return $this; + } + + public function isInWork(): bool + { + return $this->isInWork; + } + + public function setIsInWork(bool $isInWork): self + { + $this->isInWork = $isInWork; + + return $this; + } + + public function isRead(): bool + { + return $this->isRead; + } + + public function setIsRead(bool $isRead): self + { + $this->isRead = $isRead; + + return $this; + } + + public function getOrigin(): string + { + return $this->origin; + } + + public function setOrigin(string $origin): self + { + $this->origin = $origin; + + return $this; + } + + public function getMissedAt(): ?int + { + return $this->missedAt; + } + + public function setMissedAt(?int $missedAt): self + { + $this->missedAt = $missedAt; + + return $this; + } + + public function getAccountId(): int + { + return $this->accountId; + } + + public function setAccountId(int $accountId): self + { + $this->accountId = $accountId; + + return $this; + } + + /** + * @inheritDoc + */ + public function toArray(): array + { + return [ + 'talk_id' => $this->getTalkId(), + 'created_at' => $this->getCreatedAt(), + 'updated_at' => $this->getUpdatedAt(), + 'rate' => $this->getRate(), + 'contact_id' => $this->getContactId(), + 'chat_id' => $this->getChatId(), + 'entity_id' => $this->getEntityId(), + 'entity_type' => $this->getEntityType(), + 'is_in_work' => $this->isInWork(), + 'is_read' => $this->isRead(), + 'origin' => $this->getOrigin(), + 'missed_at' => $this->getMissedAt(), + 'account_id' => $this->getAccountId(), + ]; + } + + /** + * @param string|null $requestId + * + * @return array + * @throws NotAvailableForActionException + */ + public function toApi(?string $requestId = "0"): array + { + throw new NotAvailableForActionException(); + } +} diff --git a/src/AmoCRM/Models/Talks/TalkCloseActionModel.php b/src/AmoCRM/Models/Talks/TalkCloseActionModel.php new file mode 100644 index 00000000..dbc9c97c --- /dev/null +++ b/src/AmoCRM/Models/Talks/TalkCloseActionModel.php @@ -0,0 +1,50 @@ +talkId = $talkId; + $this->forceClose = $forceClose; + } + + public function getTalkId(): int + { + return $this->talkId; + } + + public function setTalkId(int $talkId): self + { + $this->talkId = $talkId; + + return $this; + } + + public function isForceClose(): bool + { + return $this->forceClose; + } + + public function setForceClose(bool $forceClose): self + { + $this->forceClose = $forceClose; + + return $this; + } +}