Описание
В данной статье рассмотрены необходимые методы и инструменты для интеграции с панелью оператора.
Это может быть необходимо для подключения функционала панели оператора в свой интерфейс (например, окно оператора в едином окне CRM)
Интеграция
Основные шаги интеграции
Авторизация
Чтобы использовать панель оператора, нужно получить авторизационный токен оператора.
Для этого можно воспользоваться методом авторизации:
Важно:
- У токена есть время жизни
- Рекомендуем устанавливать время жизни токена 24 часа и обновлять за 15 минут до окончания
- Также токен нужно обновлять при получении 403 ошибки от любого метода Twin
- Для обновления можно использовать тот же метод или метод обновления по рефреш токену
Управление оператором и работа с сообщениями
- Для управления оператором, получения информации о чатах, об очередях переписок можно воспользоваться методами из раздела "Управление оператором и очередями"
- Для работы с сообщениями нужно:
- Подключиться к соккет-серверу для получения событий от бота (подробнее в разделе "Live события")
- Использовать методы из раздела "Работа с сообщениями" для отправки, редактирования и удаления сообщений
Основные методы API
Полная документация по всем доступным эндпоинтам (раздел "Chat API")
Управление оператором и очередями
- /users/me - получить информацию о текущем оператора
- /timestamp - получить время сервера(полезно для таймеров, отсчетов, и понимания разницы)
- /users/me/activate - сменить статус текущего оператора — на возможность приема входящих сессий
- /users/me/pause - поставить оператора на паузу(прекратить получать входящие сессии)
- /sessions/${sessionId}/operators/${userId} - перевести сессию на конкретного пользователя
- /sessions/${sessionId}/names/${name} - переименовать сессию
- /sessions - получить список сессий(всех сессий, даже завершенных)
- /sessions/${sessionId}/operators/${userId} - перевести сессию на другого оператора
- /sessions/${sessionId}/groupoperators/${userId} - перевести сессию на группу операторов
- /users - получить список операторов
- /groups - получить список групп операторов
- /sessions/${sessionId} - delete: завершить сессию
- /clients/${clientId}/ban - заблокировать клиента
- /clients/${clientId}/unban - разблокировать клиента
Работа с сообщениями
- /sessions/${id}/messages - получить список сообщений по id сессии
- /clients/${id}/messages - получить список сообщений по id клиенту
- /sessions/${sessionId}/operators/messages - отправить сообщение в сессию
- /sessions/${sessionId}/operators/messages/${messageId} - put:редактировать сообщение
- /sessions/${sessionId}/operators/messages/${messageId} - delete:удалить сообщение
Live события
Подключение к соккет-серверу
Для работы с соккет-сервером используется инструмент Centrifuge.
Подробности о доступных SDK для работы с Centrifuge можно получить в официальной документации Centrifuge.
Эндпоинт для подключения: https://twin24.ai/centrifugo/connection/websocket
Пример на js
1. Создаем экземпляр класса Centrifuge, передаем ему URL сервера и создаем подключение:
const centrifuge = new Centrifuge(
`${protocol}://${window.location.host}/centrifugo/connection/websocket`,
{
data: {
application: 'notifications',
settings: { token: 'your_auth_token_here' },
},
},
)
2. Обрабатываем connection, и publication события, в самом publication получаем и реагируем на события
centrifuge.on('connected', () => {
// some logic when connected
})
centrifuge.on('publication', (publication) => {
const payload = publication.data
switch (payload.event) {
case 'chatMessageRead':
// handle chatMessageRead event
break
default:
console.warn('Unknown event type:', payload.event)
}
})
Список событий
События, которые получает оператор
- chatSessionStarted - Оператору пришла новая сессия чата (при этом не факт, что оператору, может быть просто в помощь)
- operatorNotFound - Сессия не нашла оператора и упала в помощь
- chatSessionAdded - Сессия пришла оператору
- chatMessageCreated - Оператору пришло новое сообщение в чате
- chatMessageEdited - Кто-то из операторов изменил сообщение в чате
- chatMessageRead - Оператору пришло сообщение, что клиент прочитал сообщение в чате
- chatSessionDeleted - Есть кейсы, когда сессия после отправки определенного сообщения уходит на бота - и тогда пропадает у оператора
- chatSessionSwitchedFromBotToOperator - Сессия была переключена с бота на оператора
- sessionClosedByClient - Клиент закрыл сессию
- operatorBlocked - Оператора заблокировали на платформе — требуется выкинуть оператора из кабинета
- chatUserExists - Кто-то зашел в текущего оператора. Текущий сеанс оператора нужно закрыть
- typing - пользователь печатает сообщение в чате
- operatorLoggedOut - сделать оператора офлайн
- clientOnline - клиент стал онлайн
- clientOffline - клиент стал офлайн
chatSessionStarted: {
event: 'chatSessionStarted',
data: {
id: string;
chatId: string;
clientId: string | null;
name: string;
markedAsSpam: boolean;
operatorId: string | number | null;
operatorType?: string;
channel: string;
botStatus?: string | null;
status: string;
startedAt: string;
clientOnlineAt?: string | null;
clientOfflineAt?: string | null;
lastMessageCreatedAt: string | null;
lastMessage?: Unknown | null;
clientExternalId?: string | null;
clientBanned?: boolean | null;
referer?: string;
clientIp?: string | null;
coordinates?: {
city?: string | null;
latitude?: number | null;
zip_code?: string | null;
longitude?: number | null;
time_zone?: string | null;
region_name?: string | null;
country_code?: string | null;
country_name?: string | null;
} | null;
unreadClientMessageCount?: number | null;
unreadClientMessageExists?: boolean | null;
messengerType?: string | null;
whatsappPhone?: string | null;
timerFirstAnswer?: number;
timerNextAnswers?: number;
lastOperatorMessage?: Unknown | null;
firstClientMessageAfterLastOperatorMessage?: Unknown | null;
operatorAssignedAt: string | null;
previousOperator?: {
id?: string | null;
name?: string | null;
} | null;
}
}
operatorNotFound: {
action: 'operatorNotFound';
data: {
botStatus: string; // например, 'HELP'
chatId: string;
operatorType: string;
sessionId: string;
status: string;
};
}
chatSessionAdded: {
action: 'chatSessionAdded';
data: {
id: string;
chatId: string;
clientId: string | null;
name: string;
markedAsSpam: boolean;
operatorId: string | number | null;
operatorType?: string;
channel: string;
botStatus?: string | null;
status: string;
startedAt: string;
clientOnlineAt?: string | null;
clientOfflineAt?: string | null;
lastMessageCreatedAt: string | null;
lastMessage?: Unknown | null;
clientExternalId?: string | null;
clientBanned?: boolean | null;
referer?: string;
clientIp?: string | null;
coordinates?: {
city?: string | null;
latitude?: number | null;
zip_code?: string | null;
longitude?: number | null;
time_zone?: string | null;
region_name?: string | null;
country_code?: string | null;
country_name?: string | null;
} | null;
unreadClientMessageCount?: number | null;
unreadClientMessageExists?: boolean | null;
messengerType?: string | null;
whatsappPhone?: string | null;
timerFirstAnswer?: number;
timerNextAnswers?: number;
lastOperatorMessage?: Unknown | null;
firstClientMessageAfterLastOperatorMessage?: Unknown | null;
operatorAssignedAt: string | null;
previousOperator?: {
id?: string | null;
name?: string | null;
} | null;
};
}
chatMessageCreated: {
action: 'chatMessageCreated';
data: {
id: string;
sessionId: string;
clientId: string | null;
authorId: string;
authorType: string;
authorName: string | null;
type: 'REGULAR' | 'TERMINAL';
body: string;
attachments: unknown[];
createdAt: string;
updatedAt?: string | null;
readAt?: string | null;
deletedAt?: string | null;
actions?: unknown[];
replyTo?: {
id: string;
authorType: string;
body: string;
attachments: unknown[];
authorName: string | null;
} | null;
history?: {
editedAt?: string | null;
}[];
}
replyToMessage?: {
id: string;
authorType: string;
body: string;
attachments: unknown[];
authorName: string | null;
} | null;
}
chatMessageEdited: {
action: 'chatMessageEdited';
data: {
body: string;
messageId: string;
attachments: unknown[];
};
}
chatMessageRead: {
action: 'chatMessageRead';
data: {
messageId: string;
};
}
chatSessionDeleted: {
action: 'chatSessionDeleted';
data: {
sessionId: string;
};
};
chatSessionSwitchedFromBotToOperator: {
action: 'chatSessionSwitchedFromBotToOperator';
data: {
operatorId: string;
operatorName: string;
sessionId: string;
};
};
sessionClosedByClient: {
action: 'sessionClosedByClient';
data: {
chatId: string;
sessionId: string;
};
}
operatorBlocked: {
action: 'operatorBlocked',
data: Unknown,
}
chatUserExists: {
action: 'chatUserExists';
data: Unknown;
}
typing: {
action: 'typing',
data: Unknown,
}
operatorLoggedOut: {
action: 'operatorLoggedOut,
data: Unknown,
}
clientOnline: {
action: 'clientOnline',
data: {
id: string;
}
}
clientOffline: {
action: 'clientOffline',
data: {
id: string;
}
}
События, которые отправляет оператор
- typing – отправляет оператор, когда печатает сообщение в чате