Очередной вечер переставал быть томным. Больно не радовала меня плашка с предупреждением о превышении лимита пользователей в GetCourse.
После выборки группы пользователей которых можно и нужно удалить оптимизма у меня еще больше поубавилось, 1366 учеток удалять вручную желания не было от слова «совсем». Да и так или иначе GetCourse ограничил возможность массового удаления пользователей, и для того что бы удалить несколько пользователей необходимо сформировать сегмент, а затем отправить ссылку на этот сегмент в тех. поддержку.
Процедура понятная, но не спортивная. Во первых иногда о необходимости удалить вспоминаешь в последний момент. Иногда просто не хочется дожидаться ответа от технической поддержки. А получить бонус в виде доплаты за превышение лимитов даже на месяц совершенно не хочется. Значит эту проблему будем решать своими силами.
BackUp — превыше всего
Первым делом, прежде чем что-то удалять, было бы не плохо создать резервную копию удаляемого контента. К счастью сделать backup пользователей совершенно легко. Выделяем сегмент и просто экспортируем его в CSV формате или в нативном формате Excel. База пригодится в любом случае, её можно будет снова вернуть на GetCourse либо использовать e-mail пользователей для рассылок с других сервисов или подгрузить всё в AmoCRM и отдать базу в работу ОП. В общем применений достаточно, как и причин базу всё таки сохранить.
Основная идея
Первая мысль которая мне пришла в голову — это экспортировать базу, а потом используя API GetCourse медленно но уверено пользователей удалить автоматически. В целом идея имеет право на жизнь, но под капотом кроются некоторые не очевидные подводные камни.
Во первых, банально с помощью Excel запрос к API не сформируешь, а значит нужно думать о том, как организовать базу данных, сложить в неё данные с CSV файла, а потом уже писать скрипт, который будет выбирать с этой базы пользователей и удалять через API.
А во вторых API GetCourse не предусматривает возможность удаления пользователей. На этом статью можно было бы закончить, написать в поддержку и не парить голову. Но мы пойдем другим путём =)
GetCourse Privat API
Главная проблема заключается в том, что в API GetCourse банально нет метода позволяющего удалять пользователя. Но так ли это на самом деле? Практика показывает, что как правило у сервиса помимо публичного и задокументированного API есть так называемый приватный (не публичный) API. Появление такового возможно из-за принципов по которым сервис строится и практически все современные сервисы обмениваются данными с Web-интерфейсом с помощью такого API. Но веселье заключается в том, что бы во первых найти такой API, а бонусом необходимо понять без документации, как же вся эта штука работает. Единственный путь это сделать — исследовать трафик: обмен данными между браузером и сервером GetCourse. И для этого существует восхитительная программа Fiddler. Этим мы и воспользуемся.
Анализируем трафик
Со скачиванием, установкой программы проблем быть совершенно не должно. А после установки необходимо произвести базовые настройки для того, что бы Fiddler имел возможность расшифровать https трафик. Делается это довольно просто:
Открываем программку, нажимаем клавишу F12 что бы отключить перехват трафика, заходим в Tools, далее выбираем Options. В открывшемся окне переходим на вкладку HTTPS.
Дальше — проще, выставляем галочки напротив Capture HTTPS CONNECTs, Decrypt HTTPS traffic, затем нажимаем напротив метки Protocols и вводим следующую строку <client>;ssl2;ssl3;tls1.0;tls1.1;tls1.2
Добываем API в бою
После проведения предварительных настроек настало наконец-то время для того, что бы добыть заветный Endpoint с помощью которого можно удалять пользователей. Для этого заходим в GetCourse, в карточку клиента, открываем первого попавшегося пользователя которого не жалко (крайне рекомендую добавить тестовый аккаунт). После возвращаемся в Fiddler, снова нажимаем F12, что бы включить захват трафика. Возвращаемся в GetCourse и удаляем пользователя с карточки клиента. Вот и всё. Идем в Fiddler И пытаемся разобраться во всем том безобразии, которое программа перехватила.
Собственно на этом мы и закончим перехват трафика. Теперь нужно разобраться, что с этим всем делать, и как получить то, что нужно. В левой части программы видны все запросы, в правой стороне — из чего эти запросы состоят. Первое, что бросается в глаза, это то, что наверняка где-то будет что-то, что связано либо с пользователем либо с удалением. И собственно таких запроса целых два. Их я обвел красным блоком в левой части сриншота.
POST /user/control/user/delete/id/256126628 HTTP/1.1
Собственно вот та самая заветная строчка 🙂 Очевидно она имеет отношение как к пользователям так и к удалению, т.к включает в пути user и delete, а цифры в конце строки (на них же указывает оранжевая стрелка) это id пользователя на GetCourse. Далее нам нужно понять, какие еще параметры передать в запрос. Для этого обратимся к правой части скрина в поле Requset Headers.
Здесь зеленая стрелка указывает на то, что запрос отправлен методом POST. Это важно, не буду заострять на этом внимание, здесь главное понимание того, что запросы в основном бывают двух видов. GET И POST. Формально ничем они не отличаются, кроме того, что запрос методом POST выполняется скрыто и его аргументы не отображаются в адресной строке данных. И все служебные или персональные данные как правило отправляются именно методом POST. Это если вкратце, для нашей задачи понимания этих различий достаточно.
Следующим шагом нужно как-то авторизовать запрос, ведь нас без логина и пароля на GetCourse не пустят, в штатном API для авторизации используется ключ доступа, он же токен он же Access Token и он же ключ API. Для приватного API ключи доступа используются крайне редко, а значит наверняка нужно поискать что-то еще. В правой части скриншота с Fiddler есть такой блок, который называется Cookies. Именно в «куках» как правило и хранят информацию о пользователе либо что-то, что позволяет идентифицировать пользователя и понять, зашел он в систему или нет.
Если присмотреться к разделу Cookies более внимательно, можно обнаружить, что среди прочих есть ключ PHPSESSID5. Этот ключ используется в php для работы с сессиями. Последняя, если очень упростить, по сути и является авторизацией для текущего пользователя. После знака равенства находится сам заветный ключик который нам нужен. Так же нам нужно будет генерировать заголовок Referrer, он тоже влияет на работу авторизации. Теперь можно сформировать ТЗ.
Значит нам необходимо написать скрипт, который принимал бы ID пользователя в аргументах. Затем выполнял запрос методом POST на точку /user/control/user/delete/id/ указывая ID и в заголовках отправлял значение PHPSESSID5 и Refferer которое мы перехватили
Пишем скрипт
Здесь можно было бы конечно начать писать код, но я человек по своему ленивый, да и проверить нашу гипотезу на работоспособность предварительно не помешало бы. А для того, что бы сделать проверку мы воспользуемся инструментом Postman.
Возле строчки отдаленно напоминающей адресную строку вводим URL в формате:
https://домен_школы/user/control/user/delete/id/id_пользователя и не забыть поставить POST перед этой строчкой.
В секции Headers ниже, добавляем два поля в столбце Key, это Cookie и Referer и заполняем значениями. В поле Cookie вводим PHPSESSID5, а в поле Referer точно такую же ссылку как и в адресной строчке. Далее настроим тело запроса. Для этого переходим на вкладку Body
В этой секции необходимо добавить ключ do_delete и выбрать тип содержимого x-www-form-urlencode. После этого можно приступить к тестированию 🙂 Нажимаем кнопочку Send в Postman и обновляем страницу с анкетой пользователя. Если анкета стала недоступной — у нас всё получилось
После успешного тестирования пора бы приступить к написанию кода, а большую часть кода за нас напишет сам Postman.
В выпадающем блоке необходимо выбрать PHP-cURL.
Допиливаем скрипт
Большую половину пути пройдено, осталось только дописать скрипт на php и проверить его. Для проверки php скриптов воспользуемся готовым решение — XAMPP. После установки XAMPP нужно создать файл deleteUser.php и разместить его в папке по пути C:\xampp\htdocs\. Теперь можно запустить и сам XAMPP.
Непосредственно сам код можно редактировать в чем угодно, хоть в блокноте. Но я для этих целей использую Visual Studio Code. В коде который сгенерировал нам Postman нужно добавить возможность получать id пользователя извне, так же сделаем таким образом, что бы извне можно было получать и PHPSESSID5, так как этот параметр может меняется или становится неактуальным, по этому логично было бы иметь возможность его изменять не корректируя работу php-скрипта и обновлять его на сервере. И что бы сделать скрипт совсем уже универсальным, сделаем возможным получение адреса школы так же извне.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
if(isset($_GET['uid'])) { $userId = $_GET['uid']; } else { echo 'id не указан'; return; } if(isset($_GET['key'])) { $cookie = $_GET['key']; } else { echo 'Ключ не указан'; return; } if(isset($_GET['domain'])) { $gcDomain = $_GET['domain']; } else { echo 'Адрес не указан'; return; } |
Таким образом для правильного вызова скрипта необходимый URL будет в виде
https://domain.tld/deleteUser.php?id=123&key=jsd5sdec6fcdf&domain=school.domain.tld
И еще одно изменение которое мы внесем в скрипт — это проверка, получилось ли скрипту сделать запрос. Для того, что бы понять, как сделать эту проверку, снова обратимся к тому безобразию которое сгенерировал нам Fiddler.
Во втором столбце указан код 302. HTTP код перенаправления 302 Found означает, что запрошенный ресурс был временно перемещён по адресу, указанному в заголовке Location. Значит нам необходимо отключить автоматическое перенаправление, а по возвращаемому коду ответа будем разбирать, успешно ли сработал скрипт. В случае возврата 302-го кода — успех, если код будет отличатся, значит что-то пошло не так и скрипт не смог удалить пользователя.
1 2 3 4 5 6 7 8 |
$response = curl_exec($curl); $info = curl_getinfo($curl); curl_close($curl); if ($info["http_code"] == 302) { echo 'Пользователь удален'; } else echo 'Ошибка'; |
В финале у нас должен получится скрипт, листинг кода которого я привожу ниже.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
<?php if(isset($_GET['uid'])) { $userId = $_GET['uid']; } else { echo 'id не указан'; return; } if(isset($_GET['key'])) { $cookie = $_GET['key']; } else { echo 'Ключ не указан'; return; } if(isset($_GET['domain'])) { $gcDomain = $_GET['domain']; } else { echo 'Адрес не указан'; return; } $gcDomain = 'https://' . $gcDomain; //Ссылка на школу $dUserEndpoint = '/user/control/user/delete/id/'; //Полученный нами Endpoint API $curl = curl_init(); curl_setopt_array($curl, array( CURLOPT_URL => $gcDomain . $dUserEndpoint . $userId, CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => '', CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 0, CURLOPT_FOLLOWLOCATION => false, //Запрещаем автоматический редирект CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => 'POST', CURLOPT_POSTFIELDS => 'do_delete=', CURLOPT_HTTPHEADER => array( 'Cookie: PHPSESSID5=' . $cookie, 'Referer: ' . $gcDomain . $dUserEndpoint . $userId, 'Content-Type: application/x-www-form-urlencoded' ), )); $response = curl_exec($curl); $info = curl_getinfo($curl); curl_close($curl); if ($info["http_code"] == 302) { echo 'Пользователь удален'; } else echo 'Ошибка'; |
Что дальше?
Скрипт готов и умеет удалять пользователей! Но как им воспользоваться? Если у Вас есть хостинг для php, нужно подгрузить наш файл на этот хостинг, а затем вызывать его по необходимости по url хостинга не забывая передать параметры uid, key и domain. Если же у Вас нет хостинга, то это не страшно. У вас уже есть XAMPP который может выполнять скрипты написанные на php, нужно лишь как-то дать доступ к XAMPP извне. Для этого можно воспользоваться сервисом NGROK
Там всё просто, регистрируемся, можно просто через Google войти. По ссылке выше скачать клиент NGROK. Затем нужно создать файл start.bat, в качестве содержимого указать две строки
1 2 |
ngrok authtoken 21mzEk0************VRiv_3zUAzg*********eEMR ngrok http 80 |
Непосредственно authtoken берем вот здесь в личном кабинете. После проделанных манипуляций сохраняем наш start.bat И запускаем его. Если всё верно, вы увидите окошко вроде того, что ниже.
И прям совсем финал
На этом шаге у нас теперь есть практически всё:
— Endpoin API найден
— Скрипт написан
— Доступ извне предоставлен
Осталось совсем чуть-чуть. Теперь мы заходим на GetCourse и создаем группу пользователей. В эту группу мы будем помещать тех, кого не жалко удалить. Затем идем в процессы, создаем процесс по пользователям, ставим условие «Периодическая проверка», а в правилах вхождения указываем «в группе» и выбираете группу которую создали на шаге ранее.
В теле самого процесса указываем блок Вызвать URL и вносим в него все необходимые параметры. Вместо id пользователя, подставляем переменнуюGetCourse в процессах по пользователю {object.uid}, параметр кем можно взять, нажав на замочек слева от адресной строки браузера.
Далее «Файлы cookie», выберите домен вашей школы, там так же разверните папочку «Файлы cookie» и в списке будет параметр PHPSESSID. Значение в поле «Контент» и используется в качестве key.
Теперь можно и протестировать наш процесс
Вот собственно и всё. Остается только сохранить этот процесс и запустить его. После чего можно делать выборки, добавлять пользователей массово в группу, а там GetCourse уже сформирует запросы на скрипт удаления и все добавленные пользователи будут удалены автоматически.
Собственно результат работы можно посмотреть на видео ниже.