├── .gitattributes
├── .gitignore
├── LICENSE
├── README.md
├── assets
├── yclients-logo-social.png
└── yclients-logo.png
├── composer.json
└── src
└── Yclients
├── YclientsApi.php
├── YclientsException.php
├── YclientsRequest.php
└── cacert.pem
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea/
2 | examples/
3 | logs/
4 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 slowprog
4 | Copyright (c) 2019-2024 andrey-tech
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | SOFTWARE.
23 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # YCLIENTS API PHP Wrapper
2 |
3 | 
4 |
5 | Обертка на PHP7+ для работы с [REST API YCLIENTS v2.0](https://yclients.docs.apiary.io/)
6 | c троттлингом запросов к API и логированием в файл.
7 |
8 | Данная библиотека является форком [Yclients API wrapper](https://github.com/slowprog/yclients-api) со следующими изменениями:
9 |
10 | - добавлен регулируемый троттлинг запросов к API;
11 | - добавлена отключаемая проверка SSL/TLS-сертификата сервера YCLIENTS;
12 | - добавлена проверка наличия сообщений об ошибках в ответе API;
13 | - добавлено логирование запросов и ответов сервера в файл или STDOUT;
14 | - изменен и дополнен тест сообщений об ошибках;
15 | - добавлены методы getSchedule(), getGroups();
16 | - изменен метод postHooks() в связи с изменениями в API;
17 | - добавлен метод getAll() для выгрузки всех сущностей одного типа с использованием генератора при обработке больших объемов данных.
18 |
19 | ## Содержание
20 |
21 |
22 |
23 | - [Требования](#%D0%A2%D1%80%D0%B5%D0%B1%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F)
24 | - [Установка](#%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0)
25 | - [Класс `YclientsApi`](#%D0%9A%D0%BB%D0%B0%D1%81%D1%81-yclientsapi)
26 | - [Список методов класса](#%D0%A1%D0%BF%D0%B8%D1%81%D0%BE%D0%BA-%D0%BC%D0%B5%D1%82%D0%BE%D0%B4%D0%BE%D0%B2-%D0%BA%D0%BB%D0%B0%D1%81%D1%81%D0%B0)
27 | - [Авторизация](#%D0%90%D0%B2%D1%82%D0%BE%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F)
28 | - [Онлайн-запись](#%D0%9E%D0%BD%D0%BB%D0%B0%D0%B9%D0%BD-%D0%B7%D0%B0%D0%BF%D0%B8%D1%81%D1%8C)
29 | - [Записи пользователя](#%D0%97%D0%B0%D0%BF%D0%B8%D1%81%D0%B8-%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D1%82%D0%B5%D0%BB%D1%8F)
30 | - [Сети салонов](#%D0%A1%D0%B5%D1%82%D0%B8-%D1%81%D0%B0%D0%BB%D0%BE%D0%BD%D0%BE%D0%B2)
31 | - [Компании](#%D0%9A%D0%BE%D0%BC%D0%BF%D0%B0%D0%BD%D0%B8%D0%B8)
32 | - [Категория услуг](#%D0%9A%D0%B0%D1%82%D0%B5%D0%B3%D0%BE%D1%80%D0%B8%D1%8F-%D1%83%D1%81%D0%BB%D1%83%D0%B3)
33 | - [Услуги](#%D0%A3%D1%81%D0%BB%D1%83%D0%B3%D0%B8)
34 | - [Сотрудники](#%D0%A1%D0%BE%D1%82%D1%80%D1%83%D0%B4%D0%BD%D0%B8%D0%BA%D0%B8)
35 | - [Клиенты](#%D0%9A%D0%BB%D0%B8%D0%B5%D0%BD%D1%82%D1%8B)
36 | - [Записи](#%D0%97%D0%B0%D0%BF%D0%B8%D1%81%D0%B8)
37 | - [Расписание работы сотрудников](#%D0%A0%D0%B0%D1%81%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D0%B5-%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D1%8B-%D1%81%D0%BE%D1%82%D1%80%D1%83%D0%B4%D0%BD%D0%B8%D0%BA%D0%BE%D0%B2)
38 | - [Даты для журнала](#%D0%94%D0%B0%D1%82%D1%8B-%D0%B4%D0%BB%D1%8F-%D0%B6%D1%83%D1%80%D0%BD%D0%B0%D0%BB%D0%B0)
39 | - [Комментарии](#%D0%9A%D0%BE%D0%BC%D0%BC%D0%B5%D0%BD%D1%82%D0%B0%D1%80%D0%B8%D0%B8)
40 | - [Пользователи компании](#%D0%9F%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D1%82%D0%B5%D0%BB%D0%B8-%D0%BA%D0%BE%D0%BC%D0%BF%D0%B0%D0%BD%D0%B8%D0%B8)
41 | - [Кассы](#%D0%9A%D0%B0%D1%81%D1%81%D1%8B)
42 | - [SMS рассылка](#sms-%D1%80%D0%B0%D1%81%D1%81%D1%8B%D0%BB%D0%BA%D0%B0)
43 | - [Склады](#%D0%A1%D0%BA%D0%BB%D0%B0%D0%B4%D1%8B)
44 | - [Уведомления о событиях webhooks](#%D0%A3%D0%B2%D0%B5%D0%B4%D0%BE%D0%BC%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F-%D0%BE-%D1%81%D0%BE%D0%B1%D1%8B%D1%82%D0%B8%D1%8F%D1%85-webhooks)
45 | - [Вспомогательные методы](#%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D1%8B%D0%B5-%D0%BC%D0%B5%D1%82%D0%BE%D0%B4%D1%8B)
46 | - [Дополнительные параметры](#%D0%94%D0%BE%D0%BF%D0%BE%D0%BB%D0%BD%D0%B8%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D1%8B%D0%B5-%D0%BF%D0%B0%D1%80%D0%B0%D0%BC%D0%B5%D1%82%D1%80%D1%8B)
47 | - [Примеры](#%D0%9F%D1%80%D0%B8%D0%BC%D0%B5%D1%80%D1%8B)
48 | - [Авторы](#%D0%90%D0%B2%D1%82%D0%BE%D1%80%D1%8B)
49 | - [Лицензия](#%D0%9B%D0%B8%D1%86%D0%B5%D0%BD%D0%B7%D0%B8%D1%8F)
50 |
51 |
52 |
53 |
54 | ## Требования
55 |
56 | - PHP >= 7.0.
57 | - Произвольный автозагрузчик классов, реализующий стандарт [PSR-4](https://www.php-fig.org/psr/psr-4/).
58 |
59 |
60 |
61 | ## Установка
62 |
63 | Установка через composer:
64 | ```
65 | $ composer require andrey-tech/yclients-api-php
66 | ```
67 |
68 | или добавить
69 |
70 | ```
71 | "andrey-tech/yclients-api-php": "^1.7"
72 | ```
73 |
74 | в секцию require файла composer.json.
75 |
76 |
77 |
78 | ## Класс `YclientsApi`
79 |
80 | Для работы с REST API YCLIENTS используется методы класса `\Yclients\YclientsApi`.
81 | При возникновении ошибок выбрасывается исключение с объектом класса `\Yclients\YclientsException`.
82 |
83 |
84 | ### Список методов класса
85 |
86 | - `__construct(string $tokenPartner = null)` Конструктор класса.
87 |
88 |
89 | #### Авторизация
90 |
91 | - `setTokenPartner(string $tokenPartner) :void` Устанавливает токен партнера.
92 | - `getTokenPartner() :string` Возвращает токен партнера.
93 | - `getAuth(string $login, string $password) :array` Выполняет авторизацию и возвращает токен пользователя.
94 |
95 |
96 | #### Онлайн-запись
97 |
98 | - `getBookform($id) :array` Возвращает настройки формы бронирования.
99 | - `getI18n($locale = 'ru-RU') :array` Возвращает параметры интернационализации.
100 | - `getBookServices($companyId, $staffId = null, \DateTime $datetime = null, array $serviceIds = null, array $eventIds = null) :array`
101 | Возвращает список услуг, доступных для бронирования.
102 | - `getBookStaff($companyId, $staffId = null, \DateTime $datetime = null, array $serviceIds = null, array $eventIds = null, $withoutSeances = false) :array`
103 | Возвращает список сотрудников, доступных для бронирования.
104 | - `getBookDates($companyId, $staffId = null, array $serviceIds = null, \DateTime $date = null, array $eventIds = null) :array`
105 | Возвращает список дат, доступных для бронирования.
106 | - `getBookTimes($companyId, $staffId, \DateTime $date, array $serviceIds = null, array $eventIds = null) : array`
107 | Возвращает список сеансов, доступных для бронирования.
108 | - `postBookCode($companyId, $phone, $fullname = null) :array` Отправляет СМС код подтверждения номера телефона.
109 | - `postBookCheck($companyId, array $appointments): array` Проверяет параметры записи.
110 | - `postBookRecord($companyId, array $person, array $appointments, $code = null, array $notify = null, $comment = null, $apiId = null) :array`
111 | Создает запись на сеанс.
112 |
113 |
114 | #### Записи пользователя
115 |
116 | - `postUserAuth($phone, $code) :array` Выполняет авторизовацию пользователя по номеру телефона и SMS-коду.
117 | - `getUserRecords($recordId, $recordHash = null, $userToken = null): array` Возвращает записи пользователя.
118 | - `deleteUserRecords($recordId, $recordHash = null, $userToken = null): array` Удаляет записи пользователя.
119 |
120 |
121 | #### Сети салонов
122 |
123 | - `getGroups($userToken): array` Возвращает список доступных сетей салонов
124 |
125 |
126 | #### Компании
127 |
128 | - `getCompanies($groupId = null, $active = null, $moderated = null, $forBooking = null, $my = null, $userToken = null) :array`
129 | Возвращает список компаний.
130 | - `postCompany(array $fields, $userToken) :array` Создает компанию.
131 | - `getCompany($id) :array` Возвращает компанию.
132 | - `putCompany($id, array $fields, $userToken) :array` Изменяет компанию.
133 | - `deleteCompany($id) :array` Удаляет компанию.
134 | - `getCompanyAnalytics($companyId, $dateFrom, $dateTo, $userToken)` Возвращает основные показатели компании.
135 |
136 |
137 | #### Категория услуг
138 |
139 | - `getServiceCategories($companyId, $categoryId = null, $staffId = null) :array` Возвращает список категорий услуг.
140 | - `postServiceCategories($companyId, $categoryId, $fields, $userToken) :array` Создает категорию услуг.
141 | - `getServiceCategory($companyId, $categoryId) :array` Возвращает категорию услуг.
142 | - `putServiceCategory($companyId, $categoryId, $fields, $userToken) :array` Изменяет категорию услуг.
143 | - `deleteServiceCategory($companyId, $categoryId, $userToken) :array` Удаляет категорию услуг.
144 |
145 |
146 | #### Услуги
147 |
148 | - `getServices($companyId, $serviceId = null, $staffId = null, $categoryId = null) :array` Возвращает список услуг или конкретную услугу.
149 | - `postServices($companyId, $serviceId, $categoryId, $title, $userToken, array $fields = null) :array` Создает новую услугу.
150 | - `putServices($companyId, $serviceId, $categoryId, $title, $userToken, array $fields = null) :array` Изменяет услугу.
151 | - `deleteServices($companyId, $serviceId, $userToken) :array` Удаляет услугу.
152 |
153 |
154 | #### Сотрудники
155 |
156 | - `getStaff($companyId, $staffId = null) :array` Возвращает список сотрудников или конкретного сотрудника.
157 | - `postStaff($companyId, $staffId, $name, $userToken, array $fields = null) :array` Добавляет нового сотрудника.
158 | - `putStaff($companyId, $staffId, array $fields, $userToken) :array` Изменяет сотрудника.
159 | - `deleteStaff($companyId, $staffId, $userToken) :array` Удаляет сотрудника.
160 |
161 |
162 | #### Клиенты
163 |
164 | - `getClients($companyId, $userToken, $fullname = null, $phone = null, $email = null, $page = null, $count = null) :array`
165 | Возвращает список клиентов.
166 | - `postClients($companyId, $name, $phone, $userToken, array $fields = []) :array` Добавляет клиента.
167 | - `getClient($companyId, $id, $userToken) :array` Возвращает клиента.
168 | - `putClient($companyId, $id, $userToken, array $fields) :array` Изменяет клиента.
169 | - `deleteClient($companyId, $id, $userToken) :array` Удаляет клиента.
170 |
171 |
172 | #### Записи
173 |
174 | - `getRecords($companyId, $userToken, $page = null, $count = null, $staffId = null, $clientId = null, \DateTime $startDate = null, \DateTime $endDate = null, \DateTime $cStartDate = null, \DateTime $cEndDate = null, \DateTime $changedAfter = null, \DateTime $changedBefore = null) :array`
175 | Возвращает список записей.
176 | - `postRecords($companyId, $userToken, $staffId, $services, $client, \DateTime $datetime, $seanceLength, $saveIfBusy, $sendSms, $comment = null, $smsRemainHours = null, $emailRemainHours = null, $apiId = null, $attendance = null) :array`
177 | Создает новую запись.
178 | - `getRecord($companyId, $recordId, $userToken) :array` Возвращает запись.
179 | - `putRecord($companyId, $recordId, $userToken, array $fields) :array` Изменяет запись.
180 | - `deleteRecord($companyId, $recordId, $userToken) :array` Удаляет запись.
181 |
182 |
183 | #### Расписание работы сотрудников
184 |
185 | - `getSchedule($companyId, $staffId, $startDate, $endDate, $userToken) :array` Возвращает расписание работы сотрудника.
186 | - `putSchedule($companyId, $staffId, $userToken, $fields) :array` Изменяет расписание работы сотрудника.
187 |
188 |
189 | #### Даты для журнала
190 |
191 | - `getTimetableDates($companyId, \DateTime $date, $staffId, $userToken) :array` Возвращает список дат для журнала.
192 | - `getTimetableSeances($companyId, \DateTime $date, $staffId, $userToken) :array` Возвращает список сеансов для журнала.
193 |
194 |
195 | #### Комментарии
196 |
197 | - `getComments($companyId, $userToken, \DateTime $startDate = null, \DateTime $endDate = null, $staffId = null, $rating = null) :array`
198 | Возвращает комментарии.
199 |
200 |
201 | #### Пользователи компании
202 |
203 | - `getCompanyUsers($companyId, $userToken) :array` Возвращает пользователей компании.
204 |
205 |
206 | #### Кассы
207 |
208 | - `getAccounts($companyId, $userToken) :array` Возвращает кассы компании.
209 |
210 |
211 | #### SMS рассылка
212 |
213 | - `sendSMS($companyId, $userToken, $clientIds, $text) :array` Отправляет SMS.
214 |
215 |
216 | #### Склады
217 |
218 | - `getStorages($companyId, $userToken) :array` Возвращает склады компании.
219 |
220 |
221 | #### Уведомления о событиях webhooks
222 |
223 | - `getHooks($companyId, $userToken) :array` Возвращает настройки уведомлений о событиях.
224 | - `postHooks($companyId, $fields, $userToken) :array` Изменяет настройки уведомлений о событиях.
225 |
226 |
227 | #### Вспомогательные методы
228 |
229 | - `getAll($callback) :\Generator` Загружает все сущности одного типа.
230 | + `$callback` - анонимная функция `function(int $page, int $count) { ... }`, реализующая постраничную загрузку сущностей
231 | с помощью методов `getClients()` или `getRecords()`:
232 | * `$page` - номер загружаемой страницы;
233 | * `$count` - максимальное количество сущностей, загружаемых на странице.
234 |
235 |
236 | ### Дополнительные параметры
237 |
238 | Дополнительные параметры работы устанавливаются через публичные свойства объекта класса `YclientsApi`.
239 |
240 | | Свойство | По умолчанию | Описание |
241 | |-------------------------|----------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
242 | | `$debug` | false | Включает отладочный режим с сохранением запросов и ответов в лог файл или выводом в STDOUT |
243 | | `$debugLogFile` | logs/debug.log | Устанавливает лог файл отладочного режима (null - вывод в STDOUT) |
244 | | `$throttle` | 5 | Устанавливает максимальное число запросов к API YCLIENTS в секунду ([не более 5 запросов в секунду](https://yclients.docs.apiary.io/)), значение 0 отключает троттлинг запросов к API |
245 | | `$verifySSLCerfificate` | true | Включает проверку SSL/TLS-сертификата сервера YCLIENTS |
246 | | `$SSLCertificateFile` | 'cacert.pem' | Устанавливает файл SSL/TLS-сертификатов X.509 корневых удостоверяющих центров (CA) в формате РЕМ (null - файл, указанный в `curl.cainfo` php.ini) |
247 | | `$curlConnectTimeout` | 30 | Устанавливает таймаут соединения с сервером YCLIENTS, секунды |
248 | | `$curlTimeout` | 30 | Устанавливает таймаут обмена данными с сервером YCLIENTS, секунды |
249 | | `$limitCount` | 300 | Максимальное количество сушностей, загружаемых за один запрос к API в методе `getAll()` |
250 |
251 |
252 | ### Примеры
253 |
254 | ```php
255 | use Yclients\YclientsApi;
256 |
257 | try {
258 |
259 | $login = 'user@example.com';
260 | $password = '37*%4Hd.Uda)532';
261 | $tokenPartner = 'erd8jrpo4mk7lsk8krs';
262 |
263 | $yc = new YclientsApi($tokenPartner);
264 |
265 | // Включаем отладочный режим с логированием в файл
266 | $yc->debug = true;
267 |
268 | // Устанавливаем лог файл отладочного режима
269 | $ys->debugLogFile = 'logs/debug_yclients_api.log';
270 |
271 | // Устанавливает максимальное число запросов к API YCLIENTS в секунду (значение 0 отключает троттлинг запросов к API)
272 | $yc->throttle = 1;
273 |
274 | // Выполняем авторизацию и получаем токен пользователя
275 | $response = $yc->getAuth($login, $password);
276 | $userToken = $response['user_token'];
277 |
278 | /*
279 | * Получаем список активных, прошедших модерацию компаний YCLINETS,
280 | * на управление которыми пользователь имеет права
281 | */
282 | $companies = $yc->getCompanies(
283 | $groupId = null,
284 | $active = true,
285 | $moderated = true,
286 | $forBooking = null,
287 | $my = 1,
288 | $userToken
289 | );
290 |
291 | // Получаем ID первой компании
292 | $companyId = $companies[0]['id'];
293 |
294 | // Получаем всех пользователей первой компании
295 | $users = $yc->getCompanyUsers($companyId, $userToken);
296 | print_r($users);
297 |
298 | // Получаем всех сотрудников компании
299 | $staff = $yc->getStaff($companyId);
300 | print_r($staff);
301 |
302 | // Получаем ID первого сотрудника
303 | $workerId = $staff[0]['id'];
304 |
305 | // Загружаем расписание работы первого сотрудника на 1 месяц
306 | $schedule = $yc->getSchedule(
307 | $companyId,
308 | $workerId,
309 | $startDate = '2020-01-01',
310 | $endDate = '2020-01-31'
311 | $userToken
312 | );
313 | print_r($schedule);
314 |
315 | /**
316 | * Выгружаем всех клиентов заданной компании с использованием генератора
317 | * при обработке больших объемов данных
318 | */
319 | $generator = $yc->getAll(
320 | function (int $page, int $count) use ($yc, $companyId, $userToken) {
321 | return $yc->getClients(
322 | $companyId,
323 | $userToken,
324 | $fullname = null,
325 | $phone = null,
326 | $email = null,
327 | $page,
328 | $count
329 | );
330 | }
331 | );
332 | foreach ($generator as $response) {
333 | $clients = $response['data'];
334 | foreach ($clients as $client) {
335 | print_r($client);
336 | }
337 | }
338 |
339 | /**
340 | * Выгружаем все записи сотрудника заданной компании с использованием генератора
341 | * при обработке больших объемов данных
342 | */
343 | $generator = $yc->getAll(
344 | function (int $page, int $count) use ($yc, $companyId, $userToken, $workerId) {
345 | return $yc->getRecords(
346 | $companyId,
347 | $userToken,
348 | $page,
349 | $count,
350 | $workerId
351 | );
352 | }
353 | );
354 | foreach ($generator as $response) {
355 | $records = $response['data'];
356 | foreach ($records as $record) {
357 | print_r($record);
358 | }
359 | }
360 |
361 | } catch (\Yclients\YclientsException $e) {
362 | printf('Ошибка (%d): %s' . PHP_EOL, $e->getCode(), $e->getMessage());
363 | }
364 | ```
365 |
366 |
367 | ## Авторы
368 |
369 | © 2018 slowprog
370 | © 2019-2024 andrey-tech
371 |
372 |
373 | ## Лицензия
374 |
375 | Данная библиотека распространяется на условиях лицензии [MIT](./LICENSE).
376 |
--------------------------------------------------------------------------------
/assets/yclients-logo-social.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrey-tech/yclients-api-php/2f29b177bbaa118ab4db1288b913ba4545975978/assets/yclients-logo-social.png
--------------------------------------------------------------------------------
/assets/yclients-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrey-tech/yclients-api-php/2f29b177bbaa118ab4db1288b913ba4545975978/assets/yclients-logo.png
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "andrey-tech/yclients-api-php",
3 | "description": "Обертка для работы с API YCLIENTS v2.0 c троттлингом запросов и логированием в файл",
4 | "keywords": [ "yclients", "api", "api-wrapper", "throttling", "logging" ],
5 | "homepage": "https://github.com/andrey-tech/yclients-api-php",
6 | "minimum-stability": "stable",
7 | "license": "MIT",
8 | "authors": [
9 | {
10 | "name": "andrey-tech",
11 | "homepage": "https://github.com/andrey-tech/",
12 | "role": "Developer"
13 | },
14 | {
15 | "name": "Andrey Tyshev",
16 | "role": "Developer"
17 | }
18 | ],
19 | "require": {
20 | "php": ">=7.0",
21 | "ext-curl": "*",
22 | "ext-json": "*"
23 | },
24 | "autoload": {
25 | "psr-4": {
26 | "Yclients\\": "src/Yclients"
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/Yclients/YclientsApi.php:
--------------------------------------------------------------------------------
1 | setTokenPartner($tokenPartner);
79 | }
80 |
81 | /**
82 | * Установку токена можно сделать отдельно т.к. есть запросы не
83 | * требующие авторизации партнёра
84 | *
85 | * @param string $tokenPartner
86 | * @return self
87 | * @access public
88 | */
89 | public function setTokenPartner($tokenPartner)
90 | {
91 | $this->tokenPartner = $tokenPartner;
92 |
93 | return $this;
94 | }
95 |
96 | public function getTokenPartner()
97 | {
98 | return $this->tokenPartner;
99 | }
100 |
101 | /**
102 | * Получаем токен пользователя по логину-паролю
103 | *
104 | * @param string $login
105 | * @param string $password
106 | * @return array
107 | * @access public
108 | * @see http://docs.yclients.apiary.io/#reference/0/0/0
109 | * @throws YclientsException
110 | */
111 | public function getAuth($login, $password)
112 | {
113 | return $this->request('auth', [
114 | 'login' => $login,
115 | 'password' => $password,
116 | ], self::METHOD_POST);
117 | }
118 |
119 | /**
120 | * Получаем настройки формы бронирования
121 | *
122 | * @param integer $id
123 | * @return array
124 | * @access public
125 | * @see http://docs.yclients.apiary.io/#reference/-/0/0
126 | * @throws YclientsException
127 | */
128 | public function getBookform($id)
129 | {
130 | return $this->request('bookform/' . $id);
131 | }
132 |
133 | /**
134 | * Получаем параметры интернационализации
135 | *
136 | * @param string $locale - ru-RU, lv-LV, en-US, ee-EE, lt-LT, de-DE, uk-UK
137 | * @return array
138 | * @access public
139 | * @see http://docs.yclients.apiary.io/#reference/-/1/0
140 | * @throws YclientsException
141 | */
142 | public function getI18n($locale = 'ru-RU')
143 | {
144 | return $this->request('i18n/' . $locale);
145 | }
146 |
147 | /**
148 | * Получить список услуг доступных для бронирования
149 | *
150 | * @param integer $companyId
151 | * @param integer $staffId - ID сотрудника. Фильтр по идентификатору сотрудника
152 | * @param \DateTime $datetime - дата (в формате iso8601). Фильтр по дате
153 | * бронирования услуги (например '2005-09-09T18:30')
154 | * @param array $serviceIds - ID услуг. Фильтр по списку идентификаторов уже
155 | * выбранных (в рамках одной записи) услуг. Имеет
156 | * смысл если зада фильтр по мастеру и дате.
157 | * @param array $eventIds - ID акций. Фильтр по списку идентификаторов уже выбранных
158 | * (в рамках одной записи) акций. Имеет смысл если зада
159 | * фильтр по мастеру и дате.
160 | * @return array
161 | * @access public
162 | * @see http://docs.yclients.apiary.io/#reference/-/2/0
163 | * @throws YclientsException
164 | */
165 | public function getBookServices(
166 | $companyId,
167 | $staffId = null,
168 | \DateTime $datetime = null,
169 | array $serviceIds = null,
170 | array $eventIds = null
171 | ) {
172 | $parameters = [];
173 |
174 | if ($staffId !== null) {
175 | $parameters['staff_id'] = $staffId;
176 | }
177 |
178 | if ($datetime !== null) {
179 | $parameters['datetime'] = $datetime->format(\DateTime::ISO8601);
180 | }
181 |
182 | if ($serviceIds !== null) {
183 | $parameters['service_ids'] = $serviceIds;
184 | }
185 |
186 | if ($eventIds !== null) {
187 | $parameters['event_ids'] = $eventIds;
188 | }
189 |
190 | return $this->request('book_services/' . $companyId, $parameters);
191 | }
192 |
193 | /**
194 | * Получить список сотрудников доступных для бронирования
195 | *
196 | * @param integer $companyId
197 | * @param integer $staffId - ID сотрудника. Фильтр по идентификатору сотрудника
198 | * @param \DateTime $datetime - дата (в формате iso8601). Фильтр по дате
199 | * бронирования услуги (например '2005-09-09T18:30')
200 | * @param array $serviceIds - ID услуг. Фильтр по списку идентификаторов уже
201 | * выбранных (в рамках одной записи) услуг. Имеет
202 | * смысл если зада фильтр по мастеру и дате.
203 | * @param array $eventIds - ID акций. Фильтр по списку идентификаторов уже выбранных
204 | * (в рамках одной записи) акций. Имеет смысл если зада
205 | * фильтр по мастеру и дате.
206 | * @param bool $withoutSeances - Отключает выдачу ближайших свободных сеансов,
207 | * ускоряет получение данных.
208 | * @return array
209 | * @access public
210 | * @see http://docs.yclients.apiary.io/#reference/-/3/0
211 | * @throws YclientsException
212 | */
213 | public function getBookStaff(
214 | $companyId,
215 | $staffId = null,
216 | \DateTime $datetime = null,
217 | array $serviceIds = null,
218 | array $eventIds = null,
219 | $withoutSeances = false
220 | ) {
221 | $parameters = [];
222 |
223 | if ($staffId !== null) {
224 | $parameters['staff_id'] = $staffId;
225 | }
226 |
227 | if ($datetime !== null) {
228 | $parameters['datetime'] = $datetime->format(\DateTime::ISO8601);
229 | }
230 |
231 | if ($serviceIds !== null) {
232 | $parameters['service_ids'] = $serviceIds;
233 | }
234 |
235 | if ($eventIds !== null) {
236 | $parameters['event_ids'] = $eventIds;
237 | }
238 |
239 | if ($withoutSeances) {
240 | $parameters['without_seances'] = true;
241 | }
242 |
243 | return $this->request('book_staff/' . $companyId, $parameters);
244 | }
245 |
246 | /**
247 | * Получить список дат доступных для бронирования
248 | *
249 | * @param integer $companyId
250 | * @param integer $staffId - ID сотрудника. Фильтр по идентификатору сотрудника
251 | * @param array $serviceIds - ID услуг. Фильтр по списку идентификаторов уже
252 | * выбранных (в рамках одной записи) услуг. Имеет
253 | * смысл если зада фильтр по мастеру и дате.
254 | * @param \DateTime $date - Фильтр по месяцу бронирования (например '2015-09-01')
255 | * @param array $eventIds - ID акций. Фильтр по списку идентификаторов уже выбранных
256 | * (в рамках одной записи) акций. Имеет смысл если зада
257 | * фильтр по мастеру и дате.
258 | * @return array
259 | * @access public
260 | * @see http://docs.yclients.apiary.io/#reference/-/4/0
261 | * @throws YclientsException
262 | */
263 | public function getBookDates(
264 | $companyId,
265 | $staffId = null,
266 | array $serviceIds = null,
267 | \DateTime $date = null,
268 | array $eventIds = null
269 | ) {
270 | $parameters = [];
271 |
272 | if ($staffId !== null) {
273 | $parameters['staff_id'] = $staffId;
274 | }
275 |
276 | if ($date !== null) {
277 | $parameters['date'] = $date->format('Y-m-d');
278 | }
279 |
280 | if ($serviceIds !== null) {
281 | $parameters['service_ids'] = $serviceIds;
282 | }
283 |
284 | if ($eventIds !== null) {
285 | $parameters['event_ids'] = $eventIds;
286 | }
287 |
288 | return $this->request('book_dates/' . $companyId, $parameters);
289 | }
290 |
291 | /**
292 | * Получить список сеансов доступных для бронирования
293 | *
294 | * @param integer $companyId
295 | * @param integer $staffId - ID сотрудника. Фильтр по идентификатору сотрудника
296 | * @param \DateTime $date - Фильтр по месяцу бронирования (например '2015-09-01')
297 | * @param array $serviceIds - ID услуг. Фильтр по списку идентификаторов уже
298 | * выбранных (в рамках одной записи) услуг. Имеет
299 | * смысл если зада фильтр по мастеру и дате.
300 | * @param array $eventIds - ID акций. Фильтр по списку идентификаторов уже выбранных
301 | * (в рамках одной записи) акций. Имеет смысл если зада
302 | * фильтр по мастеру и дате.
303 | * @return array
304 | * @access public
305 | * @see http://docs.yclients.apiary.io/#reference/-/5/0
306 | * @throws YclientsException
307 | */
308 | public function getBookTimes(
309 | $companyId,
310 | $staffId,
311 | \DateTime $date,
312 | array $serviceIds = null,
313 | array $eventIds = null
314 | ) {
315 | $parameters = [];
316 |
317 | if ($serviceIds !== null) {
318 | $parameters['service_ids'] = $serviceIds;
319 | }
320 |
321 | if ($eventIds !== null) {
322 | $parameters['event_ids'] = $eventIds;
323 | }
324 |
325 | return $this->request('book_times/' . $companyId . '/' . $staffId . '/' . $date->format('Y-m-d'), $parameters);
326 | }
327 |
328 | /**
329 | * Отправить СМС код подтверждения номера телефона
330 | *
331 | * @param integer $companyId
332 | * @param string $phone - Телефон, на который будет отправлен код, вида 79991234567
333 | * @param string $fullname - Имя клиента
334 | * @return array
335 | * @access public
336 | * @see http://docs.yclients.apiary.io/#reference/-/6/0
337 | * @throws YclientsException
338 | */
339 | public function postBookCode($companyId, $phone, $fullname = null)
340 | {
341 | $parameters = [
342 | 'phone' => $phone
343 | ];
344 |
345 | if ($fullname !== null) {
346 | $parameters['fullname'] = $fullname;
347 | }
348 |
349 | return $this->request('book_code/' . $companyId, $parameters, self::METHOD_POST);
350 | }
351 |
352 | /**
353 | * Проверить параметры записи
354 | *
355 | * @param integer $companyId
356 | * @param array $appointments - Массив записей со следующими полями:
357 | * integer id - Идентификатор записи
358 | * array services - Массив идентификторов услуг
359 | * array events - Массив идентификторов акций
360 | * integer staff_id - Идентификатор специалиста
361 | * string datetime - Дата и время сеанса в формате ISO8601 (2015-09-29T13:00:00+04:00)
362 | * @return array
363 | * @access public
364 | * @see http://docs.yclients.apiary.io/#reference/-/7/0
365 | * @throws YclientsException
366 | */
367 | public function postBookCheck($companyId, array $appointments)
368 | {
369 | // проверим наличие обязательных параметров
370 | foreach ($appointments as $appointment) {
371 | if (!isset($appointment['id'], $appointment['staff_id'], $appointment['datetime'])) {
372 | throw new YclientsException('Запись должна содержать все обязательные поля: id, staff_id, datetime.');
373 | }
374 | }
375 |
376 | return $this->request('book_check/' . $companyId, $appointments, self::METHOD_POST);
377 | }
378 |
379 | /**
380 | * Создать запись на сеанс
381 | *
382 | * @param integer $companyId
383 | * @param array $person - Массив обязательных данных клиента со следующими полями:
384 | * string phone - Телефон клиента вида 79161502239
385 | * string fullname
386 | * string email
387 | * @param array $appointments - Массив записей со следующими полями:
388 | * integer id - Идентификатор записи для обратной связи
389 | * array services - Массив идентификторов услуг
390 | * array events - Массив идентификторов акций
391 | * integer staff_id - Идентификатор специалиста
392 | * string datetime - Дата и время сеанса в формате ISO8601 (2015-09-29T13:00:00+04:00)
393 | * @param string $code - Код подтверждения номера телефона
394 | * @param array $notify - Массив используемых нотификацией со следующими ключами:
395 | * string notify_by_sms - За какое кол-во часов напоминанить по смс о записи (0 если не нужно)
396 | * string notify_by_email - За какое кол-во часов напоминанить по email о записи (0 если не нужно)
397 | * @param string $comment - Комментарий к записи
398 | * @param string $apiId - Внешний идентификатор записи
399 | * @return array
400 | * @access public
401 | * @see http://docs.yclients.apiary.io/#reference/-/8/0
402 | * @throws YclientsException
403 | */
404 | public function postBookRecord(
405 | $companyId,
406 | array $person,
407 | array $appointments,
408 | $code = null,
409 | array $notify = null,
410 | $comment = null,
411 | $apiId = null
412 | ) {
413 | $parameters = [];
414 |
415 | // проверим наличие обязательных параметров клиента
416 | if (!isset($person['phone'], $person['fullname'], $person['email'])) {
417 | throw new YclientsException('Клиент должен содержать все обязательные поля: phone, fullname, email.');
418 | }
419 |
420 | $parameters = array_merge($parameters, $person);
421 |
422 | if (!count($appointments)) {
423 | throw new YclientsException('Должна быть хотя бы одна запись.');
424 | }
425 |
426 | // проверим наличие обязательных параметров записей
427 | foreach ($appointments as $appointment) {
428 | if (!isset($appointment['id'], $appointment['staff_id'], $appointment['datetime'])) {
429 | throw new YclientsException('Запись должна содержать все обязательные поля: id, staff_id, datetime.');
430 | }
431 | }
432 |
433 | $parameters['appointments'] = $appointments;
434 |
435 | if ($notify) {
436 | if (isset($notify['notify_by_sms'])) {
437 | $parameters['notify_by_sms'] = $notify['notify_by_sms'];
438 | }
439 | if (isset($notify['notify_by_email'])) {
440 | $parameters['notify_by_email'] = $notify['notify_by_email'];
441 | }
442 | }
443 |
444 | if ($code !== null) {
445 | $parameters['code'] = $code;
446 | }
447 |
448 | if ($comment !== null) {
449 | $parameters['comment'] = $comment;
450 | }
451 |
452 | if ($apiId !== null) {
453 | $parameters['api_id'] = $apiId;
454 | }
455 |
456 | return $this->request('book_record/' . $companyId, $parameters, self::METHOD_POST);
457 | }
458 |
459 | /**
460 | * Авторизоваться по номеру телефона и коду
461 | *
462 | * @param string $phone - Телефон, на который будет отправлен код вида 79161005050
463 | * @param string $code - Код подтверждения номера телефона, высланный по смс
464 | * @return array
465 | * @access public
466 | * @see http://docs.yclients.apiary.io/#reference/1/0/0
467 | * @throws YclientsException
468 | */
469 | public function postUserAuth($phone, $code)
470 | {
471 | $parameters = [
472 | 'phone' => $phone,
473 | 'code' => $code,
474 | ];
475 |
476 | return $this->request('user/auth', $parameters, self::METHOD_POST);
477 | }
478 |
479 | /**
480 | * Получить записи пользователя
481 | *
482 | * @param integer $recordId - ID записи, достаточно для удаления записи если пользователь
483 | * авторизован, получить можно из ответа bookRecord()
484 | * @param string $recordHash - HASH записи, обязательно для удаления записи если пользователь
485 | * не авторизован, получить можно из ответа bookRecord()
486 | * @param string $userToken - токен для авторизации пользователя, обязательный, если $recordHash не указан
487 | * @return array
488 | * @access public
489 | * @see http://docs.yclients.apiary.io/#reference/1/1/0
490 | * @throws YclientsException
491 | */
492 | public function getUserRecords($recordId, $recordHash = null, $userToken = null)
493 | {
494 | if (!$recordHash && !$userToken) {
495 | throw new YclientsException('getUserRecords() требует обязательный 2-ой или 3-й аргумент');
496 | // trigger_error('getUserRecords() expected Argument 2 or Argument 3 required', E_USER_WARNING);
497 | }
498 |
499 | return $this->request('user/records/' . $recordId . '/' . $recordHash, [], self::METHOD_GET, $userToken ?: true);
500 | }
501 |
502 | /**
503 | * Удалить записи пользователя
504 | *
505 | * @param integer $recordId - ID записи, достаточно для удаления записи если пользователь
506 | * авторизован, получить можно из ответа bookRecord()
507 | * @param string $recordHash - HASH записи, обязательно для удаления записи если пользователь
508 | * не авторизован, получить можно из ответа bookRecord()
509 | * @param string $userToken - Токен для авторизации пользователя, обязательный, если $recordHash не указан
510 | * @return array
511 | * @access public
512 | * @see http://docs.yclients.apiary.io/#reference/1/1/1
513 | * @throws YclientsException
514 | */
515 | public function deleteUserRecords($recordId, $recordHash = null, $userToken = null)
516 | {
517 | if (!$recordHash && !$userToken) {
518 | throw new YclientsException('deleteUserRecords() требует обязательный 2-ой или 3-й аргумент');
519 | // trigger_error('deleteUserRecords() expected Argument 2 or Argument 3 required', E_USER_WARNING);
520 | }
521 |
522 | return $this->request('user/records/' . $recordId . '/' . $recordHash, [], self::METHOD_DELETE, $userToken ?: true);
523 | }
524 |
525 | /**
526 | * Получить список доступных сетей салонов
527 | * @param string $userToken - Токен для авторизации пользователя, обязательный
528 | * @return array
529 | * @access public
530 | * @see http://docs.yclients.apiary.io/#reference/33/0/0
531 | * @throws YclientsException
532 | */
533 | public function getGroups($userToken)
534 | {
535 | return $this->request('groups', [], self::METHOD_GET, $userToken);
536 | }
537 |
538 | /**
539 | * Получить основные показатели компании.
540 | *
541 | * @param string $companyId Идентификатор компании, обязательный.
542 | * @param string $dateFrom Дата начала анализируемого периода, обязательный.
543 | * @param string $dateTo Дата окончания анализируемого периода (включается в отчет), обязательный.
544 | * @param string $userToken Токен для авторизации пользователя, обязательный.
545 | *
546 | * @return array
547 | *
548 | * @see https://developers.yclients.com/ru/#tag/Analitika/paths/~1company~1%7Bcompany_id%7D~1analytics~1overall~1/get
549 | *
550 | * @throws YclientsException
551 | */
552 | public function getCompanyAnalytics($companyId, $dateFrom, $dateTo, $userToken)
553 | {
554 | if (!$companyId) {
555 | throw new YclientsException('getAnalytics() требует ID компании');
556 | }
557 |
558 | if (empty($userToken)) {
559 | throw new YclientsException('getAnalytics() требует авторизации по токену пользователя');
560 | }
561 |
562 | $parameters = [
563 | 'date_from' => $dateFrom,
564 | 'date_to' => $dateTo,
565 | ];
566 |
567 | return $this->request(
568 | sprintf('company/%s/analytics/overall/', $companyId),
569 | $parameters,
570 | self::METHOD_GET,
571 | $userToken
572 | );
573 | }
574 |
575 | /**
576 | * Получить список компаний
577 | *
578 | * @param integer $groupId - ID сети компаний
579 | * @param bool $active - Если нужно получить только активные для онлайн-записи компании
580 | * @param bool $moderated - Если нужно получить только прошедшие модерацию компании
581 | * @param bool $forBooking - Если нужно получить поле next_slot по каждой компании
582 | * @param bool $my - Если нужно компании, на управление которыми пользователь имеет права ($userToken тогда обязательно)
583 | * @param string $userToken - Токен для авторизации пользователя, обязательный, если $my указан
584 | * @return array
585 | * @access public
586 | * @see http://docs.yclients.apiary.io/#reference/2/0/0
587 | * @throws YclientsException
588 | */
589 | public function getCompanies(
590 | $groupId = null,
591 | $active = null,
592 | $moderated = null,
593 | $forBooking = null,
594 | $my = null,
595 | $userToken = null
596 | ) {
597 | if ($my && !$userToken) {
598 | throw new YclientsException('getCompanies() требует обязательный 6-ой аргумент, если установле 5-й аргумент');
599 | // trigger_error('getCompanies() expected Argument 6 if set Argument 5', E_USER_WARNING);
600 | }
601 |
602 | $parameters = [];
603 |
604 | if ($groupId !== null) {
605 | $parameters['group_id'] = $groupId;
606 | }
607 |
608 | if ($active !== null) {
609 | $parameters['active'] = $active;
610 | }
611 |
612 | if ($moderated !== null) {
613 | $parameters['moderated'] = $moderated;
614 | }
615 |
616 | if ($forBooking !== null) {
617 | $parameters['forBooking'] = $forBooking;
618 | }
619 |
620 | if ($my !== null) {
621 | $parameters['my'] = $my;
622 | }
623 |
624 | return $this->request('companies', $parameters, self::METHOD_GET, $userToken ?: true);
625 | }
626 |
627 | /**
628 | * Создать компанию
629 | *
630 | * @param array $fields - Остальные необязательные поля для создания компании
631 | * @param string $userToken - Токен для авторизации пользователя
632 | * @return array
633 | * @access public
634 | * @see http://docs.yclients.apiary.io/#reference/2/0/1
635 | * @throws YclientsException
636 | */
637 | public function postCompany(array $fields, $userToken)
638 | {
639 | if (!isset($fields['title'])) {
640 | throw new YclientsException('Для создании компании обязательно название компании.');
641 | }
642 |
643 | return $this->request('companies', $fields, self::METHOD_POST, $userToken);
644 | }
645 |
646 | /**
647 | * Получить компанию
648 | *
649 | * @param integer $id
650 | * @return array
651 | * @access public
652 | * @see http://docs.yclients.apiary.io/#reference/2/1/0
653 | * @throws YclientsException
654 | */
655 | public function getCompany($id)
656 | {
657 | return $this->request('company/' . $id);
658 | }
659 |
660 | /**
661 | * Изменить компанию
662 | *
663 | * @param integer $id
664 | * @param array $fields - Остальные необязательные поля для создания компании
665 | * @param string $userToken - Токен для авторизации пользователя
666 | * @return array
667 | * @access public
668 | * @see http://docs.yclients.apiary.io/#reference/2/1/1
669 | * @throws YclientsException
670 | */
671 | public function putCompany($id, array $fields, $userToken)
672 | {
673 | return $this->request('company/' . $id, $fields, self::METHOD_PUT, $userToken);
674 | }
675 |
676 | /**
677 | * Удалить компанию
678 | *
679 | * @param integer $id
680 | * @return array
681 | * @access public
682 | * @see http://docs.yclients.apiary.io/#reference/2/1/2
683 | * @throws YclientsException
684 | */
685 | public function deleteCompany($id)
686 | {
687 | return $this->request('company/' . $id, [], self::METHOD_DELETE);
688 | }
689 |
690 | /**
691 | * Получить список категорий услуг
692 | *
693 | * @param integer $companyId - ID компании
694 | * @param integer $categoryId - ID категории услуг
695 | * @param integer $staffId - ID сотрудника (для получения категорий, привязанных к сотруднику)
696 | * @return array
697 | * @access public
698 | * @see http://docs.yclients.apiary.io/#reference/3/0/0
699 | * @throws YclientsException
700 | */
701 | public function getServiceCategories($companyId, $categoryId = null, $staffId = null)
702 | {
703 | $parameters = [];
704 |
705 | if ($staffId !== null) {
706 | $parameters['staff_id'] = $staffId;
707 | }
708 |
709 | return $this->request('service_categories/' . $companyId . '/' . $categoryId, $parameters);
710 | }
711 |
712 | /**
713 | * Создать категорию услуг
714 | *
715 | * @param integer $companyId - ID компании
716 | * @param integer $categoryId - ID категории услуг
717 | * @param array $fields - Обязательные поля для категории со следующими полями:
718 | * string title - Название категории
719 | * integer api_id - Внешний идентификатор записи
720 | * integer weight
721 | * array staff
722 | * @param string $userToken - Токен для авторизации пользователя
723 | * @return array
724 | * @access public
725 | * @see http://docs.yclients.apiary.io/#reference/3/0/1
726 | * @throws YclientsException
727 | */
728 | public function postServiceCategories($companyId, $categoryId, $fields, $userToken)
729 | {
730 | return $this->request('service_categories/' . $companyId . '/' . $categoryId, $fields, self::METHOD_POST, $userToken);
731 | }
732 |
733 | /**
734 | * Получить категорию услуг
735 | *
736 | * @param integer $companyId - ID компании
737 | * @param integer $categoryId - ID категории услуг
738 | * @return array
739 | * @access public
740 | * @see http://docs.yclients.apiary.io/#reference/3/1/0
741 | * @throws YclientsException
742 | */
743 | public function getServiceCategory($companyId, $categoryId)
744 | {
745 | return $this->request('service_category/' . $companyId . '/' . $categoryId);
746 | }
747 |
748 | /**
749 | * Изменить категорию услуг
750 | *
751 | * @param integer $companyId - ID компании
752 | * @param integer $categoryId - ID категории услуг
753 | * @param array $fields - Обязательные поля для категории со следующими полями:
754 | * string title - Название категории
755 | * integer weight
756 | * array staff
757 | * @param string $userToken - Токен для авторизации пользователя
758 | * @return array
759 | * @access public
760 | * @see http://docs.yclients.apiary.io/#reference/3/1/1
761 | * @throws YclientsException
762 | */
763 | public function putServiceCategory($companyId, $categoryId, $fields, $userToken)
764 | {
765 | return $this->request('service_category/' . $companyId . '/' . $categoryId, $fields, self::METHOD_PUT, $userToken);
766 | }
767 |
768 | /**
769 | * Удалить категорию услуг
770 | *
771 | * @param integer $companyId - ID компании
772 | * @param integer $categoryId - ID категории услуг
773 | * @param string $userToken - Токен для авторизации пользователя
774 | * @return array
775 | * @access public
776 | * @see http://docs.yclients.apiary.io/#reference/3/1/2
777 | * @throws YclientsException
778 | */
779 | public function deleteServiceCategory($companyId, $categoryId, $userToken)
780 | {
781 | return $this->request('service_category/' . $companyId . '/' . $categoryId, [], self::METHOD_DELETE, $userToken);
782 | }
783 |
784 | /**
785 | * Получить список услуг / конкретную услугу
786 | *
787 | * @param integer $companyId - ID компании
788 | * @param integer $serviceId - ID услуги, если нужно работать с конкретной услугой
789 | * @param integer $staffId - ID сотрудника, если нужно отфильтровать по сотруднику
790 | * @param integer $categoryId - ID категории, если нужно отфильтровать по категории
791 | * @return array
792 | * @access public
793 | * @see http://docs.yclients.apiary.io/#reference/4/0//
794 | * @throws YclientsException
795 | */
796 | public function getServices($companyId, $serviceId = null, $staffId = null, $categoryId = null)
797 | {
798 | $parameters = [];
799 |
800 | if ($staffId !== null) {
801 | $parameters['staff_id'] = $staffId;
802 | }
803 |
804 | if ($categoryId !== null) {
805 | $parameters['category_id'] = $categoryId;
806 | }
807 |
808 | return $this->request('services/' . $companyId . '/' . $serviceId, $parameters);
809 | }
810 |
811 | /**
812 | * Создать услугу
813 | *
814 | * @param integer $companyId - ID компании
815 | * @param integer $serviceId - ID услуги
816 | * @param string $title - Название услуги
817 | * @param integer $categoryId - ID категории услуг
818 | * @param string $userToken - Токен для авторизации пользователя
819 | * @param array $fields - Остальные необязательные поля для услуги
820 | * @return array
821 | * @access public
822 | * @see http://docs.yclients.apiary.io/#reference/4/0/0
823 | * @throws YclientsException
824 | */
825 | public function postServices($companyId, $serviceId, $categoryId, $title, $userToken, array $fields = null)
826 | {
827 | $parameters = [
828 | 'category_id' => $categoryId,
829 | 'title' => $title,
830 | ];
831 |
832 | $parameters = array_merge($parameters, $fields);
833 |
834 | return $this->request('services/' . $companyId . '/' . $serviceId, $parameters, self::METHOD_POST, $userToken);
835 | }
836 |
837 | /**
838 | * Изменить услугу
839 | *
840 | * @param integer $companyId - ID компании
841 | * @param integer $serviceId - ID услуги
842 | * @param string $title - Название услуги
843 | * @param integer $categoryId - ID категории услуг
844 | * @param string $userToken - Токен для авторизации пользователя
845 | * @param array $fields - Остальные необязательные поля для услуги
846 | * @return array
847 | * @access public
848 | * @see http://docs.yclients.apiary.io/#reference/4/0/1
849 | * @throws YclientsException
850 | */
851 | public function putServices($companyId, $serviceId, $categoryId, $title, $userToken, array $fields = null)
852 | {
853 | $parameters = [
854 | 'category_id' => $categoryId,
855 | 'title' => $title,
856 | ];
857 |
858 | $parameters = array_merge($parameters, $fields);
859 |
860 | return $this->request('services/' . $companyId . '/' . $serviceId, $parameters, self::METHOD_PUT, $userToken);
861 | }
862 |
863 | /**
864 | * Удалить услугу
865 | *
866 | * @param integer $companyId - ID компании
867 | * @param integer $serviceId - ID услуги
868 | * @param string $userToken - Токен для авторизации пользователя
869 | * @return array
870 | * @access public
871 | * @see http://docs.yclients.apiary.io/#reference/4/0/2
872 | * @throws YclientsException
873 | */
874 | public function deleteServices($companyId, $serviceId, $userToken)
875 | {
876 | return $this->request('services/' . $companyId . '/' . $serviceId, [], self::METHOD_DELETE, $userToken);
877 | }
878 |
879 | /**
880 | * Получить список акций / конкретную акцию
881 | *
882 | * @param integer $companyId - ID компании
883 | * @param integer $eventId - ID услуги, если нужно работать с конкретной услугой.
884 | * @return array
885 | * @access public
886 | * @see http://docs.yclients.apiary.io/#reference/5//
887 | * @throws YclientsException
888 | */
889 | public function getEvents($companyId, $eventId = null)
890 | {
891 | return $this->request('events/' . $companyId . '/' . $eventId);
892 | }
893 |
894 | /**
895 | * Получить список сотрудников / конкретного сотрудника
896 | *
897 | * @param integer $companyId - ID компании
898 | * @param integer $staffId - ID сотрудника, если нужно работать с конкретным сотрудником
899 | * @return array
900 | * @access public
901 | * @see http://docs.yclients.apiary.io/#reference/6//
902 | * @throws YclientsException
903 | */
904 | public function getStaff($companyId, $staffId = null)
905 | {
906 | return $this->request('staff/' . $companyId . '/' . $staffId);
907 | }
908 |
909 | /**
910 | * Добавить нового сотрудника
911 | *
912 | * @param integer $companyId - ID компании
913 | * @param integer $staffId - ID сотрудника
914 | * @param string $name - Имя сотрудника
915 | * @param string $userToken - Токен для авторизации пользователя
916 | * @param array $fields - Остальные необязательные поля для сотрудника
917 | * @return array
918 | * @access public
919 | * @see http://docs.yclients.apiary.io/#reference/6/0/0
920 | * @throws YclientsException
921 | */
922 | public function postStaff($companyId, $staffId, $name, $userToken, array $fields = null)
923 | {
924 | $parameters = [
925 | 'name' => $name,
926 | ];
927 |
928 | $parameters = array_merge($parameters, $fields);
929 |
930 | return $this->request('staff/' . $companyId . '/' . $staffId, $parameters, self::METHOD_POST, $userToken);
931 | }
932 |
933 | /**
934 | * Изменить сотрудника
935 | *
936 | * @param integer $companyId - ID компании
937 | * @param integer $staffId - ID сотрудника
938 | * @param array $fields - Остальные необязательные поля для услуги
939 | * @param string $userToken - Токен для авторизации пользователя
940 | * @return array
941 | * @access public
942 | * @see http://docs.yclients.apiary.io/#reference/6/0/1
943 | * @throws YclientsException
944 | */
945 | public function putStaff($companyId, $staffId, array $fields, $userToken)
946 | {
947 | return $this->request('staff/' . $companyId . '/' . $staffId, $fields, self::METHOD_PUT, $userToken);
948 | }
949 |
950 | /**
951 | * Удалить сотрудника
952 | *
953 | * @param integer $companyId - ID компании
954 | * @param integer $staffId - ID сотрудника
955 | * @param string $userToken - Токен для авторизации пользователя
956 | * @return array
957 | * @access public
958 | * @see http://docs.yclients.apiary.io/#reference/6/0/2
959 | * @throws YclientsException
960 | */
961 | public function deleteStaff($companyId, $staffId, $userToken)
962 | {
963 | return $this->request('staff/' . $companyId . '/' . $staffId, [], self::METHOD_DELETE, $userToken);
964 | }
965 |
966 | /**
967 | * Получить список клиентов
968 | *
969 | * @param integer $companyId - ID компании
970 | * @param string $userToken - Токен для авторизации пользователя
971 | * @param string $fullname
972 | * @param string $phone
973 | * @param string $email
974 | * @param string $page
975 | * @param string $count
976 | * @return array
977 | * @access public
978 | * @see http://docs.yclients.apiary.io/#reference/7/0/0
979 | * @throws YclientsException
980 | */
981 | public function getClients(
982 | $companyId,
983 | $userToken,
984 | $fullname = null,
985 | $phone = null,
986 | $email = null,
987 | $page = null,
988 | $count = null
989 | ) {
990 | $parameters = [];
991 |
992 | if ($fullname !== null) {
993 | $parameters['fullname'] = $fullname;
994 | }
995 |
996 | if ($phone !== null) {
997 | $parameters['phone'] = $phone;
998 | }
999 |
1000 | if ($email !== null) {
1001 | $parameters['email'] = $email;
1002 | }
1003 |
1004 | if ($page !== null) {
1005 | $parameters['page'] = $page;
1006 | }
1007 |
1008 | if ($count !== null) {
1009 | $parameters['count'] = $count;
1010 | }
1011 |
1012 | return $this->request('clients/' . $companyId, $parameters, self::METHOD_GET, $userToken);
1013 | }
1014 |
1015 | /**
1016 | * Добавить клиента
1017 | *
1018 | * @param integer $companyId - ID компании
1019 | * @param string $name - Имя клиента
1020 | * @param integer $phone - Телефон клиента
1021 | * @param string $userToken - Токен для авторизации пользователя
1022 | * @param array $fields - Остальные необязательные поля для клиента
1023 | * @return array
1024 | * @access public
1025 | * @see http://docs.yclients.apiary.io/#reference/7/0/1
1026 | * @throws YclientsException
1027 | */
1028 | public function postClients($companyId, $name, $phone, $userToken, array $fields = [])
1029 | {
1030 | $parameters = [
1031 | 'name' => $name,
1032 | 'phone' => $phone,
1033 | ];
1034 |
1035 | $parameters = array_merge($parameters, $fields);
1036 |
1037 | return $this->request('clients/' . $companyId, $parameters, self::METHOD_POST, $userToken);
1038 | }
1039 |
1040 | /**
1041 | * Получить клиента
1042 | *
1043 | * @param integer $companyId - ID компании
1044 | * @param integer $id - ID клиента
1045 | * @param string $userToken - Токен для авторизации пользователя
1046 | * @return array
1047 | * @access public
1048 | * @see http://docs.yclients.apiary.io/#reference/7/1/0
1049 | * @throws YclientsException
1050 | */
1051 | public function getClient($companyId, $id, $userToken)
1052 | {
1053 | return $this->request('client/' . $companyId . '/' . $id, [], self::METHOD_GET, $userToken);
1054 | }
1055 |
1056 | /**
1057 | * Редактировать клиента
1058 | *
1059 | * @param integer $companyId - ID компании
1060 | * @param integer $id - ID клиента
1061 | * @param string $userToken - Токен для авторизации пользователя
1062 | * @param array $fields
1063 | * @return array
1064 | * @access public
1065 | * @see http://docs.yclients.apiary.io/#reference/7/1/1
1066 | * @throws YclientsException
1067 | */
1068 | public function putClient($companyId, $id, $userToken, array $fields)
1069 | {
1070 | return $this->request('client/' . $companyId . '/' . $id, $fields, self::METHOD_PUT, $userToken);
1071 | }
1072 |
1073 | /**
1074 | * Удалить клиента
1075 | *
1076 | * @param integer $companyId - ID компании
1077 | * @param integer $id - ID клиента
1078 | * @param string $userToken - Токен для авторизации пользователя
1079 | * @return array
1080 | * @access public
1081 | * @see http://docs.yclients.apiary.io/#reference/7/1/2
1082 | * @throws YclientsException
1083 | */
1084 | public function deleteClient($companyId, $id, $userToken)
1085 | {
1086 | return $this->request('client/' . $companyId . '/' . $id, [], self::METHOD_DELETE, $userToken);
1087 | }
1088 |
1089 | /**
1090 | * Получить список записей
1091 | *
1092 | * @param integer $companyId - ID компании
1093 | * @param string $userToken - Токен для авторизации пользователя
1094 | * @param integer $page
1095 | * @param integer $count
1096 | * @param integer $staffId
1097 | * @param integer $clientId
1098 | * @param \DateTime $startDate
1099 | * @param \DateTime $endDate
1100 | * @param \DateTime $cStartDate
1101 | * @param \DateTime $cEndDate
1102 | * @param \DateTime $changedAfter
1103 | * @param \DateTime $changedBefore
1104 | * @return array
1105 | * @access public
1106 | * @see http://docs.yclients.apiary.io/#reference/8/0/0
1107 | * @throws YclientsException
1108 | */
1109 | public function getRecords(
1110 | $companyId,
1111 | $userToken,
1112 | $page = null,
1113 | $count = null,
1114 | $staffId = null,
1115 | $clientId = null,
1116 | \DateTime $startDate = null,
1117 | \DateTime $endDate = null,
1118 | \DateTime $cStartDate = null,
1119 | \DateTime $cEndDate = null,
1120 | \DateTime $changedAfter = null,
1121 | \DateTime $changedBefore = null
1122 | ) {
1123 | $parameters = [];
1124 |
1125 | if ($page !== null) {
1126 | $parameters['page'] = $page;
1127 | }
1128 |
1129 | if ($count !== null) {
1130 | $parameters['count'] = $count;
1131 | }
1132 |
1133 | if ($staffId !== null) {
1134 | $parameters['staff_id'] = $staffId;
1135 | }
1136 |
1137 | if ($clientId !== null) {
1138 | $parameters['client_id'] = $clientId;
1139 | }
1140 |
1141 | if ($startDate !== null) {
1142 | $parameters['start_date'] = $startDate->format('Y-m-d');
1143 | }
1144 |
1145 | if ($endDate !== null) {
1146 | $parameters['end_date'] = $endDate->format('Y-m-d');
1147 | }
1148 |
1149 | if ($cStartDate !== null) {
1150 | $parameters['c_start_date'] = $cStartDate->format('Y-m-d');
1151 | }
1152 |
1153 | if ($cEndDate !== null) {
1154 | $parameters['c_end_date'] = $cEndDate->format('Y-m-d');
1155 | }
1156 |
1157 | if ($changedAfter !== null) {
1158 | $parameters['changed_after'] = $changedAfter->format(\DateTime::ISO8601);
1159 | }
1160 |
1161 | if ($changedBefore !== null) {
1162 | $parameters['changed_before'] = $changedBefore->format(\DateTime::ISO8601);
1163 | }
1164 |
1165 | return $this->request('records/' . $companyId, $parameters, self::METHOD_GET, $userToken);
1166 | }
1167 |
1168 | /**
1169 | * Создать новую запись
1170 | *
1171 | * @param integer $companyId - ID компании
1172 | * @param string $userToken - Токен для авторизации пользователя
1173 | * @param integer $staffId
1174 | * @param array $services
1175 | * @param array $client
1176 | * @param \DateTime $datetime
1177 | * @param integer $seanceLength
1178 | * @param bool $saveIfBusy
1179 | * @param bool $sendSms
1180 | * @param string $comment
1181 | * @param integer $smsRemainHours
1182 | * @param integer $emailRemainHours
1183 | * @param integer $apiId
1184 | * @param integer $attendance
1185 | * @return array
1186 | * @access public
1187 | * @see http://docs.yclients.apiary.io/#reference/8/0/1
1188 | * @throws YclientsException
1189 | */
1190 | public function postRecords(
1191 | $companyId,
1192 | $userToken,
1193 | $staffId,
1194 | $services,
1195 | $client,
1196 | \DateTime $datetime,
1197 | $seanceLength,
1198 | $saveIfBusy,
1199 | $sendSms,
1200 | $comment = null,
1201 | $smsRemainHours = null,
1202 | $emailRemainHours = null,
1203 | $apiId = null,
1204 | $attendance = null
1205 | ) {
1206 | $parameters = [];
1207 |
1208 | if ($staffId !== null) {
1209 | $parameters['staff_id'] = $staffId;
1210 | }
1211 |
1212 | if ($services !== null) {
1213 | $parameters['services'] = $services;
1214 | }
1215 |
1216 | if ($client !== null) {
1217 | $parameters['client'] = $client;
1218 | }
1219 |
1220 | if ($datetime !== null) {
1221 | $parameters['datetime'] = $datetime->format(\DateTime::ISO8601);
1222 | }
1223 |
1224 | if ($seanceLength !== null) {
1225 | $parameters['seance_length'] = $seanceLength;
1226 | }
1227 |
1228 | if ($saveIfBusy !== null) {
1229 | $parameters['save_if_busy'] = $saveIfBusy;
1230 | }
1231 |
1232 | if ($sendSms !== null) {
1233 | $parameters['send_sms'] = $sendSms;
1234 | }
1235 |
1236 | if ($comment !== null) {
1237 | $parameters['comment'] = $comment;
1238 | }
1239 |
1240 | if ($smsRemainHours !== null) {
1241 | $parameters['sms_remain_hours'] = $smsRemainHours;
1242 | }
1243 |
1244 | if ($emailRemainHours !== null) {
1245 | $parameters['email_remain_hours'] = $emailRemainHours;
1246 | }
1247 |
1248 | if ($apiId !== null) {
1249 | $parameters['api_id'] = $apiId;
1250 | }
1251 |
1252 | if ($attendance !== null) {
1253 | $parameters['attendance'] = $attendance;
1254 | }
1255 |
1256 | return $this->request('records/' . $companyId, $parameters, self::METHOD_POST, $userToken);
1257 | }
1258 |
1259 | /**
1260 | * Получить запись
1261 | *
1262 | * @param integer $companyId - ID компании
1263 | * @param integer $recordId
1264 | * @param string $userToken - Токен для авторизации пользователя
1265 | * @return array
1266 | * @access public
1267 | * @see http://docs.yclients.apiary.io/#reference/8/1/0
1268 | * @throws YclientsException
1269 | */
1270 | public function getRecord($companyId, $recordId, $userToken)
1271 | {
1272 | return $this->request('record/' . $companyId . '/' . $recordId, [], self::METHOD_GET, $userToken);
1273 | }
1274 |
1275 | /**
1276 | * Изменить запись
1277 | *
1278 | * @param integer $companyId - ID компании
1279 | * @param integer $recordId
1280 | * @param string $userToken - Токен для авторизации пользователя
1281 | * @param array $fields
1282 | * @return array
1283 | * @access public
1284 | * @see http://docs.yclients.apiary.io/#reference/8/1/1
1285 | * @throws YclientsException
1286 | */
1287 | public function putRecord($companyId, $recordId, $userToken, array $fields)
1288 | {
1289 | return $this->request('record/' . $companyId . '/' . $recordId, $fields, self::METHOD_PUT, $userToken);
1290 | }
1291 |
1292 | /**
1293 | * Удалить запись
1294 | *
1295 | * @param integer $companyId - ID компании
1296 | * @param integer $recordId
1297 | * @param string $userToken - Токен для авторизации пользователя
1298 | * @return array
1299 | * @access public
1300 | * @see http://docs.yclients.apiary.io/#reference/8/1/2
1301 | * @throws YclientsException
1302 | */
1303 | public function deleteRecord($companyId, $recordId, $userToken)
1304 | {
1305 | return $this->request('record/' . $companyId . '/' . $recordId, [], self::METHOD_DELETE, $userToken);
1306 | }
1307 |
1308 | /**
1309 | * Изменить расписание работы сотрудника
1310 | *
1311 | * @param integer $companyId - ID компании
1312 | * @param integer $staffId
1313 | * @param string $userToken - Токен для авторизации пользователя
1314 | * @param array $fields
1315 | * @return array
1316 | * @access public
1317 | * @see http://docs.yclients.apiary.io/#reference/9/0
1318 | * @throws YclientsException
1319 | */
1320 | public function putSchedule($companyId, $staffId, $userToken, $fields)
1321 | {
1322 | return $this->request('schedule/' . $companyId . '/' . $staffId, $fields, self::METHOD_PUT, $userToken);
1323 | }
1324 |
1325 | /**
1326 | * Получить расписание работы сотрудника
1327 | *
1328 | * @param integer $companyId - ID компании
1329 | * @param integer $staffId
1330 | * @param string $startDate
1331 | * @param string $endDate
1332 | * @param string $userToken - Токен для авторизации пользователя
1333 | * @return array
1334 | * @access public
1335 | * @see https://yclients.docs.apiary.io/#reference/12/1
1336 | * @throws YclientsException
1337 | */
1338 | public function getSchedule($companyId, $staffId, $startDate, $endDate, $userToken)
1339 | {
1340 | return $this->request('schedule/' . $companyId . '/' . $staffId . '/' . $startDate . '/'. $endDate, [], self::METHOD_GET, $userToken);
1341 | }
1342 |
1343 | /**
1344 | * Получить список дат для журнала
1345 | *
1346 | * @param integer $companyId - ID компании
1347 | * @param \DateTime $date
1348 | * @param integer $staffId
1349 | * @param string $userToken - Токен для авторизации пользователя
1350 | * @return array
1351 | * @access public
1352 | * @see http://docs.yclients.apiary.io/#reference/10/0/0
1353 | * @throws YclientsException
1354 | */
1355 | public function getTimetableDates($companyId, \DateTime $date, $staffId, $userToken)
1356 | {
1357 | $parameters = [];
1358 |
1359 | if ($staffId !== null) {
1360 | $parameters['staff_id'] = $staffId;
1361 | }
1362 |
1363 | return $this->request('timetable/dates/' . $companyId . '/' . $date->format('Y-m-d'), $parameters, self::METHOD_GET, $userToken);
1364 | }
1365 |
1366 | /**
1367 | * Получить список сеансов для журнала
1368 | *
1369 | * @param integer $companyId - ID компании
1370 | * @param \DateTime $date
1371 | * @param integer $staffId
1372 | * @param string $userToken - Токен для авторизации пользователя
1373 | * @return array
1374 | * @access public
1375 | * @see http://docs.yclients.apiary.io/#reference/11/0/0
1376 | * @throws YclientsException
1377 | */
1378 | public function getTimetableSeances($companyId, \DateTime $date, $staffId, $userToken)
1379 | {
1380 | return $this->request('timetable/seances/' . $companyId . '/' . $staffId . '/' . $date->format('Y-m-d'), [], self::METHOD_GET, $userToken);
1381 | }
1382 |
1383 | /**
1384 | * Получить комментарии
1385 | *
1386 | * @param integer $companyId - ID компании
1387 | * @param string $userToken - Токен для авторизации пользователя
1388 | * @param \DateTime $startDate
1389 | * @param \DateTime $endDate
1390 | * @param integer $staffId
1391 | * @param integer $rating
1392 | * @return array
1393 | * @access public
1394 | * @see http://docs.yclients.apiary.io/#reference/12/0/0
1395 | * @throws YclientsException
1396 | */
1397 | public function getComments(
1398 | $companyId,
1399 | $userToken,
1400 | \DateTime $startDate = null,
1401 | \DateTime $endDate = null,
1402 | $staffId = null,
1403 | $rating = null
1404 | ) {
1405 | $parameters = [];
1406 |
1407 | if ($startDate !== null) {
1408 | $parameters['start_date'] = $startDate->format('Y-m-d');
1409 | }
1410 |
1411 | if ($endDate !== null) {
1412 | $parameters['end_date'] = $endDate->format('Y-m-d');
1413 | }
1414 |
1415 | if ($staffId !== null) {
1416 | $parameters['staff_id'] = $staffId;
1417 | }
1418 |
1419 | if ($rating !== null) {
1420 | $parameters['rating'] = $rating;
1421 | }
1422 |
1423 | return $this->request('comments/' . $companyId, $parameters, self::METHOD_GET, $userToken);
1424 | }
1425 |
1426 | /**
1427 | * Получить пользователей компании
1428 | *
1429 | * @param integer $companyId - ID компании
1430 | * @param string $userToken - Токен для авторизации пользователя
1431 | * @return array
1432 | * @access public
1433 | * @see http://docs.yclients.apiary.io/#reference/13/0/0
1434 | * @throws YclientsException
1435 | */
1436 | public function getCompanyUsers($companyId, $userToken)
1437 | {
1438 | return $this->request('company_users/' . $companyId, [], self::METHOD_GET, $userToken);
1439 | }
1440 |
1441 | /**
1442 | * Получить кассы компании
1443 | *
1444 | * @param integer $companyId - ID компании
1445 | * @param string $userToken - Токен для авторизации пользователя
1446 | * @return array
1447 | * @access public
1448 | * @see http://docs.yclients.apiary.io/#reference/14/0/0
1449 | * @throws YclientsException
1450 | */
1451 | public function getAccounts($companyId, $userToken)
1452 | {
1453 | return $this->request('accounts/' . $companyId, [], self::METHOD_GET, $userToken);
1454 | }
1455 |
1456 | /**
1457 | * Отправить SMS
1458 | *
1459 | * @param integer $companyId - ID компании
1460 | * @param string $userToken - Токен для авторизации пользователя
1461 | * @param integer[] $clientIds - ID клиентов
1462 | * @param string $text - Тест сообщения
1463 | * @return array
1464 | * @access public
1465 | * @see http://docs.yclients.apiary.io/#reference/14/0/0
1466 | * @throws YclientsException
1467 | */
1468 | public function sendSMS($companyId, $userToken, $clientIds, $text)
1469 | {
1470 | $parameters = [];
1471 | $parameters['client_ids'] = $clientIds;
1472 | $parameters['text'] = $text;
1473 |
1474 | return $this->request('sms/clients/by_id/' . $companyId, $parameters, self::METHOD_POST, $userToken);
1475 | }
1476 |
1477 | /**
1478 | * Получить склады компании
1479 | *
1480 | * @param integer $companyId - ID компании
1481 | * @param string $userToken - Токен для авторизации пользователя
1482 | * @return array
1483 | * @access public
1484 | * @see http://docs.yclients.apiary.io/#reference/15/0/0
1485 | * @throws YclientsException
1486 | */
1487 | public function getStorages($companyId, $userToken)
1488 | {
1489 | return $this->request('storages/' . $companyId, [], self::METHOD_GET, $userToken);
1490 | }
1491 |
1492 | /**
1493 | * Получить настройки уведомлений о событиях
1494 | *
1495 | * @param integer $companyId - ID компании
1496 | * @param string $userToken - Токен для авторизации пользователя
1497 | * @return array
1498 | * @access public
1499 | * @see http://docs.yclients.apiary.io/#reference/18/0/0
1500 | * @throws YclientsException
1501 | */
1502 | public function getHooks($companyId, $userToken)
1503 | {
1504 | return $this->request('hooks_settings/' . $companyId, [], self::METHOD_GET, $userToken);
1505 | }
1506 |
1507 | /**
1508 | * Изменить настройки уведомлений о событиях
1509 | *
1510 | * @param integer $companyId - ID компании
1511 | * @param array $fields
1512 | * @param string $userToken - Токен для авторизации пользователя
1513 | * @return array
1514 | * @access public
1515 | * @see http://docs.yclients.apiary.io/#reference/18/0/1
1516 | * @throws YclientsException
1517 | */
1518 | public function postHooks($companyId, $fields, $userToken)
1519 | {
1520 | if (!isset($fields['urls'])) {
1521 | throw new YclientsException('Не передан обязательный параметр urls');
1522 | }
1523 | if (!isset($fields['active'])) {
1524 | throw new YclientsException('Не передан обязательный параметр active');
1525 | }
1526 | return $this->request('hooks_settings/' . $companyId, $fields, self::METHOD_POST, $userToken);
1527 | }
1528 | }
1529 |
--------------------------------------------------------------------------------
/src/Yclients/YclientsException.php:
--------------------------------------------------------------------------------
1 | tokenPartner) {
113 | throw new YclientsException('Не указан токен партнёра');
114 | }
115 |
116 | $headers[] = 'Authorization: Bearer ' . $this->tokenPartner . (is_string($auth) ? ', User ' . $auth : '');
117 | }
118 |
119 | return $this->requestCurl($url, $parameters, $method, $headers);
120 | }
121 |
122 | /**
123 | * Выполнение непосредственно запроса с помощью curl
124 | *
125 | * @param string $url
126 | * @param array $parameters
127 | * @param string $method
128 | * @param array $headers
129 | * @return array
130 | * @access protected
131 | * @throws YclientsException
132 | */
133 | protected function requestCurl($url, $parameters = [], $method = 'GET', $headers = [])
134 | {
135 | // Увеличиваем счетчик числа отправленных запросов
136 | $this->requestCounter++;
137 |
138 | $ch = curl_init();
139 |
140 | $jsonParameters = '{}';
141 | if (count($parameters)) {
142 | if ($method === self::METHOD_GET) {
143 | $url .= '?' . http_build_query($parameters);
144 | } else {
145 | $jsonParameters = json_encode($parameters);
146 | if ($jsonParameters === false) {
147 | $code = json_last_error();
148 | throw new YclientsException("Ошибка кодирования JSON ({$code}): " . print_r($parameters, true));
149 | }
150 | curl_setopt($ch, CURLOPT_POSTFIELDS, $jsonParameters);
151 | }
152 | }
153 |
154 | if ($method === self::METHOD_GET) {
155 | $this->debug("[{$this->requestCounter}] ===> GET {$url}");
156 | } elseif ($method === self::METHOD_POST) {
157 | curl_setopt($ch, CURLOPT_POST, true);
158 | $this->debug("[{$this->requestCounter}] ===> POST {$url}" . PHP_EOL . $jsonParameters);
159 | } elseif ($method === self::METHOD_PUT) {
160 | curl_setopt($ch, CURLOPT_CUSTOMREQUEST, self::METHOD_PUT);
161 | $this->debug("[{$this->requestCounter}] ===> PUT {$url}" . PHP_EOL . $jsonParameters);
162 | } elseif ($method === self::METHOD_DELETE) {
163 | $this->debug("[{$this->requestCounter}] ===> DELETE: {$url}" . PHP_EOL . $jsonParameters);
164 | curl_setopt($ch, CURLOPT_CUSTOMREQUEST, self::METHOD_DELETE);
165 | }
166 |
167 | curl_setopt($ch, CURLOPT_URL, self::URL . '/' . $url);
168 | curl_setopt($ch, CURLOPT_FAILONERROR, false);
169 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
170 | curl_setopt($ch, CURLOPT_TIMEOUT, $this->curlTimeout);
171 | curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $this->curlConnectTimeout);
172 | curl_setopt($ch, CURLOPT_HEADER, false);
173 |
174 | // Включение проверки SSL-сертификата сервера YClients
175 | if ($this->verifySSLCerfificate) {
176 | curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
177 | curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
178 | if ($this->sslCertificateFile) {
179 | $sslCertificateFile = dirname(__FILE__) . DIRECTORY_SEPARATOR . $this->sslCertificateFile;
180 | curl_setopt($ch, CURLOPT_CAINFO, $sslCertificateFile);
181 | }
182 | } else {
183 | curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
184 | curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
185 | }
186 |
187 | if (count($headers)) {
188 | curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
189 | }
190 |
191 | $result = $this->throttleCurl($ch);
192 | $deltaTime = sprintf('%0.4f', microtime(true) - $this->lastRequestTime);
193 | $code = (int) curl_getinfo($ch, CURLINFO_HTTP_CODE);
194 | $errno = curl_errno($ch);
195 | $error = curl_error($ch);
196 | curl_close($ch);
197 |
198 | // Проверка ошибок cURL
199 | if ($errno) {
200 | throw new YclientsException("Oшибка cURL ({$errno}): {$error}");
201 | }
202 |
203 | // Если в ответе были переданы только заголовки без тела сообщения (204 No Content)
204 | if ($code === 204) {
205 | $this->debug(
206 | "[{$this->requestCounter}] <=== RESPONSE {$deltaTime}s ({$code})" . PHP_EOL . print_r($result, true)
207 | );
208 | return null;
209 | }
210 |
211 | // Декодирование JSON ответа сервера
212 | $response = json_decode($result, true);
213 | $this->debug(
214 | "[{$this->requestCounter}] <=== RESPONSE {$deltaTime}s ({$code})" . PHP_EOL . print_r($response, true)
215 | );
216 | if (is_null($response)) {
217 | $code = json_last_error();
218 | throw new YclientsException("Ошибка декодирования JSON ({$code}): {$result}");
219 | }
220 |
221 | // Если сообщение об ошибке в ответе сервера
222 | if (isset($response['errors'])) {
223 | throw new YclientsException(
224 | 'Ошибка: ' . print_r($response['errors'], true) . '. Request: ' . $jsonParameters
225 | );
226 | }
227 |
228 | // Если сообщение об ошибке success:false в ответе сервера
229 | if (isset($response['success']) && ! $response['success']) {
230 | throw new YclientsException('Ошибка: ' . print_r($response, true) . '. Request: ' . $jsonParameters);
231 | }
232 |
233 | return $response;
234 | }
235 |
236 | /**
237 | * Загружает все сущности заданного типа
238 | * @param object $callback Анонимная функция для загрузки сущностей: $callback($page, $count)
239 | * $page - номер страницы, $count - число сущностей на странице
240 | * @return \Generator
241 | */
242 | public function getAll($callback) :\Generator
243 | {
244 | $page = 1;
245 |
246 | while (true) {
247 | $response = $callback($page, $this->limitCount);
248 | $data = $response['data'];
249 |
250 | yield $response;
251 |
252 | if (count($data) < $this->limitCount) {
253 | break;
254 | }
255 |
256 | $page++;
257 | }
258 | }
259 |
260 | /**
261 | * Обеспечивает троттлинг запросов к YClients API
262 | * @param resource $curl
263 | * @return string|null
264 | */
265 | protected function throttleCurl($curl)
266 | {
267 | if ($this->throttle > 0) {
268 | do {
269 | $usleep = (int) (1E6 * ($this->lastRequestTime + 1/$this->throttle - microtime(true)));
270 | if ($usleep <= 0) {
271 | break;
272 | }
273 |
274 | $throttleTime = sprintf('%0.4f', $usleep/1E6);
275 | $this->debug("[{$this->requestCounter}] ++++ THROTTLE ({$this->throttle}) {$throttleTime}s");
276 |
277 | usleep($usleep);
278 | } while (false);
279 | }
280 |
281 | $this->lastRequestTime = microtime(true);
282 |
283 | $result = curl_exec($curl);
284 |
285 | return $result;
286 | }
287 |
288 | /**
289 | * Выводит отладочные сообщения
290 | * @param string $message
291 | * @return void
292 | */
293 | // ------------------------------------------------------------------------
294 | protected function debug(string $message = '')
295 | {
296 | if (! $this->debug) {
297 | return;
298 | }
299 |
300 | // Формируем строку времени логгирования
301 | $dateTime = \DateTime::createFromFormat('U.u', sprintf('%.f', microtime(true)));
302 | $timeZone = new \DateTimeZone(date_default_timezone_get());
303 | $dateTime->setTimeZone($timeZone);
304 | $timeString = $dateTime->format('Y-m-d H:i:s,u P');
305 |
306 | $uniqId = $this->getUniqId();
307 | $message = "*** {$uniqId} [{$timeString}]" . PHP_EOL . $message . PHP_EOL . PHP_EOL;
308 |
309 | // Если лог файл не указан, то вывод в STDOUT
310 | if (empty($this->debugLogFile)) {
311 | echo $message . PHP_EOL;
312 | return;
313 | }
314 |
315 | // Формируем полное имя лог файла
316 | $debugLogFile = dirname(__FILE__) . DIRECTORY_SEPARATOR . $this->debugLogFile;
317 | $this->checkDir(dirname($debugLogFile));
318 |
319 | // Записываем сообщение в лог файл
320 | if (! file_put_contents($debugLogFile, $message, FILE_APPEND|LOCK_EX)) {
321 | throw new YclientsException("Не удалось записать в лог файл {$debugLogFile}");
322 | }
323 | }
324 |
325 | /**
326 | * Возвращает уникальное значение ID для метки в отладочных сообщениях
327 | * @param int $length Длина ID
328 | * @return string
329 | */
330 | protected function getUniqId(int $length = 7) :string
331 | {
332 | if (! isset($this->uniqId)) {
333 | $this->uniqId = substr(str_shuffle("0123456789abcdefghijklmnopqrstuvwxyz"), 0, $length);
334 | }
335 | return $this->uniqId;
336 | }
337 |
338 | /**
339 | * Проверяет наличие каталога для сохранения файла и создает каталог при его отсутствии рекурсивно
340 | * @param string $directory Полный путь к каталогу
341 | * @return void
342 | */
343 | protected function checkDir(string $directory)
344 | {
345 | // Выходим, если каталог уже есть (is_dir кешируется PHP)
346 | if (is_dir($directory)) {
347 | return;
348 | }
349 |
350 | // Создаем новый каталог рекурсивно
351 | if (!mkdir($directory, $mode = 0755, $recursive = true) && !is_dir($directory)) {
352 | throw new YclientsException("Не удалось рекурсивно создать каталог {$directory}");
353 | }
354 | }
355 | }
356 |
--------------------------------------------------------------------------------