Using the Pyrus SDK for iOS, you can embed chat in your mobile app. With chat for iOS applications, your users can contact support from within the app and get help. Your support specialists will process tickets in Pyrus even if these messages come from a smartphone messenger app.
You can use the default chat or customize it for your app. You can also receive files and subscribe the userclient to push notifications about new messages.
This guide will help developers embed Pyrus chat into their app.
First, connect your app to the Pyrus form where support team processes client requests. You need an administrator account in Pyrus with access to the form settings in order to get started. If you aren’t a form administrator, ask a colleague who has this access.
1. Go to the service ticket form configuration page and find Integrations. Click Set Up next to Mobile App Chat.
2. Copy App ID from the Credentials section.
Add to Pods file::
pod 'PyrusServiceDesk', :git => ‘https://github.com/simplygoodsoftware/pyrusservicedesk.git’, :tag => ‘1.2.0’Or download the framework and open Targets » General and move the framework to the Embedded Binaries.
To let users attach files to messages, you must configure access to the camera and gallery. In the file Info.plist, add
“Privacy - Camera Usage Description”, “Privacy - Photo Library Usage Description”, “Privacy - Microphone Usage Description”.
The PyrusMobileChat library can be authorized in one of two ways: anonymously, or externally.
Anonymous authorization makes implementation easier, as the chat is tied to a device. On an authorized device a user can participate in the chat without entering any login info.
The biggest disadvantage of anonymous authorization is that if you use the mobile app on another device, you cannot see the previous chat.
If you want the chat history to be accessible to the same user on multiple devices, you have to set up external authorization. To do this, you have to turn on a web service that tells the system a user has access to the chat.
Please note that anonymous and external authorization are mutually exclusive. If you switch the PyrusMobileChat library from anonymous to external, the previous chat, which was conducted in anonymous authorization mode, will become invisible to mobile app users.
In external authorization mode the Pyrus backend does not decide on its own whether a user has access to a chat; it asks a special authorization service, which you have to turn on. Here’s how this works:
1. The user logs in on a mobile app, and then receives a pair (userID, securityKey) from your backend. The PyrusMobileChat library and the Pyrus backend do not participate at this stage.
2. When initializing the PyrusMobileChat library, the userID and securityKey definitions are given as parameters.
3. From then on, whenever any request is sent to the backend (for example, a request for a chat history, or when a user comment is being sent), the PyrusMobileChat library automatically also sends the Pyrus backend these parameters (userID, securityKey).
3.1. Before processing the request, the Pyrus backend verifies your access rights. That’s what it sends the pair (userID, securityKey) to your authorization web service for.
3.2. The authorization web service and your backend communicate to authenticate the parameters (userID, securityKey), and they send the results of that check back to the Pyrus backend.
3.3. Upon receipt of confirmation from the authorization service, the Pyrus backend processes the request: it sends the chat history, saves the user’s comments, etc.
The authorization service URL has to be indicated in the form the mobile chat is connected to. To make sure it is, go into the settings of the selected form, and, in the Extensions section, select Mobile app chat.
Then, on the page that opens, enter the URL in the appropriate field.
When starting the app, invoke the createWith() () method of the PyrusServiceDesk class. The parameters of the createWith() () method:
These parameters are used only for external authorization.
Objective-C
Initialize the chat function in the AppDelegate.m file.
(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { PyrusServiceDesk *psd = [[PyrusServiceDesk alloc] createWith:@"your_app_id"]; return YES; }
Swift
Initialize the chat function in the AppDelegate.swift file.
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")
If you send the parameter userId=nil, then anonymous authorization turns on. This is connected to a device, not to a user.
To launch the user interface, invoke the start() method of the PyrusServiceDesk class. The start() method parameters:
Objective-c:
[PyrusServiceDesk startOn:self];
Swift:
PyrusServiceDesk.start(on: self)
To customize the chat appearance, pass the configuration parameter. Parameters of the start() method:
Objective-c:
[PyrusServiceDesk startOn:self configuration:configuration];
Swift:
PyrusServiceDesk.start(on: self, configuration:configuration)
The start() method is used for starting the chat interface. It contains the configuration parameter, an object of the ServiceDeskConfiguration class. Parameters of the ServiceDeskConfiguration class:
Objective-C:
ServiceDeskConfiguration *configure = [[ServiceDeskConfiguration alloc] createWith]; configure.userName = @"John Smith"; configure.chatTitle = @"Support CompanyName"; configure.welcomeMessage = @"Hello! How can I help you?"; configure.themeColor = [UIColor redColor]; configure.avatarForSupport = [UIImage imageNamed:@"logo.png"];
Swift:
let configure : ServiceDeskConfiguration = ServiceDeskConfiguration.createWith() configure.userName = "John Smith" configure.chatTitle = "Support CompanyName" configure.welcomeMessage = "Hello! How can I help you?" configure.themeColor = .red configure.avatarForSupport = UIImage.createWith(named: "logo.png")
You can use push notifications to inform users about new messages in the chat. This is the alternative option. It’s easier to implement, but notifications will be delayed and you won’t see the content of a new comment. Enable push notifications
To get notifications about new messages from a support specialist, implement the NewReplySubscriber interface and pass the implementation to the subscribeToReplies() of the PyrusServiceDesk class.
If you're using the Pyrus Mobile Chat library on multiple devices, which you can do in external authorization mode, it's useful for your mobile app to know which new comments have already been read on another device. In this case, the library calls the onNewReply function with a hasUnreadComments parameter equal to false. If the chat is open, the function will not be called even if new comments appear.
@objc public protocol NewReplySubscriber{ @objc func onNewReply(hasUnreadComments: Bool) }
Objective-C:
In the ViewController.h file
@interface ViewController : UIViewController
In the ViewController.m file
-(void)viewWillAppear:(BOOL)animated{ ... [PyrusServiceDesk subscribeToReplies:self]; } -(void)viewDidDisappear:(BOOL)animated{ ... [PyrusServiceDesk unsubscribeFromReplies:self]; } -(void)onNewReply { NSLog(@"New unread messages"); }
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("New unread messages.") } }
You can use push notifications to inform the user about new messages in the chat. Here’s how it works:
Your app communicates with APNs when launching to receive its device token, which you then forward to your provider server. Your server includes that token with every notifications it sends.
To subscribe a user to notifications about new messages, register a push token.
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 ... } })
On the application server side, you should implement a webhook that will receive notifications about new messages in the in-app chat. Add the webhook URL in the form settings in Pyrus.
When there is a new message from the support team, a POST request will be sent to the webhook URL. It contains:
ticket_id — the number of the task to which the comment is added.
token — user's identificator including:
comment — information about the new comment:
author — information about the author of the comment:
created_at — date and time the comment was created.
attachments — description of the attached files:
For an enhanced support experience your users can send files without having to leave the chat flow. By default, users can attach photos taken with the device camera or select images from the gallery. To add other file types like configuration files, use the registerFileChooser() method of the PyrusServeDesk class.
PyrusServiceDesk.registerFileChooser (chooser: (FileChooser & UIViewController)?)
Chooser is an implementation of the FileChooser interface. To stop using the configured FileChooser, pass null to the method.
FileChooser has a label parameter where a string with the name of the corresponding menu option is stored (for example, Attach file) and a chooserDelegate parameter which is a protocol of the FileChooserDelegate type.
Objective-C:
In the CustomViewController.h:
@import PyrusServiceDesk; @interface CustomViewController : UIViewController@end
In the CustomViewController.m:
#import "CustomViewController.h" @interface CustomViewController () @end @implementation CustomViewController @synthesize chooserDelegate; @synthesize label; //The label must be specified when initializing the CustomViewController ... @end
Swift:
class CustomViewController: UIViewController, FileChooser{ var chooserDelegate: FileChooserDelegate? var label: String = "Send logs" ... }
CustomViewController can pass (chooserDelegate) to its delegate:
1. Cancellation message. Closes CustomViewController.
Objective-C:
[self.chooserDelegate didEndWithCancel];
Swift:
self.chooserDelegate?.didEndWithCancel()
2. Success message. It must contain the data and the path to it. Closes CustomViewController and sends data as an attachment to the chat.
Objective-C:
[self.chooserDelegate didEndWithSuccess:data url:url];
Swift:
self.chooserDelegate?.didEndWithSuccess(data, url: url)
The current version is 2.0.32 built using Xcode 12.0.1, Swift 5.3.
@objc public class PyrusServiceDesk: NSObject
A class for creating a chat in your app.
@objc public createWith(_ appId: String?)
Parameters
appID | For every query. If appID isn’t set, PyrusServiceDesk Controller won’t be created. |
@ @objc static public func createWith(_ clientId: String?, userId: String, securityKey: String)pre>Parameters
userID: | User ID line in the external system. Must stay the same for single user. |
securityKey: | The user identification line user_id in the external system. Can change for single user, if the system allows it. |
@objc public static func registerFileChooser(_ chooser: (FileChooser & UIViewController)?)
Parameters
chooser | UIViewController with a FileChooser extension. This starts the interface for selecting files. Send null to disable it. |
@objc public static func setPushToken(_ token:String?, completion: @escaping(Error?) -> Void)
Sends device ID to the server.
Parameters
completion | Error. Not nil, if success. To find out what went wrong, check error.localizedDescription. |
token | A string with a device identifier. |
@objc public static func start(on viewController:UIViewController)
Shows the chat.
Parameters
viewController | Presents a chat. |
@objc public static func start(on viewController:UIViewController, configuration:ServiceDeskConfiguration?)
Shows the chat.
Parameters
configuration | The ServiceDeskConfiguration object or nil. ServiceDeskConfiguration is an object that creates the user interface, including main color, welcome message, support avatar, and chat window title. If nil, the default configuration will be used. |
viewController | Presents the chat. |
@objc public static func subscribeToReplies(_ subscriber: NewReplySubscriber?)
This subscribes [subscriber] to notifications about new messages in the chat.
@objc public static func unsubscribeFromReplies(_ subscriber: NewReplySubscriber?)
This unsubscribes [subscriber] from notifications about new messages.
Is entered when the securityKey and userID parameters have failed the authentication.
@objc public class ServiceDeskConfiguration: NSObject
A class for setting up chat UI.
@objc public var avatarForSupport : UIImage?
A support specialist’s avatar. This appears when there is no avatar in a support specialist’s Pyrus profile.
@objc public var chatTitle : String?
Contains the text for a chat title. By default, it’s “Support.”
@objc public var themeColor : UIColor?
Chat window color. By default, the app tintColor is used. If it isn’t set, then (red: 0, green: 0.4784313725, blue: 1, alpha: 1) is used.
@objc public var userName : String?
The username (client’s name) that a support specialist sees in ticket in Pyrus. This uses “Guest” by default. If a user is logged into the app, you can pass that user’s name, email address, and other info to this method.
@objc public var welcomeMessage : String?
The first message that the user sees in the chat. If not specified, the chat will be displayed without a welcome message.
@objc public protocol NewReplySubscriber
Protocol for sending notifications about new messages.
@objc func onNewReply(hasUnreadComments: Bool)
A new message is sent.
@objc public protocol FileChooser
File transfer extension.
@objc var chooserDelegate : FileChooserDelegate? { get set }
Sends status messages when the process is complete.
@objc var label : String { get set}
The name of the menu option.
@objc public protocol FileChooserDelegate
Sends status messages when the process is complete.
@objc func didEndWithCancel()
Sends the “Canceled” status.
@objc func didEndWithSuccess(_ data : Data?, url : URL?)
Sends the “Success” status.
Parameters
data | The attachment that will be sent to the chat. If empty or nil, an error message will be displayed. |
url | Path to the file. |
Receives the command HTTP POST with the parameters:
The expected response: