integrations:pyrus-app-chat-ios

Встраиваемый чат для мобильных приложений iOS

Программные средства разработки (SDK) Pyrus для iOS позволяют встроить удобный чат в ваше мобильное приложение.

Встроенный чат помогает получать мгновенную обратную связь от пользователей вашего мобильного приложения.

Когда клиент пишет в чат, ваша служба поддержки автоматически получает тикет в Pyrus. Специалист отвечает на заявку прямо в Pyrus, а клиенту приходит пуш-уведомление на телефон и ответ в чат вашего мобильного приложения. Это позволяет специалистам поддержки оперативно решать вопросы клиентов.

Основные возможности

  • Внешний вид чата настраивается, поэтому чат может выглядеть как часть вашего приложения.
  • Push-уведомления приходят клиенту, когда специалист отвечает на заявку.
  • История переписки сохраняется в чате.
  • Клиент может приложить к сообщению файлы, например фотографии, сделанные на камеру, или из галереи.

Встраиваемый чат для iOS поможет решить две задачи:

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

Вы можете использовать внешний вид чата по умолчанию или настроить его так, чтобы он выглядел как органичная часть вашего приложения. Также мы предусмотрели возможность отправки файлов в чат и подписку на уведомления о новых сообщениях.

Вы можете встроить такой чат в приложение на базе iOS с помощью програмных средств разработки (SDK) Pyrus. Вот пошаговая инструкция.

Получить идентификатор приложения (AppID)

Чтобы специалисты службы поддержки могли обрабатывать сообщения из чата в Pyrus, ваше приложение нужно подключить к форме, в которой ведётся работа с обращениями клиентов. Для начала работы вам понадобится аккаунт администратора в Pyrus с доступом к настройке формы, в которой обрабатываются обращения пользователей. Если у вас нет такого аккаунта, обратитесь к коллеге, у которого он есть.

  1. Включите интеграцию в Pyrus. Убедитесь, что администратор формы в Pyrus включил интеграцию с чатом в приложении.
  2. Получите AppID в настройке формы в Pyrus. Мы сгенерируем его автоматически, когда администратор формы включит интеграцию. AppID записан на странице настройки интеграции.

Подготовить проект

В файл Pods добавить:

pod 'PyrusServiceDesk', :git => ‘https://github.com/simplygoodsoftware/pyrusservicedesk.git’, :tag => ‘2.0.32’

Или скачайте framework и перейдите Targets » General. Перетащите framework в Embedded Binaries.

Чтобы пользователи могли прикреплять к сообщениям видео и фотографии, настройте доступ к камере и галерее. В файле Info.plist вашего приложения добавьте

“Privacy - Camera Usage Description”, “Privacy - Photo Library Usage Description”, “Privacy - Microphone Usage Description”.

Выбрать тип авторизации

Библиотека PyrusServiceDesk может работать в одном из двух режимов: с анонимной либо с внешней авторизацией.

Анонимный режим работы требует меньше затрат на внедрение. В этом случае данные чата привязаны к устройству. Пользователь на одном устройстве без использования явных логинов и паролей может писать в чат и видеть ответы операторов.

Основной недостаток анонимного режима в том, что если пользователь использует мобильное приложение на другом устройстве, то предыдущую переписку он не видит.

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

Обратите внимание, что анонимная и внешняя авторизация взаимно исключают друг друга. Если вы, например, переключаете библиотеку PyrusServiceDesk с анонимной авторизации на внешнюю, то старая переписка в чате, сделанная с анонимной авторизацией, пользователям мобильного приложения перестаёт быть доступна.

Как работает авторизационный сервис

В режиме с внешней авторизацией решение о том, есть ли у пользователя доступ к данным чата, бэкенд Pyrus не принимает самостоятельно, а спрашивает об этом специальный авторизационный сервис, который вам необходимо реализовать. Работает это так.

1. Пользователь любым способом авторизуется в мобильном приложении и после этого получает от вашего бэкенда пару (userID, securityKey). На этом этапе библиотека PyrusServiceDesk и бэкенд Pyrus не участвуют.

2. При инициализации библиотеки PyrusServiceDesk значения userID и securityKey передаются как параметры.

3. В дальнейшем при любом запросе в бэкенд Pyrus (например, при запросе истории переписки или при отправке комментария пользователя) библиотека PyrusServiceDesk автоматически передаёт в бэкенд Pyrus параметры (userID, securityKey).

3.1. Перед обработкой запроса по существу бэкенд Pyrus проверяет права доступа, для этого передает пару (userID, securityKey) в ваш авторизационный веб-сервис.

3.2. Авторизационный веб-сервис в коммуникации с вашим бэкендом проверяют, являются ли параметры (userID, securityKey) подлинными и передают результат проверки обратно в бэкенд Pyrus.

3.3. Если разрешение от авторизационного сервиса получено, бэкенд Pyrus выполняет запрос: отправляет историю переписки, сохраняет комментарий пользователя и т.п.

URL авторизационного сервиса следует указать в форме, к которой подключен мобильный чат. Для этого зайдите в настройки выбранной формы и в разделе Расширения выберите Чат в мобильном приложении.

На открывшейся странице введите URL в соответствующее поле.

Инициализировать чат

При старте приложения вызовите метод createWith() класса PyrusServiceDesk.

Параметры метода createWith():

  • appID, объект класса String. Идентификатор вашего приложения. Он записан в настройке формы, к которой подключён чат. Если у вас нет доступа, попросите администратора формы скопировать AppID, как описано в разделе «Получить идентификатор приложения (AppID)».

Данные параметры применяются только при внешней авторизации:

  • userID, объект класса String. Строка ID пользователя во внешней системе. Не должен меняться у одного и того же пользователя;
  • securityKey, объект класса String. Строка для аутентификации пользователя user_id во внешней системе. Может меняться у одного и того же пользователя, если внешняя система это позволяет.

Инициализация чата в анонимном режиме

Objective-C

Функция чата инициализируется в файле AppDelegate.m.

(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[PyrusServiceDesk createWith:@"your_app_id"];
return YES;
}

Swift

Функция чата инициализируется в файле AppDelegate.swift.

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        PyrusServiceDesk.createWith("your_app_id")
        return true
        }

Инициализация чата в режиме внешней авторизации

Objective-C:

 [PyrusServiceDesk createWith:@"your_app_id" userId:@"userId" securityKey:@"securityKey"];

Swift:

PyrusServiceDesk.createWith("your_app_id", userId: "userId", securityKey: "securityKey")
Если передать параметр userId = nil, то будет работать анонимная авторизация, привязанная к устройству, а не к пользователю.

Запустить пользовательский интерфейс

Чтобы запустить пользовательский интерфейс, вызовите метод start() класса PyrusServiceDesk. Параметры метода start(): viewController, объект класса UIViewController. Нужен для запуска пользовательского интерфейса.

Objective-c:

[PyrusServiceDesk startOn:self];

Swift:

PyrusServiceDesk.start(on: self)

Для настройки оформления чата передайте параметр configuration.

Параметры метода start():

  • viewController, объект класса UIViewController. Нужен для запуска пользовательского интерфейса.
  • configuration, объект класса ServiceDeskConfiguration. Используется для настройки оформления чата.
  • onStopCallback, объект класса OnStopCallback. Используется для подписки на закрытие чата.

Objective-c:

[PyrusServiceDesk startOn:self configuration:configuration onStopCallback:onStopCallback];

Swift:

PyrusServiceDesk.start(on: self, configuration:configuration, onStopCallback:onStopCallback)

Настроить оформление чата

Метод start(), используемый для запуска пользовательского интерфейса, содержит параметр configuration, объект класса ServiceDeskConfiguration.

ServiceDeskConfiguration может иметь параметры:

  • userName, объект класса String — имя пользователя (клиента поддержки), которое специалист службы поддержки увидит в Pyrus. Если пользователь авторизовался в приложении, вы можете передавать имя, почту и другие его данные в этот метод, чтобы оператор поддержки понимал, с кем общается, и быстрее решил вопрос.
  • chatTitle, объект класса String — заголовок окна с чатом.
  • welcomeMessage, объект класса String — приветственное сообщение, которое увидит пользователь, открыв чат.
  • themeColor, объект класса UIColor — цвет основных элементов интерфейса.
  • avatarForSupport, объект класса UIImage — аватар сотрудника службы поддержки.

Objective-C:

    	ServiceDeskConfiguration *configure = [[ServiceDeskConfiguration alloc] init];
    	configure.userName = @"Иван Петров";
   	configure.chatTitle = @"Поддержка ИмяОрганизации";
    	configure.welcomeMessage = @"Добрый день! Как я могу вам помочь?";
    	configure.themeColor = [UIColor redColor];
    	configure.avatarForSupport = [UIImage imageNamed:@"logo.png"];

Swift:

    	let configure : ServiceDeskConfiguration = ServiceDeskConfiguration.init()
	configure.userName = "Иван Петров"
   	configure.chatTitle = "Поддержка ИмяОрганизации"
	configure.welcomeMessage = "Добрый день! Как я могу вам помочь?"
   	configure.themeColor = .red
   	configure.avatarForSupport = UIImage.init(named: "logo.png")

Уведомления о новом сообщении в чате

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

Чтобы получать уведомления о новых сообщениях от сотрудника поддержки в чате, реализуйте интерфейс NewReplySubscriber и передайте реализацию интерфейса в метод subscribeToReplies() класса PyrusServiceDesk.

Если вы используете библиотеку PyrusSeviceDesk на нескольких устройствах, что возможно с внешней авторизацией, то мобильному приложению полезно знать, что все новые комментарии уже прочитаны на другом устройстве. В этом случае библиотека вызовет функцию onNewReply с параметром hasUnreadComments равным false. Если чат открыт, функция не будет вызвана, даже если придут новые сообщения.

@objc public protocol NewReplySubscriber{
    @objc func onNewReply(hasUnreadComments: Bool)
}

Objective-C:

В файле ViewController.h

@interface ViewController : UIViewController

В файле ViewController.m

-(void)viewWillAppear:(BOOL)animated{
...
    [PyrusServiceDesk subscribeToReplies:self];
}
-(void)viewDidDisappear:(BOOL)animated{
...
    [PyrusServiceDesk unsubscribeFromReplies:self];
}
-(void)onNewReply {
    NSLog(@"Есть непрочитанные сообщения");
}

Swift:

class ViewController: UIViewController, NewReplySubscriber{
 override func viewWillAppear(_ animated: Bool) {
...
        PyrusServiceDesk.subscribeToReplies(self)
    }
    override func viewWillDisappear(_ animated: Bool) {
	...
        PyrusServiceDesk.unsubscribeFromReplies(self)
    }
    func onNewReply(hasUnreadComments: Bool) {
        print("Есть непрочитанные сообщения")
    }
 }

Push-уведомления

Вы можете настроить отправку push-уведомлений, чтобы пользователь узнавал, когда специалист поддержки отправит комментарий в чат. Общая схема оповещения выглядит так: специалист отвечает на обращение клиента в Pyrus, из Pyrus с помощью вебхука ответ специалиста и push-токен отправляется на ваш сервер. Затем push-сервер Apple отправляет в приложение клиента push-уведомление о новом сообщении в чате.

Push-сервер Apple должен знать токен, уникальный для устройства и вашего приложения. При запуске ваше приложение связывается с push-сервером Apple и получает токен устройства, который записывается в Pyrus.

Чтобы подписаться на уведомления о новых сообщениях в чате, зарегистрируйте push-токен.

Objective-C:

[PyrusServiceDesk setPushToken:@”your_token” completion:^(NSError* error){
        if(error)
        {
            //error
            NSLog(@"error = %@",error.localizedDescription);
        }
        else{
            //success
        }
    }];

Swift:

PyrusServiceDesk.setPushToken(“your_token”, completion: {
            (error) in
            if error != nil{
                //error
                print(error!.localizedDescription)
			...
            }
            else{
                //success
...
            }
        })

Чтобы отписаться от push-уведомлений, нужно передать nil в функцию setPushToken:

Objective-C:

[PyrusServiceDesk setPushToken:nil completion:^(NSError* error){
        if(error)
        {
            //error
            NSLog(@"error = %@",error.localizedDescription);
        }
        else{
            //success
        }
    }];

Swift:

PyrusServiceDesk.setPushToken(nil, completion: {
            (error) in
            if error != nil{
                //error
                print(error!.localizedDescription)
			...
            }
            else{
                //success
...
            }
        })

На стороне сервера приложения нужно реализовать вебхук, который будет получать уведомления о новых комментариях в чате. И в настройке формы добавьте его URL.

При появлении нового ответа от поддержки на URL вебхука будет отправляться POST-запрос со следующим содержанием:

ticket_id — номер задачи, в которую добавлен комментарий.

token — идентификатор пользователя, включающий:

  • user_id — идентификатор пользователя, который передается при каждом запросе;
  • app_id — идентификатор мобильного приложения/веб-чата;
  • device_id — идентификатор устройства;
  • type — тип устройства: «iOS».

comment — информация о новом комментарии:

  • comment_id — номер нового комментария;
  • body — текст комментария;
  • is_inbound — всегда false, показывает, что комментарий исходящий, то есть ответ поддержки.

author — информация об авторе комментария:

  • name — имя автора;
  • avatar_id — идентификатор аватара автора;
  • avatar_color — цвет аватара автора. Используется, если avatar_id не заполнено.

created_at — дата и время создания комментария.

attachments — описание приложенных файлов:

  • id — идентификатор файла;
  • name — имя файла;
  • size — размер файла в байтах.

Уведомления о закрытии чата

Чтобы получать сообщения о закрытии окна чата, реализуйте интерфейс OnStopCallback и передайте реализацию интерфейса в метод start() класса PyrusServiceDesk.

@objc public protocol OnStopCallback{ 
    @objc func onStop() 
} 

Включаем оценку сервиса

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

Чтобы подключить оценку, зайдите в раздел Формы в левом меню и выберите форму, в которой работает PyrusServiceDesk.

На странице настройки формы в списке доступных расширений нажмите значок Оценка сервиса.

Установите переключатель в положение Включено.

Настройка меню отправки файлов в чат

По умолчанию пользователь может отправлять в чат фотографии, сделанные камерой, или выбирать изображения из галереи. Чтобы дать пользователю возможность отправлять другие типы файлов (например, техническую информацию, файлы конфигурации и т. д.), используйте метод registerFileChooser() класса PyrusServiceDesk.

PyrusServiceDesk.registerFileChooser (chooser: (FileChooser 
& UIViewController)?)

Chooser — реализация интерфейса FileChooser. Для того, чтобы перестать использовать настроенный FileChooser, в метод нужно передать null.

FileChooser имеет параметр label, в котором должна храниться строка с названием соответствующего пункта меню, например, «Прикрепить файл», и параметр chooserDelegate, протокол типа FileChooserDelegate.

Objective-C:

В CustomViewController.h:

@import PyrusServiceDesk;
@interface CustomViewController : UIViewController 
@end

В CustomViewController.m:

 
#import "CustomViewController.h"
@interface CustomViewController ()
@end
@implementation CustomViewController
@synthesize chooserDelegate;
@synthesize label; //label необходимо задать при инициализации CustomViewController
...
@end

Swift:

class CustomViewController: UIViewController, FileChooser{
    var chooserDelegate: FileChooserDelegate?
    var label: String = "Отправить логи"
    ...
}

CustomViewController может отсылать своему делегату (chooserDelegate):

1. Сообщение об отмене. Закрывает CustomViewController.

Objective-C:

[self.chooserDelegate didEndWithCancel];

Swift:

self.chooserDelegate?.didEndWithCancel()

2. Сообщение об успехе. Должно содержать данные и путь к ним. Закрывает CustomViewController и отправляет данные в виде вложения в чат.

Objective-C:

[self.chooserDelegate didEndWithSuccess:data url:url];

Swift:

self.chooserDelegate?.didEndWithSuccess(data, url: url)
//data — данные, которые необходимо отправить в чат, а url — путь к ним.

Закрытие окна

Для принудительного закрытия окна чата используйте метод stop():

Swift : PyrusServiceDesk.stop()
Objective-C: [PyrusServiceDesk stop];

Описание используемых типов и методов

Текущая версия 2.0.32 собрана с использованием Xcode 12.0.1, Swift 5.3.

PyrusServiceDesk

@objc public class PyrusServiceDesk: NSObject

Класс для создания чата в приложении.

createWith

@objc public func createWith(_ appId: String?)

Параметры

appID: Используется для всех запросов. Если appId не задан, PyrusServiceDesk Controller не будет создан.

createWith

@objc static public func createWith(_ clientId: String?, userId: String, securityKey: String)  

Параметры

userID: Cтрока ID пользователя во внешней системе. Не должен меняться у одного и того же пользователя.
securityKey: Cтрока, для аутентификации пользователя user_id во внешней системе. Может меняться у одного и того же пользователя, если внешняя система это позволяет.

registerFileChooser

@objc public static func registerFileChooser(_ chooser: (FileChooser & UIViewController)?)

Параметры

chooser UIViewController с расширением FileChooser. Запускает интерфейс для выбора файлов. Для отключения можно передавать null.

setPushToken

@objc public static func setPushToken(_ token:String?, completion: @escaping(Error?) -> Void)

Отправляет идентификатор устройства на сервер.

Параметры

completion Ошибка. Не nil, если всё прошло успешно. Чтобы разобраться, что случилось, проверьте error.localizedDescription.
token Строка с идентификатором устройства.

start

@objcpublicstaticfunc start(on viewController:UIViewController, onStopCallback: OnStopCallback? = nil)

Показать чат.

Параметры

viewController Представляет чат.
onStopCallback: Объект OnStopCallback или nil. Объект, который будет получать сообщения о том что чат был закрыт.

start

 @objcpublicstaticfunc start(on viewController:UIViewController, configuration:ServiceDeskConfiguration?, onStopCallback: OnStopCallback? = nil)

Показать чат.

Параметры

configuration onStopCallback: Объект OnStopCallback или nil. Объект, который будет получать сообщения о том, что чат был закрыт.
configuration Объект ServiceDeskConfiguration или nil. ServiceDeskConfiguration — это объект, который создаёт внешний вид интерфейса: основной цвет, приветственное сообщение, аватар специалиста поддержки, заголовок окна с чатом. Если nil, используется стандартная конфигурация.
viewController Представляет чат.

subscribeToReplies

@objc public static func subscribeToReplies(_ subscriber: NewReplySubscriber?)

Подписывает [subscriber] на уведомления о том, что в чате появились новые сообщения от поддержки.

unsubscribeFromReplies

@objc public static func unsubscribeFromReplies(_ subscriber: NewReplySubscriber?)

Отписывает [subscriber] от оповещений о новых сообщениях от поддержки в чате.

onAuthorizationFailed

Вызывается, когда параметры securityKey и userID не прошли проверку валидности

ServiceDeskConfiguration

@objc public class ServiceDeskConfiguration: NSObject

Класс для настройки оформления чата.

avatarForSupport

@objc public var avatarForSupport : UIImage?

Аватар специалиста поддержки. Отображается, если у специалиста поддержки не установлен аватар в Pyrus.

chatTitle

@objc public var chatTitle : String?

Содержит текст для заголовка чата. По умолчанию используется «Поддержка».

themeColor

@objc public var themeColor : UIColor?

Цвет чата. По умолчанию используется tintColor приложения; если и он не задан, то (red: 0, green: 0.4784313725, blue: 1, alpha: 1).

userName

@objc public var userName : String?

Имя пользователя (клиента поддержки), которое специалист службы поддержки увидит в Pyrus. По умолчанию используется «Гость» или "Guest" в зависимости от локали. Если пользователь авторизовался в приложении, вы можете передавать имя, почту и другие его данные в этот метод, чтобы оператор поддержки понимал, с кем общается, и быстрее решил вопрос.

welcomeMessage

@objc public var welcomeMessage : String?

Первое сообщение, которое пользователь видит в чате. Если текст не задан, чат будет отображаться без приветственного сообщения.

NewReplySubscriber

@objc public protocol NewReplySubscriber

Протокол для отправки оповещений о новых сообщениях.

onNewReply

@objc func onNewReply(hasUnreadComments: Bool)

Отправлено новое сообщение.

FileChooser

@objc public protocol FileChooser

Расширение для передачи файлов.

chooserDelegate

@objc var chooserDelegate : FileChooserDelegate? { get set }

Отправляет статусные сообщения о завершении.

label

@objc var label : String { get set}

Название пункта меню, которое видит пользователь.

FileChooserDelegate

@objc public protocol FileChooserDelegate

Отправляет статусные сообщения о завершении.

didEndWithCancel

@objc func didEndWithCancel()

Отправляет статус «Отменено».

didEndWithSuccess

@objc func didEndWithSuccess(_ data : Data?, url : URL?)

Отправляет статус «Успешно».

Параметры

data Данные вложения, которые нужно отправить в чат. Если пустое или nil, отобразится предупреждение об ошибке.
url Путь к файлу.

OnStopCallback

@objc public protocol OnStopCallback 

Протокол для отправки оповещений о закрытии чата.

onStop

@objc func onStop()

Окно чата PyrusServiceDesk было закрыто.

Авторизационный веб-сервис

Получает вызов HTTP POST c параметрами:

  • app_id: строка, создается Pyrus в настройках мобильного чата;
  • user_id: строка до 100 символов, ID пользователя во внешней системе. Никогда не должен меняться. Не может совпадать у разных пользователей, в том числе бывших;
  • security_key: строка до 100 символов, для аутентификации пользователя user_id во внешней системе. Логика формирования и использования security_key полностью отдается на ваше усмотрение. Не рекомендуем использовать без хеширования с солью пароли, секретные ключи и другие параметры, которые позволяют авторизоваться в мобильном приложении или дают доступ к каким-либо другим вашим системам.

Ожидаемый ответ:

  • в случае успешной авторизации: HTTP 200 OK;
  • в случае некорректно сформированного запроса (неправильные поля либо security_key неверного для вашей системы формата): HTTP 400 Bad Request;
  • в случае неуспешной авторизации: HTTP 403 Forbidden.

Была ли эта статья полезной?

Да, спасибо! Нет, остался вопрос