Описание сервиса
Общие сведения
Сервис предоставляет доступ к функционалу Sender посредством http(s) транспорта.
Формат запросов-ответов и url
Тестовый сервер (dev): https://api-dev.sender.mobi/ver/
Пререлизный сервер (rc): https://api-rc.sender.mobi/ver/
Боевой сервер (prod): https://api.sender.mobi/ver/
ver - версия используемого АПИ
Все запросы посылаются методом POST с content-type "application/json", в кодировке UTF-8. В теле запроса отправляется json-структура, в ответе возвращается также json.
В определенные моменты времени сервер присылает клиенту (в comet-соединение) пакет вида:
{ "cid": "<clientMsgId>", "chatId":"<chatId>", "model":{ "1":"xxx.xxx.xxx.xxx", "2":"xxx.xxx.xxx.xxx" } "formId": "", "robotId": "ip", "companyId": "sender", "type":"sys" }
Тут поля обьекта model это порядковые номера (приоритет) ip-адресов для доступа к серверу. Если позиция "0" не занята, то в эту позицию следует поместить доменное имя. Иначе - помещаем его в конец списка. По этому списку осуществляем подключение к серверу. При получении любого невалидного ответа или сетевой ошибки переходим на следующий адрес.
Terminology:
developerID - ID выданный Сендером для индентификации Разработчика. Сохранияется в коде приложения;
developerKey - Секретный ключ выданный Сендером. Уникальный для каждого разработчика. Сохранияется в коде приложения;
UDID - Уникальный идентификатор устройства, подписанный разработчиком. Генерируется перед отправвкой на сервер;
masterKey - Уникальный идентификатор регистрации устройства в системе. Получается с сервера и сохраняется в настройках приложения;
Для генерации нужно использовать железный идентификатор устройства, например IMEI. Идентификатор устройства меняться не должен
UDID = HMAC-SHA1(Developer-Key, IMEI)
SHA1 длинной 160 символов
Вызывает клиент, если у него отсутсвует deviceKey или streaming закрывается ошибкой "3". Данный запрос не использует протокол форм.
POST /reg
{ "developerId":"1234", "udid": "<udid>", "pushToken":"<pushToken>", "devType": "<DevType>", "devModel": "<DevModel>" "devOS":"<devOS>", "versionOS":"<versionOS>", "clientType":"<clientType>", "clientVersion":"<clientVersion>", "language":"<language>", "companyId":"<companyId>" }
Параметры "apns..." (только для IOS):
Ответ (синхронно)
{ "code": "0", "deviceKey":"<deviceKey>", "challenge": "<challenge>", "mode": "<mode>" }
mode может быть: 1) "full" - полная версия с п2п контактами, на текщий момент эквивалентна "sync_user_ct"="true" (т.е. слать контакты в синхронизации). 2) "restricted" - урезанная версия без п2п контактов, на текщий момент эквивалентна "sync_user_ct"="false" (т.е. не слать контакты в синхронизации).
Calculation masterKey
masterKey = HMAC-SHA256(developer_key, udid + device_key)
GET /[request]?udid=&token=
На любой запрос в случае передачи невалидного параметра token, сооединение будет закрыто с ответом:
{ "code": "1", "challenge": "<challenge>" }
challenge - рандомное значение из 64 символоd необходимое для рассчета параметра token по алгоритму:
token = HMAC-SHA256(masterKey, challenge)
Параметр token имеет ограниченное время жизни (2 часа). Новое значение challenge вернется при следующем поднятии соединения.
Посылает клиент если на клиенте изменился токен.
POST /token?udid=&token=
{ "token":"<Token>", "apns":"<Apns>" }
Параметр apns, (только для IOS), значения:
Ответ (синхронно)
{ "code": 0 }
POST /version_set?udid=&token=
{ "devType": "<DevType>", "devModel": "<DevModel>", "devManufact": "<devManufact>", "devOS":"<devOS>", "versionOS":"<versionOS>", "clientType":"<clientType>", "clientVersion":"<clientVersion>", }
Ответ (синхронно)
{ "code": 0 }
POST /get_user_dev_info?udid=&token=
{ "userId": "<userId>" }
Ответ (синхронно)
{ "code": 0, "devs": [ {"sipLogin": "<sipLogin>"} ] }
POST /get_sip_info?udid=&token=
{ "sipLogin": "<sipLogin>" }
Ответ (синхронно)
{ "code": 0, "userId": "<userId>" }
Отправитель отправляет один раз в начале звонка пакет в send:
{ //позже уберем? "formId": "", "robotId": "<robotId>", "companyId": "sender", "from": "me", "chatId": "user+sender", "class":".callRing.sender", "model": { "userId": "<toUserId>" } }
На все девайсы получателя приходит в comet и в push (в history это тоже приходит):
{ //позже уберем? "from": "sender", "chatId": "user+sender", "formId": "", "robotId": "<robotId>", "companyId": "sender", "class": ".callState.sender", "model": { "state": "ring", "userId": "<userId>", "devId": "<devId>", "sipLogin": "<sipLogin>", "from_me": false, "code": "no_devices" }, "created": 1333333333, "type": "sys" }
state - может быть "ring" - гудок, "run" - разговор, "close" - завершен.
from_me - Boolean, если true - инициатор действия собственный девайс, false - чужой.
code - только для state="close", может быть "manual" когда человек отменил, "busy" - занят другим звонком, "no_devices" - если нет девайсов, есть и другие коды - при ошибках.
Параметры devId и sipLogin могут отсутствовать при state="close".
Когда получатель поднимает звонок sip он отправляет в send:
{ //позже уберем? "formId": "", "robotId": "<robotId>", "companyId": "sender", "from": "me", "chatId": "user+sender", "class": ".callRun.sender", "model": { "userId": "<fromUserId>", "devId": "<fromDevId>" } }
И вызывающему девайсу отпарвителя и всем остальным девайсам получателя приходит в comet .callState.sender c state="run". И отправитель должен начать sip звонок.
Когда звонок отменен или завершен, то нужно послать в send:
{ //позже уберем? "formId": "", "robotId": "<robotId>", "companyId": "sender", "from": "me", "chatId": "user+sender", "class": ".callClose.sender", "model": { "userId": "<userId>", "devId": "<devId>", "code": "<code>" } }
devId - необязательный только для отправителя только тогда когда получатель ничего не ответил ему.
code - необязательный, разрешены следующие: "manual" - когда человек отменил, "busy" - занят другим звонком, если не указан то используется "manual".
И всем девайсам получателя и отправител приходит в comet .callState.sender c state="close".
Послать комнаду получения контакт форм компаний после авторизации.
POST /get_companies_cf?udid=&token=
{ }
Ответ (синхронно)
{ "code": 0, "noDefaultCompanies":[ "<companyUserId1>", "<companyUserId2>" //... ], "defaultView": { //... } }
noDefaultCompanies - список UserId компаний у которых не дефалтовая форма контакта.
defaultView - фмл дефалтовой карточки, она также может прийти позже асинхроно через обычную форму контакта с CompanyId="!". В ней использется FML {{!meta.!user.<Parameter>}}
с помощью которых подставлется данные компании.
После чего асинхронно приходят какрточки компаний у которых не дефалтовая форма контакта. У карточек контактов FormId="contact", RobotId="contact".
Запрос:
POST /send?udid=&token=
Тело запроса:
{ "fs": [ { ... } ] }
в массиве fs передеются обычные асинхронные формы. Если по отправленной форме нужно получить procId и серверное время (time), то в корень json-представления этой формы добавляем уникальный идентификатор cid, который будет получен в ответе
Ответ 200 OK
{ "cr": [ { "cid": "<clientMsgId>", "packetId": "<serverMsgId - packetId>", "time": <time> } ], "code": 0 }
Алгоритм работы с очередью и пакетной отправки
Запрос:
POST /comet?udid=&token=&ac=<=&ln=
Тело запроса:
{ "meta": { "net": "wifi", "ci": "<chatId>" }, "lbi": "<lastBatсhId>", "size": <size>, "ref": "<ref>" }
ac - (обязательно), get параметр, идентифкатор текущего чата.
lt - (опционально), get параметр, географическая широта latitude в градусах, десятичный разделитель точка ".".
ln - (опционально), get параметр, географическая долгота longitude в градусах, десятичный разделитель точка ".".
lbi (обязательно), lastBatchId, строка - это bi (batchId), полученный в предыдущем ответе. Ответ на запрос приходит при наличии на сервере сообщений или через 5 минут приходит пустой.
size - (опционально), целое, ожидаемый максимальный размер пакета, если не указан то равен 50.
ref - (опционально), строка, референс пуша, который инициировал поднятие.
Ответ 200 OK
{ "bi": "<batchId>", "fs": [ { ... } ], "code": 0 }
Если после ответа bi нет, в следующем запросе lbi не передается. Если lbi не вернуть на сервер, он повторит отправку сообщений, которые были в этом пакете
При получении формы с сервера клиент оповещает о их получении в зависимости от значения поля model.state. Возможные значения и действия по ним:
Текстовое сообщение представляет собой упрощённую "невидимую" форму вида:
{ "model": { "text":"<text of mesage>", "key":"<key>" }, "companyId":"sender", "cid":"<cid>", "formId":"text", "robotId":"routerobot", "chatId":"<chatId>" }
Тут поле text содержит текст сообщения
Поле key содержит 5 последних символов публичного ключа получателя, которым было зашифровано сообщения (только для шифрованных сообщений)
Поля fromName и fromPhoto опциональны, если они присутствуют, то имя и иконка отправителя в чате берутся из этих полей а не по fromId
Поле chatId содержит id чата
При получении текстовое сообщение представляет собой форму:
{ "model": { "text":"<text of mesage>", "encrypted":true, "fromName":<users name>, "fromPhoto":<users avatar path> }, "companyId":"sender", "cid":"<cid>", "formId":"text", "robotId":"routerobot", "chatId":"<chatId>", "from":"<userId>", "type":"msg" }
Тут поле text содержит текст сообщения
Поле encrypted (опционально) показывает зашифровано ли сообщение
Поле chatId содержит id чата
Поле from содержит userId отправителя
Сохранение, обновление и получение информации о себе
Сохранение, обновление. Если поле не передается, его не изменяем. Чтобы удалить значение - передаем поле с пустым значением.
POST /selfinfo_set?udid=&token=
{ "name": "<UserName>", "photo": "<photoUrl>", "address": "<address>", "description": "<Description>", "btcAddr": "<address for receive btc payments>", "msgKey": "<public key to encrypt messages>" }
Ответ (синхронно)
{ "code": 0 }
Получение:
POST /selfinfo_get?udid=&token=
{ }
Ответ (синхронно)
{ "selfInfo": { "name": "<UserName>", "photo": "<photoUrl>", "address": "<address>", "description": "<Description>", "btcAddr": "<address for receive btc payments>", "msgKey": "<public key to encrypt messages>", "companies": [ "<companyId>", ... ], "contacts": [ { "type":"phone", "value":"38093432334", "valueRaw":"093 432334" }, ... ], "code": 0 } }
Получение информации о пользователе.
POST /get_user_info?udid=&token=
{ "userId": "<userId>", "fields": ["<field>"] }
Ответ 200 OK
{ "user": { "name": "<UserName>", "photo": "<photoUrl>", "description": "<Description>", "isCompany":"<isCompany>", "contacts": [ { "type":"phone", "value":"38093432334" }, ... ] } "code": 0 }
fields - массив полей, которые необходимо вернуть. Пример fields:["name"]. Если не указан, возвращаются все.
Получение списка операторов и ролей компании
POST /get_operators
{ "companyId": "<companyId>" }
Ответ 200 OK
{ "operators": [ { "userId":"<userId>", "roleId":"<roleId>", "name": "<UserName>", "photo": "<photoUrl>" } ], "roles":[ { "roleId":"<roleId>", "name": "<RoleName>" } ], "code": 0 }
Получение списка операторов компании
POST /get_company_operators
{ "companyId": "<companyId>" }
Ответ 200 OK
{ "operators": ["<userId>"], "code": 0 }
Запрос:
POST /history?udid=&token=
Тело запроса:
{ "pos":<pos>, "size":<size>, "chatId":"<chatId>" }
pos - с какой позиции получать сообщения, 0 - с начала, n - c n-го сообщения
size - количество возвращаемых сообщений
Ответ 200 OK
{ "msgs": [<msgs>], "code": 0 }
SendBar представляет собой набор элементов управления специфичный для чата с данной компанией.
Для всех чатов кроме p2p чата с компанией у которой явно установлен sendBar используется sendBar компании Sender";
Представляет собой json-структуру вида:
{ "textColor": "#000000", "items": [ { "id": "1", "icon": "https://s.sender.mobi/bars/plus.png", "actions": [ { "oper": "reload", "_0": [ 2, 3, 4, 5, 8, 6, 7 ], "_1": [ 9, 10, 11, 12, 13, 16, 17, 18 ] } ] }, { "id": "2", "icon": "https://s.sender.mobi/bars/cancel.png", "actions": [ { "oper": "reload", "_0": [ 1, 3, 4, 5, 8, 6, 7 ] } ] }, { "id": "3", "icon": "https://s.sender.mobi/bars/twitch.png", "actions": [ { "oper": "sendMedia", "type": "twitch" } ] }, { "id": "4", "icon": "https://s.sender.mobi/bars/geo2.png", "actions": [ { "oper": "sendMedia", "type": "location" } ] }, { "id": "5", "icon": "https://s.sender.mobi/bars/text.png", "actions": [ { "oper": "sendMsg", "expand": false }, { "oper": "reload", "_0": [ 1, 5, 7, 8 ] } ] }, { "id": "6", "icon": "https://s.sender.mobi/bars/camera.png", "actions": [ { "oper": "sendMedia", "type": "photo" } ] }, { "id": "7", "icon": "https://s.sender.mobi/bars/smile.png", "actions": [ { "oper": "sendMedia", "type": "smile" } ] }, { "id": "8", "icon": "https://s.sender.mobi/bars/voice.png", "actions": [ { "oper": "sendMedia", "type": "voice" } ] }, { "id": "9", "icon": "https://s.sender.mobi/bars/add_user.png", "name": { "ru": "Добавить", "en": "Add user" }, "actions": [ { "oper": "addUser" } ] }, { "id": "10", "icon": "https://s.sender.mobi/bars/stickers.png", "name": { "ru": "Стикер", "en": "Sticker" }, "actions": [ { "oper": "sendMedia", "type": "sticker" } ] }, { "id": "11", "icon": "https://s.sender.mobi/bars/attach.png", "name": { "ru": "Файл", "en": "Send file" }, "actions": [ { "oper": "sendMedia", "type": "file" } ] }, { "id": "12", "icon": "https://s.sender.mobi/bars/video.png", "name": { "ru": "Видео", "en": "Send video" }, "actions": [ { "oper": "sendMedia", "type": "video" } ] }, { "id": "13", "icon": "https://s.sender.mobi/bars/cards.png", "name": { "ru": "Деньги", "en": "Money" }, "actions": [ { "oper": "reload", "_1": [ 14, 15 ] } ] }, { "id": "14", "icon": "https://s.sender.mobi/bars/send.png", "name": { "ru": "Отправить", "en": "Send" }, "actions": [ { "oper": "callRobot", "class": ".sendMoney.sender" } ] }, { "id": "15", "icon": "https://s.sender.mobi/bars/top_up.png", "name": { "ru": "Пополнить", "en": "Fill phone" }, "actions": [ { "oper": "callRobot", "class": ".payMobile.sender" } ] }, { "id": "16", "icon": "https://s.sender.mobi/bars/lock_open.png", "icon2": "https://s.sender.mobi/bars/lock_closed.png", "name": { "ru": "Шифрование", "en": "Encryption" }, "actions": [ { "oper": "switchCrypto" } ] }, { "id": "17", "icon": "https://s.sender.mobi/bars/vibro.png", "name": { "ru": "Вибро", "en": "Vibro" }, "actions": [ { "oper": "sendMedia", "type": "vibro" } ] }, { "id": "18", "icon": "https://s.sender.mobi/bars/games.png", "name": { "ru": "Игры", "en": "Play" }, "actions": [ { "oper": "reload", "_1": [ 19, 20, 21 ] } ] }, { "id": "19", "icon": "https://s.sender.mobi/bars/tic-tac.png", "name": { "ru": "Крестики-нолики", "en": "Tic Tac Toe" }, "actions": [ { "oper": "callRobot", "class": ".ticTacToe.sender" } ] }, { "id": "20", "icon": "https://s.sender.mobi/bars/vinni.png", "name": { "ru": "Винни Пух", "en": "Winny Puh" }, "actions": [ { "oper": "callRobot", "class": ".winnieThePoohHoney.sender" } ] }, { "id": "21", "icon": "https://s.sender.mobi/bars/chess.png", "name": { "ru": "Шахматы", "en": "Chess" }, "actions": [ { "oper": "callRobot", "class": ".chess.sender" } ] } ], "init": { "_0": [ 1, 3, 4, 5, 8, 6, 7 ] } }
textColor - цвет текста подписей к кнопкам
name - подпись на кнопке
id - идентификатор элемента бара (для построения уровней)
icon - изображение на кнопке в нормальном состоянии
icon2 - изображение на кнопке во "включенном" состоянии (опционально)
actions - действия по нажатию
Бар строится в 2 уровня "0" и "1". Уровень "0" всегда видимый, "1" - может появиться при активации одного из элементов бара.
Построение начинается с заполнения уровней элементами согласно id перечисленных в соответствующем массиве элемента "init".
Любой из элементов может содержать в списке actions элемент с "oper":"reload". Action этого вида требует перестроения уровней, аналогично init.
Остальные actions (если они есть) выполняются поле reload. Если в init или reload состав уровня не описан, он очищается.
SendBar является опциональным свойством любого контакта компании.
Динамически создаваемые элементы интерфейса приложения (в т.ч. элементы fml-форм) при их актвации пользователем могут инициировать действия, описанные c помощью actions-атрибута:
Значением атрибута actions является массив обьектов, которые описывают действия, выполняемые в порядке следования в массиве.
Каждый обьект одержит обязательное поле: oper - определяющее выполняемую операцию, обязательное поле. Оста
Выполнить вызов внешнего сервера с параметрами (опционально), введёнными в фроме. При ответе сервера форма с содержимым ответа отправляется обычным способом
Пример:
{ "actions": [ { "oper":"extCall", "url":"<url to external get request>", "form_data": true } ] }
form_data - признак, следует ли отправлять в запросе поля формы. Поля отправяляются как get-параметры в формате <имя поля>=<значение>&...
Отправить пользователя в указанный интерфейс приложения. Обязательным атрибутом является "to", который принимает значения:
contacts|dialogs|profile|settings
В случае, если action описан в fml-форме, она должна быть отправлена на сервер перед переходом
Пример:
{ "actions": [ { "oper":"goTo", "to":"<to>" } ] }
Возможные значения to
Добавить пользователя в текущий чат: открыть диалог выбора пользователя и по результату добавить выбранного (выбранных)
Если текущий чат p2p - будет создан новый, групповой чат
Пример:
{ "actions": [ { "oper":"addUser" } ] }
В поле "link" передается веб ссылка, начиная с http/https, поле обязательно. Открываем стандартный диалог выбора приложений для открытия ссылки, если таковых несколько. Если одно, открываем напрямую, если отсутствует уведомляем об отсутствии.
Пример:
{ "actions" : [ { "oper":"viewLink","link":"<link>" } ] }
Открыть окно ввода текста и введённый текст отправить сообщением в текущий чат
Пример:
{ "actions": [ { "oper":"sendMsg" } ] }
Открыть окно выбора медиа-контента (cпецифическое для типа контента и платформы) и выбранный контент отправить в текущий чат.
Обязательное поле type определяет тип контента. Варианты: sticker, file, photo, video, location
Пример:
{ "actions": [ { "oper":"sendMedia", "type":"<type>" } ] }
При активации элемента с этим oper, показываем диалог сканирования, обращаемся к ридеру, при успешном сканировании строку к номером карты помещаем в поле "card" json-структуры, которую отправляем на серврер как model формы. Остальные ранее введённые данные этой формы также отправляются в этой структуре аналогично обычному submit формы.
Пример:
{ "actions": [ { "oper":"scanCard" } ] }
В поле "phone" передается телефон в международном формате, без плюса, поле обязательно. Открываем стандартный диалог телефонного вызова с этим номером
Пример:
{ "actions": [ { "oper":"callPhone", "phone":"380501234567" } ] }
Вызывается робот в текущем чате (чате в котором форма находится).
В поле "class" передается класс робота который вызывается, поле обязательно.
Если авзывается из формы, при нажатии в model посылаются все те же элементы что и при нажатии на обычную кнопку этой формы.
Пример:
{ "actions": [ { "oper":"callRobot", "class":"<robotClass>", "data": { "name":"value" } } ] }
Данные из обьекта "data" передаются в model вместе с данными формы. Если имена полей совпадают с именами полей в форме данные из "data" считаются более приоритетными
При нажатии клиент-приложение должно послать в этот чат обычный fsubmit запрос:
POST /fsubmit
{ "sid": "<sid>", "chatId": "<chatId>", "model": {}, "class": "<robotClass>" }
В поле "userId" передается UserId пользователя или компании в p2p чат с которым нужно перейти, поле обязательно.
В поле "class" передается класс робота который вызывается, поле обязательно.
При нажатии в model посылаются все те же элементы что и при нажатии на обычную кнопку.
Пример:
{ "actions": [ { "oper": "callRobotInP2PChat", "userId": "<userId>", "class": "<robotClass>" } ] }
При нажатии клиент-приложение должно по найти/создать p2p чат и перейти в него, и послать в этот чат обычный fsubmit запрос:
POST /fsubmit
{ "sid": "<sid>", "chatId": "<chatId>", "model": {}, "class": "<robotClass>" }
В поле "userId" передается UserId пользователя или компании в p2p чат с которым нужно перейти, поле обязательно.
Пример:
{ "actions": [ { "oper": "startP2PChat", "userId": "<userId>" } ] }
При выборе элемента в поле action которого указан этот oper нужно открыть нативный диалог выбора пользователей из списка контактов.
В диалоге отображаются только зарегистрированные пользователи при "reg":true иначе - все пользователи.
При выборе конкретного пользователя его номер телефона помещается в поле формы, имя которого задано в атрибуте "to".
Если "autosubmit":true форма отправляется на сервер сразу после того, как клиент сделал выбор в списке контактов, иначе - после выбора форма доступна для работы и отправки на сервер обычным способом (кнопкой в форме)
Например:
{ "actions": [ { "oper": "selectUser", "reg": true, "to": "<field name>", "autosubmit":true } ] }
При выборе элемента в поле action которого указан этот oper нужно скрыть элементы, name которых указаны в массиве "hide", и показать элементы, name которых указаны в массиве "show". Т.е. первой группе должен быть назначен "state":"gone" а второй - "state":"visible" выполнена перерисовка формы
{ "actions": [ { "oper": "switchView", "hide": [ elem1, elem2 ], "show": [ elem3, elem4 ] } ] }
При выборе элемента в поле action которого указан этот oper нужно открыть окно с картой (google maps), при выборе точки на карте значение поля val должно быть равно занчению широты и долготы с разделителем ";" а поле title должно быть равно адресу выбранной точки.
{ "actions": [ { "oper": "coords" } ] }
При выборе элемента в поле action которого указан этот oper нужно вызвать окно сканирования qr-кода и отсканированный результат отправить роботу, указанному в поле "class". model отправляемой формы должна содержать результат распознавания кода в поле "qr". Форму результата отправляем в чат указанный в поле "chatId". Например:
{ "actions": [ { "oper": "qrScan", "class":"<robotClass>", "chatId":"<chatId>" } ] }
В результает отправляем форму:
{ "sid": "<sid>", "chatId": "<chatId>", "model": { "qr":"<value>" }, "class": "<robotClass>" }
Если для клиента есть сообщения, а он не вычитывает их, сервер может отправить клиенту push-сообщение по системному каналу, в зависимости от платформы клиента
Также сервер может спросить клиента в онлайне он или нет.
Push-сообщение представляет собой json-обьект вида:
{ "status": "wake_up", "online_key": "<key>", "ref":"<ref>" }
Оба поля опциональны.
При получении "status":"wake_up" нужно поднять comet-канал для получения сообщений. "" передавать в коммет
При получении "online_key" нужно послать синхронный запрос вида:
POST /online?udid=&token=<token>&online_key=<key>&ref=
где - значение поля "online_key" в push-сообщении
В случае, если при получении/обработке ответа/сообщения с сервера произошла ошибка, то клиентское приложение шлёт на сервер форму:
{ "fs": [ { "cid": "<clientMsgId>", "chatId":"<chatId>", "model":{ "time":1223456, "net":"<type of connection>", "get":"< get request>", "post":"<post request>", "data":"<crash data>" }, "formId": "", "robotId": "crash", "companyId": "sender" } ] }
где:
type of connection - тип соединения: wifi или mob
Вызов "взбодрить" в чате с параметром type.
type - один из: kickass fail lol omg win wtf cool hurray thanks
type:kickass - по умолчанию
POST /send?udid=&token=
{ "fs": [ { "cid": "<clientMsgId>", "chatId":"<chatId>", "model":{"type":"<type>"}, "formId": "", "robotId": "alert", "companyId": "sender" } ] }
Ответ 200 OK
{ "cr": [ { "cid": "<clientMsgId>", "packetId": "<serverMsgId - packetId>", "time": <time> } ], "code": 0 }
Ответ (в comet)
{ "fs": [ { "model": { "state":"alert" }, "chatId": "<chatId>", "from": "<userId>", "formId": "<type>", "robotId": "alert", "companyId": "sender", "view": "<fml>", "type":"fml" } ] }
Для отправки шифрованного сообщения получателю должны быть соблюдены следующие условия:
Алгоритм зашифровывания:
Алгоритм расшифровывания:
При возникновении ошибки расшифровки считать сообщение не шифрованным и отображать "как есть"
При возникновении ошибки зашифровывания выводить сообщение пользователю и не отправлять сообщение
Загрузка файлов/изображений.
POST /upload?udid=<UDID>&token=<Token>&filename=<FileName>&filetype=<FileType>
BODY содержит загружаемый файл в бинарном формате. Максимальный размер файла 104857600 байт.
{ "url":"<URL>", "code":0 }
FileName, FileType, URL - формат значений не определен.
Для загрузки картинок с созданием превью. Клиент-приложение это делает самостоятельно.
Поддерживаемые форматы: jpg, gif, png.
Если картинка большая - то можно запрещать посылать ее как картинику, только как файл (для web - не больше 5 MB).
Превью картинки: Конвертировать в jpg с коэффициентом сжатия 0.6, квадрат 400х400, если оригинальная картинка не квадратная - то из нее берется центральный квадрат. Альфа-канал заполнять белым цветом. Для гиф брать первый кадр (или если это невозможно то картинку-заглушку).
Полная картинка: 1) Для gif - оригинальный gif файл. 2) Для других форматов - конвертировать в jpg с коэффициентом сжатия 0.6, если большая из сторон превышает 1600 - сжимать пропорционально чтобы это сторона стала 1600, если не превышает - то размеры картинки оставлять оригинальными. Альфа-канал заполнять белым цветом.
Для загрузки аватаров пользователей.
Будет делать клиент-приложение, скоро будет согласование.
jpg размер 800x800. jpg размер 120x120.
Будет делать клиент-приложение, скоро будет согласование.
jpg размер 120x120.
Активация/деактивация полной версии сендера. После изменения версии необходимо выполнить повторную синхронизацию контактов. Подробнее в разделе Sync Request.
POST /full_version
{ "activate":"true|false" }
Ответ
{ "sync_user_ct":"true|false" }
sync_user_ct - синхронизировать или нет свою контактную книгу
Получить текущий чат.
Отправляет клиент в чат с Sender-oм.
POST /send в fs:
{ "chatId": "user+sender", "model": {"companyId":"privat24"}, "companyId": "sender", "robotId": "getCurrentChat", "formId": "" }
model.companyId - для какой компании выполняется, пока разрешено только "privat24" только
Ответ (синхронно)
Ответ (асинхронно)
{ "packetId": "<packetId>", "linkId": "<packetId>", "chatId": "user+sender", "model": { "chatId":"<chatId>" }, "companyId": "sender", "robotId": "getCurrentChat", "formId": "" }
model.chatId - текущий чат
Поиск компаний в глобальной книге
Отправляет клиент при вводе более 2ух символов в поисковой строке контактной книги
POST /global_search
{ "t":"Киевс" }
t - введенный текст
Ответ (синхронно)
{ "code":0, "cts"[ { "userId": "<userId>", "name": "<name>", "description": "<description>", "photo": "<photo>", "isCompany": true } ] }
Поиск, обновление global_search.
Отправляет клиент при вводе более 2ух символов в поисковой строке контактной книги. Клиентам нужно экономить кол-во запросов, т.е. отправлять не по символьно - а через 1-2 секунды когда человек перестал печатать.
POST /search
{ "t":"Киевс" }
t - введенный текст
Ответ (синхронно)
{ "code": 0, "list": [ { "type": "contact", "userId": "<userId>", "name": "<name>", "description": "<description>", "photo": "<photo>", "isCompany": true }, { "type": "contact", "userId": "<userId>", "name": "<name>", "description": "<description>", "photo": "<photo>", "isCompany": true, "actions": [ { "oper": "callRobotInP2PChat", "userId": "<robotUserId>", "name": "<robotName>", "photo": "<robotPhoto>", "class": "<robotClass>", "data":{ "param1": "value1", "param2": {"key2":"value2"}, "param3": [true, false, 1, -1.2, [], {}, {"q":"aaa"}] } } ] } ] }
userId, name, description, photo, isCompany - в этих полях приходят данные контакта.
action - необязательный параметр, массив, в котором приходят экшены.
action.oper - "callRobotInP2PChat" как и в action вызов робота в п2п чате.
action.photo, action.name - фото и подпись экшена.
action.userId - в какой чат переходить, сделано так для совместимости с action callRobotInP2PChat.
action.data - необязательный параметр, объект, если есть то это параметры которые нужно посылать в model при запуске робота.
Подтверждение доставки сообщения GET /deliv?udid=&token=&chatId=&packetId=
Ответ 200 OK
{ "code": 0 }
Оповещение о добавлении пользователя в чат.
Ответ (асинхронно)
{ "linkId": "<packetId>", "packetId": "<packetId>", "from": "sender", "created": 1422312682124, "chatId": "sender", "companyId": "sender", "robotId": "addChat", "formId": "", "class":".addChat.sender", "type":"sys", "model": { "chatId": "<UpdatedChatId>", "actionUser": { "userId": "<userId>" }, "users": [ { "userId": "<userId>", "role":"<role>", "name":"<userName>" } ... ], "chatInfo": { "chatId": "<UpdatedChatId>", "chatName": "<ChatName>", "chatDesc": "<ChatDescription>", "chatPhoto": "<PhotoURL>", "p2p": "<Boolean(true/false)>", "companyId": "<companyId>", "type":"<type>", "members": [ { "userId": "<userId>", "role":"<role>" } ... ] }, "contactsInfo": [ { "contactId": "<contactId>", "userId": "<userId>", "isOwn": "true", "name": "<name>", "description": "<description>", "photo": "<photo>", "isCompany": "<isCompany>", "contactItemList": [{ "value": "<value>", "valueRaw": "<valueRaw>", "type": "<type>" }] }, ... ] } }
actionUser - инициатор действия.
contactsInfo - полная информация по всем участникам чата, которые отсутсвуют у получателя на момент после добавления
model.chatId - chatId изменяемого чата
chatInfo - (опционально) передаётся только юзеру, которого добавили в чат.
userId - userId пользователя или значение "me".
Оповещение о удалении участников из чата.
Получают все пользователи чата, которые участвуют в чате, в том числе и удаляемые.
Ответ (асинхронно)
{ "linkId": "<packetId>", "packetId": "<packetId>", "chatId": "sender", "from": "sender", "created": 1422312682124, "companyId": "sender", "robotId": "delChat", "formId": "", "class": ".delChat.sender", "type":"sys", "model": { "chatId": "<UpdatedChatId>", "actionUser": {"userId":"<userId_or_me>"}, "users": [ { "userId": "<userId>", "role":"<role>", "name":"<userName>" } ... ] } }
actionUser.id - инициатор действия, может быть userId или "me"(когда инциатором являестя пользователь который и получил этот пакет)
users - список пользователей которые были удалены.
userId - userId пользователя или значение "me".
На клиенте этот пакет можно преобразовать в сообщение типа: "Пользователь(Вы) удалил из чата (Вас и) Пользовтеля2, Пользователя 3".
Оповещение о выходе из чата пользователя.
Получают все пользователи чата, которые участвуют в чате, в том числе и выходящий.
Ответ (асинхронно)
{ "linkId": "<packetId>", "packetId": "<packetId>", "chatId": "sender", "from": "sender", "created": 1422312682124, "companyId": "sender", "robotId": "leaveChat", "formId": "", "class": ".leaveChat.sender", "type":"sys", "model": { "chatId": "<UpdatedChatId>", "actionUser": { "userId":"<userId_or_me>", "role":"<role>", "name":"<userName>" } }, }
actionUser.userId - инициатор действия, может быть userId или "me"(когда инциатором являестя пользователь который и получил этот пакет)
На клиенте этот пакет можно преобразовать в сообщение типа: "Пользователь(Вы) вышел(вышли) из чата".
Предложение: после получения этого пакета - обновленный список участников нужно получить по info.chatrobot.sender - так сделано из-за возможной гонки пакетов о изменении участников чата. Этот пакет не приходит для п2п чата - для п2п чата придет второму собеседнику сразу сообщение (меньше отвлекающих сообщений, меньше трафика).
Получение бара.
POST /get_bar?udid=&token=
{ "barId": "<barId>" }
Ответ 200 OK
{ "bar": {}, "code": 0 }
Для определённых клиентов на сервер отправляем аггрегированные данные о пользовательской активности (нажатия кнопок, переходы между экранами и т.п.). Данные следует отправлять не чаще чем раз в 10 минут.
POST /send в fs:
{ "chatId": "user+sender", "model": { "type":"<тип устройства, аналогично запросу reg>", "model":"<модель устройства, аналогично запросу reg>", "ver":"<версия клиентстого приложения, аналогично запросу reg>", "udid":<UDID>, "events":[ <массив json структур, представляющих собой события пользовательского интерфейса> ] }, "companyId": "sender", "robotId": "uiMonitoring", "formId": "" }
Открытие websocket соединения
ws://URL/websocket
Для начала работы сессии необходимо отправить пакет:
{ "class": "wsSession", "model":{ "udid":"<udid>", "token":"<token>"} }
Ответ в случае устаревшего токена:
{ "class": "wsChallenge", "model":{ "challenge":"<challenge>"} }
Список активных диалогов поддержки (приходит в вебсокете)
{ "class":".oDlgs.sender", "model":{ "dlgs":[{ "chatId": "<UpdatedChatId>", "companyId":"<companyId>", "created":<created>, "members": [ { "userId": "<userId>", "role":"user|operator", "name":"<name>", "photo":"<photo>" } ] }] }, "type":"ntf" }
Создание/изменение диалога (приходит в вебсокете)
{ "class":".oChatSet.sender", "model":{ "chatInfo":{ "chatId": "<UpdatedChatId>", "companyId":"<companyId>", "created":<created>, "members": [ { "userId": "<userId>", "role":"user|operator|company", "name":"<name>", "photo":"<photo>" } ], "type": "oper" } }, "type":"sys" }
Закрытие диалога (приходит в вебсокете)
{ "class":".oChatDel.sender", "model":{ "companyId":"<companyId>", "chatId":"<chatId>" }, "type":"sys" }
Установка статуса активности оператора (онлайн/офлайн) в разрезе компаний
{ "class": ".oStatusSet.sender", "model":{ "list": [ {"companyId":"<companyId>", "status":"online|offline"} ]}, "chatId":"user+sender" }
Ответ (асинхронно)
{ "class": ".oStatusSet.sender", "model":{ "list": [ {"companyId":"<companyId>", "status":"online|offline"} ]}, "type":"sys" }
Name | Value | Description |
---|---|---|
REST_STATUS_OK | 0 | Успех |
REST_STATUS_ACCESS_INVALID | 1 | token невалидный, получив challenge необходимо пересчитать |
REST_STATUS_MISSING_PARAM | 2 | отсутствует обязательный параметр(ы) |
REST_STATUS_UDID_INVALID | 3 | данный udid не зарегистрирован |
REST_STATUS_INTERNAL_ERROR | 4 | внутренняя ошибка сервера |
REST_STATUS_NEW_STREAM_REG | 5 | параллельно былы открыто соединение |
- | 6 | не используется |
- | 7 | не используется |
REST_STATUS_VER_NOT_SUPPORT | 8 | данная версия АПИ не актуальна, нужно обновить приложение |
REST_STATUS_CHAT_INVALID_DATA | 9 | переданы неверные данные для создания чата |
REST_STATUS_CHAT_NOT_FOUND | 10 | указанный чат не найден |