Mobile chat for iOS
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.
Get an App ID
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.
Go to the service ticket form configuration page and find Integrations. Click Set Up next to Mobile App Chat.
Copy App ID from the Credentials section.
Prepare the project
Add to Pods file::
pod 'PyrusServiceDesk', :git => ‘https://github.com/simplygoodsoftware/pyrusservicedesk.git’, :tag => ‘3.0.38’
Or download the framework and open Targets >> General and move the framework to the Embedded Binaries.
Get permissions to access phone camera and gallery
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”.
Choose the type of authorization
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.
How the authorization service works
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:
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.
When initializing the PyrusMobileChat library, the userID and securityKey definitions are given as parameters.
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).
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.
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.
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.
Initialize chat
When starting the app, invoke the createWith() () method of the PyrusServiceDesk class. The parameters of the createWith() () method:
appID, an object of the String class. It’s your application ID from the settings of the connected form in Pyrus. If you aren’t an administrator of the form, ask a colleague who has administrator rights to copy the AppID as described in the Get an App ID section.
These parameters are used only for external authorization.
userID, a String class object. User ID line in the external system. Must stay the same for single user.
securityKey, a String class object. The user identification line user_id in the external system. Can change for single user, if the system allows it.
Initializing the chat in anonymous authorization mode
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 }
Initialization of chat in external authorization mode
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.
Launch the user interface
To launch the user interface, invoke the start() method of the PyrusServiceDesk class. The start() method parameters:
- viewController, the object of the UIViewController class.
Objective-c:
[PyrusServiceDesk startOn:self];
Swift:
PyrusServiceDesk.start(on: self)
To customize the chat appearance, pass the configuration parameter. Parameters of the start() method:
- viewController, an object of the UIViewController class. It’s used for launching chat UI.
- configuration, an object of the ServiceDeskConfiguration class. It’s used for configuring chat UI.
Objective-c:
[PyrusServiceDesk startOn:self configuration:configuration];
Swift:
PyrusServiceDesk.start(on: self, configuration:configuration)
Customize the chat
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:
- userName, an object of the String class — the username that a support specialist will see in a Pyrus ticket. If a user has logged into the app, you can pass his or her name, email, and other info to this method. It will help your support specialist understand who he or she is talking to and resolve the ticket more quickly.
- chatTitle, an object of the String class — the title of the chat window.
- welcomeMessage, an object of the String class — a welcome message that the user sees when opening a chat.
- themeColor, an object of the UIColor class — the color of the main elements of the chat interface.
- avatarForSupport, an object of the UIImage class — a support manager’s avatar.
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")
Notifications about new messages
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.
@objcpublicprotocol NewReplySubscriber{ @objcfunc onNewReply( hasUnreadComments: Bool, lastCommentText: String?, lastCommentAttachmentsCount: Int, lastCommentAttachments: [String]?, utcTime: Double ) }
Objective-C:
In the ViewController.h file
@interface ViewController : UIViewController<NewReplySubscriber>
In the ViewController.m file
-(void)onNewReplyWithHasUnreadComments:(BOOL)hasUnreadComments lastCommentText:(NSString *)lastCommentText lastCommentAttachmentsCount:(NSInteger)lastCommentAttachmentsCount lastCommentAttachments:(NSArray<NSString *> *)lastCommentAttachments utcTime:(double)utcTime { print("New unread messages"") }
Swift:
func onNewReply(hasUnreadComments: Bool, lastCommentText: String?, lastCommentAttachmentsCount: Int, lastCommentAttachments: [String]?, utcTime: Double) { print("New unread messages ")
Enabling push notifications
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.
You can call setPushToken no more than once every five minutes for the one user, and no more than 5 times every five minutes in total. 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 identifier including:
- user_id — user ID, which is passed with each request
- app_id — mobile application / web chat identifier
- device_id — device identifier
- type — device type: "iOS"
comment — information about the new comment:
- comment_id — number of the new comment
- body — comment text
- is_inbound — always false, shows that the comment is from the support team
author — information about the author of the comment:
- name — author's name
- avatar_id — author's avatar identifier
- avatar_color — the color of the author's avatar. Used if avatar_id is not specified
created_at — date and time the comment was created.
attachments — description of the attached files:
- id — file identifier
- name — file name
- size — file size in bytes
Setting up the chat menu
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 <FileChooser> @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:
Cancellation message. Closes CustomViewController.
Objective-C:
[self.chooserDelegate didEndWithCancel];
Swift:
self.chooserDelegate?.didEndWithCancel()
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)
Types and methods description
The current version is 3.0.38 built using Xcode 15.4, Swift 5.10.
PyrusServiceDesk
@objc public class PyrusServiceDesk: NSObject
A class for creating a chat in your app.
createWith()
@objc public createWith(_ appId: String?)
Parameters
appID | For every query. If appID isn’t set, PyrusServiceDesk Controller won’t be created. |
createWith()
@ @objc static public func createWith(_ clientId: String?, userId: String, securityKey: String)
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. |
registerFileChooser
@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. |
setPushToken
@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. |
start
@objc public static func start(on viewController:UIViewController)
Shows the chat.
Parameters
viewController | Presents a chat. |
start
@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. |
subscribeToReplies
@objc public static func subscribeToReplies(_ subscriber: NewReplySubscriber?)
This subscribes [subscriber] to notifications about new messages in the chat.
unsubscribeFromReplies
@objc public static func unsubscribeFromReplies(_ subscriber: NewReplySubscriber?)
This unsubscribes [subscriber] from notifications about new messages.
onAuthorizationFailed
Is entered when the securityKey and userID parameters have failed the authentication.
ServiceDeskConfiguration
@objc public class ServiceDeskConfiguration: NSObject
A class for setting up chat UI.
avatarForSupport
@objc public var avatarForSupport : UIImage?
A support specialist’s avatar. This appears when there is no avatar in a support specialist’s Pyrus profile.
chatTitle
@objc public var chatTitle : String?
Contains the text for a chat title. By default, it’s “Support.”
themeColor
@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.
userName
@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.
welcomeMessage
@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.
NewReplySubscriber
@objc public protocol NewReplySubscriber
Protocol for sending notifications about new messages.
onNewReply
@objcfunc onNewReply( hasUnreadComments: Bool, lastCommentText: String?, lastCommentAttachmentsCount: Int, lastCommentAttachments: [String]?, utcTime: Double )
A new message is sent.
Parameters
hasUnreadComments: | Is there a new messages in chat. |
lastCommentText: | The text of last unread message. Returns nil if there is no new messages or text in it. |
lastCommentAttachmentsCount: | Total number of attachments in the message. Returns nil if there is no new messages or attachments in it. |
lastCommentAttachments: | The list of attachments' names. Returns nil if there is no new messages, or attachments in it. |
utcTime: | The date of last unread message in(utc). Returns nil if there is no new messages. |
FileChooser
@objc public protocol FileChooser
File transfer extension.
chooserDelegate
@objc var chooserDelegate : FileChooserDelegate? { get set }
Sends status messages when the process is complete.
label
@objc var label : String { get set}
The name of the menu option.
FileChooserDelegate
@objc public protocol FileChooserDelegate
Sends status messages when the process is complete.
didEndWithCancel
@objc func didEndWithCancel()
Sends the “Canceled” status.
The authorization web service
Receives the command HTTP POST with the parameters:
- app_id: this line is created in Pyrus in the mobile chat settings;
- user_id: this line of up to 100 symbols is the user ID in the external system. This value must never change, and cannot be the same for different users, including former ones;
- security_key: this line of up to 100 symbols is for authenticating the user’s user_id in the external system. In this mode, the logic of the formation and use of the security_key is entirely up to you. We do not recommend using this mode without hash coding the passwords, secret keys, and other parameters that grant users access to any of your systems, or to get authorized on a mobile app.
The expected response:
- if authorization is successful: HTTP 200 OK;
- if the request was formed incorrectly (the wrong fields were filled in, or the security_key is in the wrong format for your system): HTTP 400 Bad Request;
- if authorization fails: HTTP 403 Forbidden.