iOS
Swift-пакет Kavchat добавляет в приложение для iOS бота поддержки, который работает по сценарию, с компонентами SwiftUI и UIKit. Ответы предсказуемы и доступны даже без сети благодаря последней опубликованной версии. Требуется iOS 15 или новее.
В пакете два продукта: KavchatEngine, версия движка диалога на Swift без UIKit, и Kavchat, который включает сетевое взаимодействие, кеш на устройстве и интерфейс: KavchatChatView (SwiftUI), KavchatLauncher и KavchatViewController (UIKit).
Установка
Через Swift Package Manager в Xcode: выберите File > Add Package Dependencies и введите адрес репозитория:
https://bitbucket.org/maxsave/kavchat-ios.gitИли в файле Package.swift:
.package(url: "https://bitbucket.org/maxsave/kavchat-ios.git", from: "0.0.11"),
// ...
.product(name: "Kavchat", package: "kavchat-ios"),SDK доступен с открытым исходным кодом по лицензии MIT: bitbucket.org/maxsave/kavchat-ios.
Настройка
Вызовите configure один раз как можно раньше, например в init вашего App или в application(_:didFinishLaunchingWithOptions:):
import Kavchat
Kavchat.configure(publicKey: "pk_live_...") // the public key from the dashboard
// Optional:
// Kavchat.configure(publicKey: "pk_live_...", apiBase: "https://api.kavchat.com", locale: "he")Публичный ключ можно включать в приложение. Секретный ключ (sk_live_...) нельзя включать в него ни при каких обстоятельствах.
SwiftUI
Плавающая кнопка в углу, выбранном в панели управления, открывает чат в модальном окне (sheet):
ContentView()
.kavchatLauncher()Вы также можете разместить кнопку самостоятельно или встроить чат в свой экран:
KavchatLauncher()
KavchatChatView() // full chat, no close button
KavchatChatView(onClose: { showChat = false }) // with a close buttonОткрывать и закрывать окно плавающей кнопки из кода можно с помощью Kavchat.open() и Kavchat.close().
UIKit
Kavchat.present(from: self) // modal, with a close button
// or
let chat = KavchatViewController(showsCloseButton: false)
navigationController?.pushViewController(chat, animated: true)Токен идентификации
Для идентификации вошедшего в систему пользователя используйте JWT, подписанный вашим сервером с помощью секретного ключа (см. Идентификация пользователей). Токен передаётся в заголовке Authorization: Bearer <token>. Идентифицированный пользователь может видеть версии, доступные только тестовым пользователям, и отправлять форму обращения без электронной почты или телефона.
Kavchat.setUser(token: identityToken, name: "Dana") // after login
Kavchat.setUser(token: nil) // after logoutПри смене пользователя версия загружается заново и начинается новый диалог, поэтому переписка одного пользователя не отображается у другого.
Экраны приложения: onScreen
Кнопка типа screen в сценарии запрашивает открытие одного из экранов приложения. Сначала окно чата закрывается, чтобы экран был виден:
Kavchat.onScreen = { screen, targetId in
router.open(screen, id: targetId) // e.g. "orders", "42"
}Без обработчика такие кнопки ничего не делают. Кнопки link открывают только ссылки https и tel. Для аналитики Kavchat.onEvent передаёт события ready, unavailable, open, close, effect и ticket.
Список экранов в редакторе
Один раз объявите экраны, которые умеет открывать приложение, в Kavchat.configure(..., screens:). SDK самостоятельно отправит список в Kavchat, и редактор сценариев предложит эти экраны по названиям в выпадающем списке вместо поля для свободного ввода. Редактор также запросит идентификатор элемента, если он нужен экрану, и предупредит о кнопке, ведущей на необъявленный экран. Вводить список экранов вручную в панели управления не нужно.
Kavchat.configure(publicKey: "pk_live_...", screens: [
KavchatScreen(id: "orders", label: "My orders"),
KavchatScreen(id: "product", label: "Product page", needsTarget: true), // needs a targetId
])
// or later: Kavchat.registerScreens([...])idсодержит значение, которое передаётся вonScreen: латинские буквы, цифры,_,.и-, до 40 символов.labelсодержит название, которое видит администратор, до 60 символов. Можно указать до 100 экранов. Некорректные записи и повторяющиеся идентификаторы пропускаются.needsTarget: кнопка также передаёт идентификатор элемента (например, товара), который поступает вonScreenкакtargetId.- Список отправляется в фоне после загрузки версии, только если он изменился или раз в неделю. Ошибка отправки не отображается, повторная попытка выполняется при следующем запуске. Пользователь ничего не видит.
- Зарегистрированные экраны отображаются в панели управления в разделе «Бот», «Настройки», «Экраны приложения» вместе с платформами, сообщившими о каждом экране. Экран, удалённый из приложения, можно удалить и там.
Цвета
Цвета задаются в панели управления (primaryColor). Текст на фоне фирменного цвета отображается белым или почти чёрным в зависимости от контрастности по WCAG. Если цвет слишком светлый для текста на белом фоне, в ссылках и кнопках он заменяется на почти чёрный. Имя бота, подзаголовок, изображение и сторона размещения плавающей кнопки (start или end) тоже задаются в панели управления, поэтому их можно менять без обновления приложения.
Надпись «Работает на Kavchat by maxsave» со ссылкой на kavchat.com отображается на всех тарифах. На тарифе Премиум её можно скрыть в настройках бота.
Языки и RTL
- Язык интерфейса определяется значением
locale, переданным вconfigure. Если оно не передано, используется язык устройства при наличии перевода (he, en, ar, ru, es, fr, de, pt, it, tr), затем язык сценария и, наконец, английский. - Сопоставление со сценарием всегда выполняется на языке сценария с учётом пропускаемых частых слов и приставок в иврите и арабском.
- Для иврита и арабского
layoutDirectionвсего чата задаёт направление справа налево. Ничего не отражается вручную: если вы оборачиваете компоненты в свои контейнеры, используйтеleadingиtrailing.
Ответы ИИ (Премиум)
В приложении ничего настраивать не нужно. Когда в панели управления включены ответы ИИ с вашим собственным ключом провайдера ИИ, вопрос, на который не отвечает ни один сценарий, отправляется в Kavchat. Во время ожидания, до 20 секунд, чат показывает, что бот печатает. Ответ отображается обычным текстом с небольшой пометкой «Ответ ИИ» на языке интерфейса. Под ним размещаются кнопка связанной темы, если она есть, и кнопка «Связаться с командой».
Если ответа нет, запрос завершился ошибкой, занял слишком много времени или превысил лимит (10 ответов на диалог за каждые 15 минут), чат показывает обычное сообщение «Не удалось найти ответ». Вопрос по-прежнему попадает в отчёт о вопросах без ответа, а ответы ИИ сохраняются в истории диалога, как и любые другие сообщения.
Чат с оператором
В приложении ничего настраивать не нужно. Когда в панели управления включён чат с операторами, чат в приложении работает точно так же, как виджет на сайте.
- Эта возможность отображается только тогда, когда чат с операторами включён в опубликованной версии. Когда бот показывает кнопку «Связаться с командой», SDK проверяет наличие свободного оператора. Результат сохраняется на 30 секунд. Если оператор свободен, перед этой кнопкой появляется кнопка «Чат с оператором». Если нет, отображается только форма обращения. Над ней коротко объясняется причина: сейчас нерабочее время (с указанием времени возобновления работы) или все операторы заняты.
- Перед началом чата нужно заполнить короткую форму: имя, электронная почта или телефон, отдел (только если доступно больше одного отдела) и первое сообщение (необязательно). Гость должен указать электронную почту или телефон. Пользователю, идентифицированному с помощью токена, не нужно указывать ни то ни другое. Если к моменту отправки свободных операторов уже нет, открывается форма обращения с ранее введёнными данными.
- Во время ожидания отображаются время до преобразования чата в обращение и кнопка «Оставить сообщение вместо чата». Время ожидания задаётся в панели управления, по умолчанию это 2 минуты. Писать можно и во время ожидания, оператор увидит сообщения. Если за это время никто не освободится, чат сохранится как обычное обращение и отобразится его номер.
- Во время чата отображаются имя оператора, уведомление о его подключении (в том числе после перевода на другого оператора), индикатор набора текста и кнопка завершения чата. Сообщения могут содержать только обычный текст, до 2000 символов, без ссылок. Сообщение, которое ещё не дошло до сервера, отмечается надписью «Отправка...». Если отправка не удалась несколько раз, можно нажать на сообщение, чтобы повторить попытку. Повторная попытка не создаёт дубликат сообщения.
- После каждого обрыва соединения SDK немного ждёт, загружает пропущенные данные и подключается заново. Время ожидания постепенно увеличивается. Сообщения всегда отображаются по порядку и без дубликатов. Если постоянное соединение не удаётся установить (например, из-за корпоративного прокси), SDK временно переходит на периодические запросы к серверу.
- Когда приложение уходит в фон, соединение закрывается. При возвращении в приложение SDK загружает пропущенные данные и подключается заново. Открытый чат продолжается даже после закрытия и повторного запуска приложения, если прошло не больше 12 часов.
- В этой версии нет push-уведомлений. Сообщения приходят только при открытом приложении. Ответ, отправленный, пока приложение было в фоне, появляется сразу после возвращения в него.
- Данные доступа к чату хранятся только в памяти и в Keychain устройства. Они не сохраняются в
UserDefaults, адресе или журнале. Эти данные удаляются, когда чат завершается, превращается в обращение или истекает срок его действия, а также при смене пользователя черезsetUser.
С помощью Kavchat.shared.livePage можно указать оператору, с какого экрана пришёл пользователь.
Вопросы, условия и лиды
Настройки в приложении не нужны. Сценарий может запрашивать данные (имя, телефон, электронную почту, число или произвольный текст), выбирать дальнейшие действия по уже известной информации и отправлять лид.
- Подходящая клавиатура: когда бот ждёт ответа, для текстового поля открывается клавиатура для ввода телефона, электронной почты или чисел. При запросе имени клавиатура переключается на заглавную букву в начале каждого слова. Если ответ некорректен, бот выводит короткое сообщение на языке чата, а поле выделяется. Для необязательного вопроса появляется кнопка «Пропустить». Ввод слова «Отмена» на любом поддерживаемом языке позволяет выйти из вопроса.
- Телефон: для номера без
+используется страна по умолчанию для рабочего пространства, заданная в настройках панели управления. - Лид: шаг отправки лида показывает текст согласия с кнопками «Отправить» и «Нет, спасибо», а затем сообщение с подтверждением. Лид добавляется в очередь на устройстве и отправляется на сервер. Если нет сети или сервер недоступен, отправка повторяется, в том числе при следующем запуске и после
reload(). Сервер игнорирует дубликаты. - Предзаполнение: форма обращения и форма запроса чата с оператором заполняются собранными именем, электронной почтой и телефоном. Все собранные значения прикрепляются к обращению или запросу чата с оператором. Вопросы перед чатом с оператором (Премиум) задаются до подключения.
- Токен идентификации: при использовании
setUserполяname,emailиphoneиз токена заполняют ответы на соответствующие вопросы, и бот их пропускает. - Текущий экран: условия могут проверять текущий экран. Задайте
Kavchat.shared.livePage(например,"checkout").
Собранные значения являются персональными данными. Они остаются в диалоге, сохранённом на устройстве, и передаются только в лиды, обращения и чаты с оператором, но никогда не попадают в отчёты.
Работа без сети и кеширование
Последняя версия сохраняется в UserDefaults вместе со своим ETag и проверяется через If-None-Match (304) при каждом запуске. Если сети нет, используется сохранённая копия и отображается уведомление об этом. Если бот выключен, доступен только тестовым пользователям или квота исчерпана, ничего не отображается. Открытый диалог сохраняется до 30 минут бездействия, поэтому выход из чата или приложения не запускает его заново. Данные о ходе диалога отправляются через две секунды после последнего действия и сразу при переходе приложения в фон.