Документация

API позволяет взаимодействовать с Knocknock.
Адрес взаимодействия https://knocknock.ru/api/МЕТОД
Способ передачи данных POST или GET
Максимальное количество обращений к API - 10 раз в секунду, в ином случае блокировка на 15 минут.

Готовый пример использования на PHP

Ниже вы можете найти примитивный пример реализации взаимодействия с нашим API на языке PHP. В этом примере раскрыты практически все основные возможности нашего сервиса.

В качестве примера реализована аворизация на гипотетическом ресурсе используя сессии.
<?php
    session_start();
    $_APPID = 1;
    $_APPKEY = "secretkey";

    if(!isset($_SESSION['logged'])) {
        if(isset($_GET['success']) && isset($_SESSION['knock_id'])) {
            // Отменяем Knock-операцию
            $knock_id = $_SESSION['knock_id'];
            // Получили от клиента переадресацию, убеждаемся что ответ действительно получен
            $request = file_get_contents("https://knocknock.ru/api/getKnock?key={$_APPKEY}&appid={$_APPID}&knock_id={$knock_id}");
            $request = json_decode($request, true);
            if($request['status']) {
                if($request['is_completed'] == true) {
                    if($request['answer'] == true) {
                        // Получен ПОЛОЖИТЕЛЬНЫЙ ответ из Telegram, авторизуем пользователя 
                        $_SESSION['logged'] = true;
                    }
                    else {
                        // Получен ОТРИЦАТЕЛЬНЫЙ ответ из Telegram
                    }
                    // Все данные для авторизации обнуляем
                    unset($_SESSION['knock_id']);
                    unset($_SESSION['code']);
                    unset($_SESSION['public_check_url']);
                }
            }
        }
        else if((isset($_GET['cancel']) || isset($_POST['cancel'])) && isset($_SESSION['knock_id'])) {
            // Отменяем Knock-операцию
            $knock_id = $_SESSION['knock_id'];
            file_get_contents("https://knocknock.ru/api/unKnock?key={$_APPKEY}&appid={$_APPID}&knock_id={$knock_id}");
            unset($_SESSION['knock_id']);
            unset($_SESSION['code']);
            unset($_SESSION['public_check_url']);
        }
        else if(isset($_POST['login']) && !isset($_SESSION['knock_id'])) {
            // Инициализируем Knock-операцию
            $msg - urlencode("Зафиксирована попытка авторизоваться в личном кабинете, подтвердите свое действие");
            $userID = 17; // User ID в системе Knocknock
            $request = file_get_contents("https://knocknock.ru/api/initKnock?key={$_APPKEY}&appid={$_APPID}&msg={$msg}&user={$userID}");
            $request = json_decode($request, true);
            if($request['status'] == true) {
                $_SESSION['knock_id'] = $request['knock_id'];
                $_SESSION['code'] = $request['secure_code'];
                $_SESSION['public_check_url'] = $request['public_check_url'];
            }
        }
    }
    else {
        if(isset($_GET['logout'])) {
            // Выходим из аккаунта
            unset($_SESSION['logged']);
        }
    }
?>
<!DOCTYPE html>
<html lang="en">
<head>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
    <meta charset="UTF-8">
    <title>Пример Knocknock PHP</title>
</head>
<body>
    <?php 
        if(!isset($_SESSION['logged'])) { 
            if(isset($_SESSION['knock_id'])) { ?>
                <p>
                    Ключ запроса <b><?=$_SESSION['code']?></b><br/>
                    Подтвердите пожалуйста свою авторизацию в Telegram
                </p>
                <form action method='post'>
                    <input type='submit' value='Повторить запрос' name='cancel'>
                </form>
                <script src='https://knocknock.ru/uploads/js/check.js'></script>
                <script>
                    checkKnock("<?=$_SESSION['public_check_url']?>", function(answer) {
                        if(answer != null) {
                            if(answer == true) location.href = "https://knocknock.ru/test_app.php?success";
                            else location.href = "https://knocknock.ru/test_app.php?cancel";
                        }
                        else console.log("Ответа нет, ждем");
                    })
                </script>
            <?php } else { ?>
                <form action method='post'>
                    <!-- Какие-то дополнительные поля формы, например логин и пароль -->
                    <input type='submit' value='Войти в аккаунт' name='login'>
                </form>
            <?php } ?>
        <?php } else { ?>
            <p>Вы авторизованы! <a href='https://knocknock.ru/test_app.php?logout'>Выйти</a></p>
        <?php } ?>
</body>
</html>

        

Определение понятий

ТерминОпределение
Сервис Так называется созданное вами в личном кабинете Knocknock решение, которое позволяет вам взаимодействовать с нашим API, просматривать статистику, подключать своего бота и так далее.
Подписка на сервис Специальное действие, при котором пользователь Telegram отправляет специальный код Knocknock боту (или вашему боту при соответствующей настройке сервиса), которым он выражает свое намерение подключиться к вашему сервису и получать Knock-операции.
Пользователь Это пользователь Telegram, который подписался на ваш сервис и теперь ему можно отправлять Knock-операции и всячески с ним взаимодействовать.
Knock-операция Специальное сообщение в Telegram к вашему пользователю с предложением одобрить или отклонить ту или иную операцию, например автризацию в аккаунт на вашем сайте.
Ключ запроса Случайно сгенерированный четырехзначный код, который известен вам и пользователю, который совершает какое-либо действие, например входит в аккаунт вашего сайта. Вы можете показать код на вашем сайте и попросить ответить в Telegram, пользователь сравнивает ключи запроса, если совпадают, то он может быть уверен, что одобряет именно свое действие а не действие злоумышленника.

Стандартная схема взаимодействия

МетодinitKnock

Метод инициализирует Knock-операцию для пользователя вашего сервиса.
Если повторить initKnock к пользователю, который не успел ответить на уже ранее инициализированную Knock-операцию, то старая Knock-операция будет автоматически отменена и удалена у пользователя.
Для успешного выполнения метода необходимо передать следующие параметры:
параметрописание
appid Идентификатор вашего сервиса
key Секретный ключ вашего сервиса
appuser
  или
user
appuser - это идентификатор на вашей стороне, например e-mail адрес, или ID пользователя в вашей системе. Идентификатор передается вами и присваивается во время подписки пользователя к вашему сервису.

user - это идентификатор пользователя на нашей стороне, мы его передаем вам во время подписки пользователя на ваш сервис, универсальный способ.
msg Сообщение о проводимой пользователем операции. Например вы можете передать подобное сообщение: "Подтвердите пожалуйста авторизацию в ваш аккаунт с IP 127.0.0.1 (Россия). Это точно были вы?". По умолчанию будет написано: "Если это вы, пожалуйста подтвердите свое действие нажав на кнопку ниже\nЕсли вы ничего не делали, то немедленно отклоните эту операцию"
action В Knock-операции появится специальное дополнительное поле с переданным значением. Например вы можете кратко указать действие пользователя "Смена пароля", и ваш пользователь сразу поймет о чем данная Knock-операция
agree_btn Текст который будет на кнопке согласия, по умолчанию Разрешить
cancel_btn Текст который будет на кнопке отказа, по умолчанию Запретить
remove Время в минутах, спустя которое после ответа пользователем, это сообщение будет удалено из его Telegram истории для соблюдения порядка. По умолчанию стоит 1 минута, поставьте 0 если не хотите удалять сообщения из истории.
code Если не хотите использовать дополнительный уровень безопасности с кодами, то можете передать 0 с этим параметром, тогда пользователь не увидит ключ запроса.

После совершения запроса вы получите от нас JSON ответ приблизительно следующего вида:
{
    "status": true,
    "knock_id": 1420,
    "secure_code": 7028,
    "public_check_url": "https://knocknock.ru/api/checkKnock?pk=..."
}
        
параметрописание
status true в случае успешного выполнения запроса, false в случае неудачи
knock_id Уникальный идентификатор Knock-операции на стороне Knocknock
secure_code Случайно сгенерированный четырехзначный ключ запроса, который вы можете показать пользователю для обеспечения дополнительного уровня безопасности
public_check_url Публичная ссылка для проверки статуса ответа пользователем на отправленную Knock-операцию, подробное описание и способ использования можно найти здесь.

МетодgetKnock

Данный метод возвращает основную информацию по инициализированной ранее Knock-операции.
Для успешного выполнения метода необходимо передать следующие параметры:
параметрописание
appid Идентификатор вашего сервиса
key Секретный ключ вашего сервиса
knock_id Идентификатор осуществленной ранее Knock-операции

После совершения запроса вы получите от нас JSON ответ приблизительно следующего вида:
{
    "status": true,
    "knock_id": 1420,
    "init_time": 1585805131,
    "secure_code": 0,
    "is_delivered": true,
    "user": 301,
    "is_appuser": false,
    "is_completed": true,
    "answer": true,
    "public_check_url": "https://knocknock.ru/api/checkKnock?pk=...",
    "transferred_data": {
        "msg": "Подтвердите пожалуйста смену пароля от аккаунта [email protected]",
        "agree_btn": "Меняем!",
        "cancel_btn": "Это был не я!",
        "remove": "0",
        "code": "1"
    }
}
        
параметрописание
status true в случае успешного выполнения запроса, false в случае неудачи
knock_id Уникальный идентификатор Knock-запроса на стороне Knocknock
init_time UNIX время инициализации Knock-операции
secure_code Случайно сгенерированный четырехзначный ключ запроса, который вы можете показать пользователю для обеспечения дополнительного уровня безопасности
is_delivered Был ли доставлен данный Knock-запрос в Telegram к вашему пользователю, если false то вся информация ниже отсутствует
user Идентификатор пользователя к которому осуществлялась Knock-операция
is_appuser Если true, то использовался идентификатор с вашей стороны, если false то использовался наш уникальный идентификатор
is_completed Если true, то ответ от пользователя получен, если false то пользователь все еще не нажал ни на одну из кнопок
answer Если is_completed true, то есть это поле. true - пользователь дал положительный ответ, false - пользователь дал отрицательный ответ
public_check_url Публичная ссылка для проверки статуса ответа пользователем на отправленную Knock-операцию, подробное описание и способ использования можно найти здесь.
transferred_data Переданные в initKnock дополнительные поля

МетодunKnock

Данный метод отменяет Knock-операцию (которая должна быть без ответа пользователя) и удаляет сообщение из Telegram.
Для успешного выполнения метода необходимо передать следующие параметры:
параметрописание
appid Идентификатор вашего сервиса
key Секретный ключ вашего сервиса
knock_id Идентификатор осуществленной ранее Knock-операции

После совершения запроса вы получите от нас JSON ответ приблизительно следующего вида:
{
    "status": true
}
        
параметрописание
status true в случае успешного выполнения запроса, false в случае неудачи

Публичный методcheckKnock

Этот метод используется для проврки статуса Knock-операции на стороне клиента (доверять следует только информации которую мы отправляем на ваш Callback), например с помощью AJAX запроса каждые N секунд, чтобы при получении положительно ответа направить клиента на нужную страницу вашего сайта.
Актуальную checkKnock ссылку вы получаете каждый раз инициализируя initKnock или с помощью метода getKnock, публичная checkKnock ссылка передается в public_check_url

ВНИМАНИЕ! public_check_url адрес доступен с одного IP 1 раз в 2 секунды, в ином случае выдается кэшированная версия последнего ответа.


После совершения запроса вы получите от нас JSON ответ приблизительно следующего вида:
{
    "status": true,
    "code": 2040,
    "request_time": 1585924617,
    "answered": true,
    "answer": true,
    "token": "AKH7I5Kb4g34yz4nrZ7GcrotFYHUCCu4d41MXBNPIGI77CknphUtz0N5YlOpO0jT"
}
        
параметрописание
status true в случае успешного выполнения запроса, false в случае неудачи
code Ключ запроса Knock-операции
init_time Время инициализации Knock-операции
answered Получен ли ответ от пользователя о его решении касаемо Knock-операции
answer true - пользователь дал положительный ответ, false - пользователь жад отрицательный ответ
token Уникальный, случайно сгенерированный ключ, который появляется только в случае подтверждения Knock-операции вашим пользователем. Этот токен можно использовать для проверки в методе verifyToken
spam_filter может появиться вместе со status=false, что будет означать что превышен лимит количества обращений


Как можно использовать?

Например ваш клиент пытается авторизоваться в личном кабинете вашего сайта, вводит логин и пароль, нажимает на кнопку "Войти". Теперь вы отправляете запрос на initKnock и спрашиваете у пользователя, действительно ли это именно он входит в личный аккаунт. Перезагружаем страницу, показываем ключ запроса и просим подтвердить свое действие в Telegram. Параллельно на стороне клиента осуществляем AJAX запрос на ссылку public_check_url, где получив какие-либо данные решаем куда переадресовать клиента и что ему показать. При этом обязательно сверьте информацию самостоятельно, ведь мы шлем вам Callback, или сами сделайте запрос к getKnock на стороне сервера.

Пример реализации проверки ответа на стороне клиента с помощью библиотеки jQuery:

var intervalTimer = null;
var requests = 0;
function checkKnock(url, callback) {
    if(intervalTimer != null) {
        // Если checkKnock уже был и сделан новый, нужно все обнулить
        clearInterval(intervalTimer);
        requests = 0;
    }
    intervalTimer = setInterval(function() {
        $.post(url, function(data) {
            if(data.status) {
                if(data.answered) {
                    // Пользователь ответил в Telegram
                    clearInterval(intervalTimer);
                    callback(data.answer);
                    return;
                }

                if(requests >= 26) {
                    // Если ожидание длится более минуты, то можно отменить что-либо на стороне клиента
                    requests = 0;
                    clearInterval(intervalTimer);
                    callback(false);
                    return;
                }
                requests++;
            }
            callback(null);
        })
    }, 2300);
}

checkKnock("https://knocknock.ru/api/checkKnock?pk=...", function(answer) {
    if(answer != null) {
        if(answer == true) console.log("Получен положительный ответ");
        else console.log("Получен отрицательный ответ");
    }
    else console.log("Ответа нет, ждем");
})
        

МетодverifyToken

Данный метод служит проверкой token (уникального случайно сгенерированного ключа), который вы получаете в публичном методе checkKnock.
Токен можно проверить только один раз, в остальных случаях он вернет false.
Для успешного выполнения метода необходимо передать следующие параметры:
параметрописание
appid Идентификатор вашего сервиса
key Секретный ключ вашего сервиса
appuser
  или
user
appuser - это идентификатор на вашей стороне, например e-mail адрес, или ID пользователя в вашей системе. Идентификатор передается вами и присваивается во время подписки пользователя к вашему сервису.

user - это идентификатор пользователя на нашей стороне, мы его передаем вам во время подписки пользователя на ваш сервис, универсальный способ.
token Ключ полученный в checkKnock

После совершения запроса вы получите от нас JSON ответ приблизительно следующего вида:
{
    "status": true,
    "knock_id": 924
}
        
параметрописание
status true в случае если токен найден на нашей стороне, и пользователь действительно давал положительный ответ на Knock-операцию. В остальных случаях мы возвращает false.
knock_id Уникальный идентификатор Knock-операции


Как можно использовать?

Как известно checkKnock проверяется на стороне клиента. Как только вы получаете status: true из checkKnock, вы можете вставить в форму дополнительное скрытое input поле со значением токена, и отправить форму с помощью, например, jQuery: $("form").submit(); и на стороне сервера проверить это переданное значение с помощью метода verifyToken.

Проверить токен можно только один раз и в течение двух минут, в остальных случаях будет возвращать false.
true будет означать, что в течение последних двух минут пользователь одобрял Knock-операцию.
false будет означать, что пользователь не одобрял или прошло более 2 минут или этот токен уже проверялся ранее

МетодinitNotifier

Данный метод доставляет вашим пользователям оповещения.
Для успешного выполнения метода необходимо передать следующие параметры:
параметрописание
appid Идентификатор вашего сервиса
key Секретный ключ вашего сервиса
appuser
  или
user
appuser - это идентификатор на вашей стороне, например e-mail адрес, или ID пользователя в вашей системе. Идентификатор передается вами и присваивается во время подписки пользователя к вашему сервису.

user - это идентификатор пользователя на нашей стороне, мы его передаем вам во время подписки пользователя на ваш сервис, универсальный способ.
msg Какое либо сообщение пользователю, например "Ваш баланс пополнен на 5000 рублей".

После совершения запроса вы получите от нас JSON ответ приблизительно следующего вида:
{
    "status": true,
    "notifier_id": 924
}
        
параметрописание
status true в случае успешного выполнения запроса, false в случае неудачи
notifier_id Уникальный идентификатор оповещения

Обработка данныхCallback на Knock события

Здесь речь пойдет о Callback, который в настройках сервиса указан как "Callback URL для метода initKnock".

Каждый раз, когда ваш пользователь нажимает на кнопки "Разрешить" или "Запретить" в своем Telegram - мы моментально отправляем вам информацию об этом.

Мы передаем вам следующие данные POST запросом:
параметрописание
knock_id Уникальный идентификатор Knock-операции который вы получили при initKnock
notifier_id Уникальный идентификатор оповещения
code Ключ запроса
user Идентификатор пользователя
is_appuser true - в user использовался идентификатор с вашей стороны, например никнейм. false - в user использовался уникальный идентификатор с нашей стороны
init_time UNIX время инициализации Knock-операции
answer_time UNIX время ответа пользователя на Knock-операцию
user_answer true - пользователь нажал на кнопку "Разрешить", false - пользователь нажал на кнопку "Запретить"
appid Идентификатор вашего сервиса

Обработка данныхCallback пользователей

Здесь речь пойдет о Callback, который в настройках сервиса указан как "Callback URL о пользователях сервиса".

Для того, чтобы вы смогли отправлять Knock-операции и оповещения тому или иному человеку, для начала его нужно подписать на ваш сервис. Подробнее о подписке пользователей прочтите нажав сюда. А здесь мы обсудим обработку событий ваших пользователей.

Как только пользователь введет ваше секретное сообщение (о котором мы рассказываем здесь) в бота Telegram, мы отправляем на ваш Callback пользователей следующие данные POST запросом:
параметрописание
action Действие пользователя, check в случае проверки секретного сообщения
key Секретное сообщение, которое вы должны найти у себя и понять для кого оно выделено
hash sha256 хэш сформированный из appid+key+Секретный ключ API сервиса

Вы должны на своей стороне в Callback пользователей сверить все полученные от нас данные, найти какому из ваших пользователей принадлежит выданное вами секретное сообщение и вернуть нам информацию в JSON ответе
В случае если пользователь найден и можно оформлять подписку мы ожидаем:
{
    "result": true,
    "appuser": "Nickname or ID or E-mail"
}
        
Не обязательно возвращать нам appuser, но если вы его указываете, то это будет означать, что вы сможете совершать Knock-операции и оповещения по своему внутреннему идентификатору пользователя, например по его ID внутри системы, по E-mail или никнейму. Важно чтобы переданное вами значение было уникальным среди всех пользователей вашего конкретного сервиса.
В случае если вы не ожидаете подписки по этому секретному сообщению, мы ожидаем получить отказ.
{
    "result": false
}
        
После того, как мы получим от вас result: true, мы добавляем Telegram аккаунт пользователя в список пользователей вашего сервиса. Если вы передавали нам appuser, то мы присваиваем его к данному пользователю, и после всего на этот же Callback пользователей отправляем новое событие и передаем следующие данные POST запросом:
параметрописание
action Действие пользователя, connected в случае окончательной подписки пользователя на ваш сервис
key Секретное сообщение, которое было передано при check событии
hash sha256 хэш сформированный из appid+key+Секретный ключ API сервиса
[user]id (в массиве user) Уникальный идентификатор пользователя на нашей стороне, вы всегда можете обращаться именно к нему при формировании Knock-операций и оповещений
[user]nickname (в массиве user) Никнейм пользователя в Telegram
[user]appuser_saved (в массиве user) false в случае ошибок или не переданного значения appuser, true если мы смогли сохранить appuser для пользователя

Пример реализации Callback пользователей на языке PHP
<?php
    $_APPID = 1;
    $_SECRET = "t6Z2miF5KxDdpFOlePDfPBUXovb3nkLHf";

    if($_POST['key'] && $_POST['hash']) {
        // Инициализируем переменные
        $key = $_POST['key'];
        $hash = $_POST['hash'];

        // Генерируем настоящий хэш
        $realHash = hash("sha256", $_APPID.$key.$_SECRET);

        // Сверяем полученный хэш с настоящим
        if(hash_equals($realHash, $hash)) {

            // Определяемся с действием
            if($_POST['action'] == "check") {
                // Сверяем полученное секретное сообщение с тем, что хранится в вашей базе данных и определяем пользователя, к которому привязываемся
                $_SOME_REAL_SECRET_MSG = "pIOHUGYTCYXTRCYUGIHOJPK";

                if(strcmp($key, $_SOME_REAL_SECRET_MSG) == 0) {
                    // Мы нашли такое секретное сообщение и поняли какому пользователю оно принадлежит, сообщаем Knocknock об этом
                    echo json_encode(["result" => true]);
                }
                else echo json_encode(["result" => false]);
                // Не нашли кому принадлежит, и вообще что-то не то, отказываем
            }
            else if($_POST['action'] == "connected") {
                // Пользователь подключился
                $params = $_POST['user']; // Просто для удобства управления переданными данными пользователя 
                $userid = $params['id']; // ID юзера на стороне Knocknock, по нему можно осуществлять все запросы
                $nickname = $params['nickname']; // Никнейм юзера в Telegram
                // Сохраняем куда-нибудь для дальнейшего обращения к пользователю
            }
        }
        else echo json_encode(["result" => false]);
    }
?>
        
В целях безопасности и предотвращения спама пользователь может обращаться только 1 раз в 20 секунд.

ОписаниеПринцип подписки пользователей на сервис

Надеемся для вас понятно, что для осуществления каких-либо операций с тем или иным пользователем мы должны получить от него разрешение на эту деятельность, это и называется подпиской. Чтобы пользователь Telegram ожидал от конкретно вашего сайта каких-либо сообщений и для него это не было новостью.

Получить разрешение можно одним способом, приводим пример ниже:
Например пользователь находится на вашем сайте, в своем личном кабинете и перешел в настройки. Там он переходит на вкладку "Безопасность", где от вас написано предложение подключиться к вашему Telegram боту и обезопасить свой аккаунт, для этого он должен отправить такому-то боту сообщение формата x-xxxxxx:секртноесообщение
Это самое секртноесообщение должно быть трудно подбираемым, уникальным и числиться за конкретным пользователем внутри вашей системы, чтобы вы смогли идентифицировать его.

Если секртноесообщение будет E-mail или, например, никнеймом - то любой сможет подобрать и выдать себя за другого пользователя. Поэтому советуем генерировать случайные символы в разном регистре.

А вот x-xxxxxx это публичный уникальный идентификатор вашего сервиса внутри системы Knocknock, его можно найти в личном кабинете Knocknock в настройках сервиса.

x-xxxxxx:секртноесообщение - а все это вместе называется секретным сообщением, которое и должен ваш пользователь отправить боту, чтобы подписаться на ваш сервис.

ТестерПроверка передаваемых для Knocknock данных

В этом разделе вы можете протестировать сообщения разного рода, и понять что вы можете слать через в Knocknock используя API. Для проверки валидности данных мы в том числе используем регулярные выражения, и не можем пропускать абсолютно любые символы в целях безопасности.
Поле appuser^([a-zA-Z0-9\+\@\-\(\)\.,:_\?!]){1,100}$
action в initKnock^([йЙёЁa-zA-Zа-яА-Я0-9\+\@\-\(\)\.,:_\?! ]){2,64}$
msg в initKnock^([йЙёЁa-zA-Zа-яА-Я0-9\+\@\-\(\)\.,:_\?! —\]\["'»«;\/=]){2,500}$
msg в initNotifier^([a-zA-Z0-9\+\@\-\(\)\.,:_\?!]){1,100}$
Кнопки agree_btn и cancel_btn^([йЙёЁa-zA-Zа-яА-Я0-9\+\@\-\(\)\.,:_\?! ]){2,16}$

ДополнительноBB коды для оформления текста

Чтобы красиво оформить свой текст (msg) в initKnock или initNotifier используйте BB коды.
[b]текст[/b] Текст будет жирным
[u]текст[/u] Текст будет подчеркнутым
[s]текст[/s] Текст будет зачеркнутым
[br] Используйте для перехода на новую строчку