====== CEC iOS SDK API ====== * [[#Messages|Messages]] * [[#Conversations|Conversations]] * [[#Notes|Notes]] * [[#real-time_audiovideo_calling|Real-Time Audio and Video]] ===== Messages ===== ==== Send Text Message ==== // Create a text message body EMTextMessageBody *body = [[EMTextMessageBody alloc] initWithText:@"content"]; HMessage *message = [[HMessage alloc] initWithConversationID:<#conversationId#> from:<#Hyphenate username#> to:<#IM service ID#> body:body]; [[HChatClient sharedClient].chat sendMessage:message progress:^(int progress) { // progress of sending the message } completion:^(HMessage *aMessage, HError *aError) { // message sent. It is successful if aError is empty }]; ==== Send Voice Message ==== EMVoiceMessageBody *body = [[EMVoiceMessageBody alloc] initWithLocalPath:"local path" displayName:@"diplay name"]; body.duration = @"length of time"; HMessage *message = [[HMessage alloc] initWithConversationID:<#conversationId#> from:<#Hyphenate username#> to:<#IM service ID#> body:body]; [[HChatClient sharedClient].chat sendMessage:message progress:^(int progress) { // progress of sending the message } completion:^(HMessage *aMessage, HError *aError) { // message sent. It is successful if aError is empty }]; ==== Send Picture Message ==== EMImageMessageBody *body = [[EMImageMessageBody alloc] initWithData:<#imagedata#> displayName:<#image name#>]; HMessage *message = [[HMessage alloc] initWithConversationID:<#conversationId#> from:<#Hyphenate username#> to:<#IM service ID#> body:body]; [[HChatClient sharedClient].chat sendMessage:message progress:^(int progress) { // progress of sending the message } completion:^(HMessage *aMessage, HError *aError) { // message sent. It is successful if aError is empty }]; ==== Send Location Message ==== EMImageMessageBody *body = [[EMImageMessageBody alloc] initWithData:<#imagedata#> displayName:<#image name#>]; HMessage *message = [[HMessage alloc] initWithConversationID:<#conversationId#> from:<#Hyphenate username#> to:<#IM service ID#> body:body]; [[HChatClient sharedClient].chat sendMessage:message progress:^(int progress) { // progress of sending the message } completion:^(HMessage *aMessage, HError *aError) { // message sent. It is successful if aError is empty }]; Send Transparent Message ==== // used in "chat with agent" scenarios. The parameter is the specific action EMCmdMessageBody *body = [[EMCmdMessageBody alloc] initWithAction:@"TransferToKf"]; HMessage *message = [[HMessage alloc] initWithConversationID:<#conversationId#> from:<#Hyphenate username#> to:<#IM service ID#> body:body]; // The parameter is type. The id and serviceSessionId in the parameters are passed by the server ControlType *type = [[ControlType alloc] initWithValue:[weichat valueForKey:@"ctrlType"] ]; ControlArguments *arguments = [ControlArguments new]; arguments.identity = [ctrlArgs valueForKey:@"id"]; arguments.sessionId = [ctrlArgs valueForKey:@"serviceSessionId"]; ControlMessage *hcont = [ControlMessage new]; hcont.type = type; // assign when needed hcont.arguments = arguments; // assign when needed [message addCompositeContent:hcont]; [[HChatClient sharedClient].chat sendMessage:message progress:^(int progress) { // progress of sending the message } completion:^(HMessage *aMessage, HError *aError) { // message sent. It is successful if aError is empty }]; ==== Send Extended Message ==== Extended messages are used to implement certain functions, such as specifying a team, specifying an agent, passing a customer profile. message (HMessage *); NSDictionary *dic = @{@"key1":@"value1", @"key2":@"value2"}; [message addAttributeDictionary:dic]; [[HChatClient sharedClient].chat sendMessage:message progress:^(int progress) { // progress of sending the message } completion:^(HMessage *aMessage, HError *aError) { // message sent. It is successful if aError is empty }]; ==== Pass Customer Profile ==== When you need to pass customer attributes (nickname, phone, etc.) to Hyphenate Customer Engagement Cloud, you need to put the attributes in an extended message. Example of an extended text message: // these attributes can be default HVisitorInfo *visitor = [[HVisitorInfo alloc] init]; visitor.name = @"Jane Doe"; visitor.qq = @"12345678"; visitor.phone = @"13636362637"; visitor.companyName = @"Hyphenate"; visitor.nickName = @"Jane"; visitor.email = @"abv@hyphenate.io"; visitor.desc = @"Hyphenate Customer Engagement Cloud"; HMessage *message = [....];// construct the message [message addContent:visitor]; // pass the customer profile [[HChatClient sharedClient].chat sendMessage:message progress:^(int progress) { // progress of sending the message } completion:^(HMessage *aMessage, HError *aError) { // message sent. It is successful if aError is empty }]; ==== Send Track Message ==== EMTextMessageBody *body = [[EMTextMessageBody alloc] initWithText:@""]; HMessage *message = [[HMessage alloc] initWithConversationID:<#conversationId#> from:<#Hyphenate username#> to:<#IM service ID#> body:body]; VisitorTrack *vst = [VisitorTrack new]; vst.title = title; // title vst.price = price; // price vst.desc = desc;// description vst.imageUrl = imageUrl; // image URL vst.itemUrl = itemUrl; // Link to jump to [message addContent:vt]; [[HChatClient sharedClient].chat sendMessage:message progress:^(int progress) { // progress of sending the message } completion:^(HMessage *aMessage, HError *aError) { // message sent. It is successful if aError is empty }]; ==== Send Order Message ==== EMTextMessageBody *body = [[EMTextMessageBody alloc] initWithText:@""]; HMessage *message = [[HMessage alloc] initWithConversationID:<#conversationId#> from:<#Hyphenate username#> to:<#IM service ID#> body:body]; OrderInfo *ord = [OrderInfo new]; ord.title = title; ord.orderTitle = orderTitle; ord.price = price; ord.desc = desc; ord.imageUrl = imageUrl; ord.itemUrl = itemUrl; [message addContent:ord]; [[HChatClient sharedClient].chat sendMessage:message progress:^(int progress) { // progress of sending the message } completion:^(HMessage *aMessage, HError *aError) { // message sent. It is successful if aError is empty }]; ==== Specify Agent ==== Specify an agent to serve conversations. The agent account is the agent's login email address. HMessage *message = [....];// construct a message [message addContent:[[HAgentIdentityInfo alloc] initWithValue:@"Agent account"]]; ==== Specify Team ==== Specify a team to serve conversations. The name of the team must be exactly the same as the name of the team set on the Hyphenate Customer Engagement Cloud. HMessage *message = [....];// construct a message [message addContent:[[HQueueIdentityInfo alloc] initWithValue:@"Team name"]]; ==== Receive Messages ==== Receive messages by registering listeners to the messages. // Add a message listener. The second parameter is the queue to execute the delegate. It is the main queue by default. [[HChatClient sharedClient].chat addDelegate:self delegateQueue:nil]; // Remove message listener [[HChatClient sharedClient].chat removeDelegate:self]; - (void)messagesDidReceive:(NSArray *)aMessages{ // receive a regular message, format: } - (void)cmdMessagesDidReceive:(NSArray *)aCmdMessages{ // receive a command message, format: . Command messages are not saved in the database. They are used as system notifications, such as comment updates in notes, // and conversations served, transferred, and closed } - (void)messageStatusDidChange:(HMessage *)aMessage error:(HError *)aError{ // message status updated. It is used to refresh the list and display the latest status } - (void)messageAttachmentStatusDidChange:(HMessage *)aMessage error:(HError *)aError{ // Message sent. It is used to refresh the list and display the latest message } ==== Detect Message Type ==== message.body.type == EMMessageBodyTypeText; // text message message.body.type == EMMessageBodyTypeImage; // image message message.body.type == EMMessageBodyTypeVoice; // voice message message.body.type == EMMessageBodyTypeFile; // file message message.body.type == EMMessageBodyTypeCmd; // command message // for a text message, you need to check its subtype [HjudgeTextMessageSubType isTrackMessage:<#HMessage *#>] == YES; // track message [HjudgeTextMessageSubType isOrderMessage:<#HMessage *#>] == YES; // order message [HjudgeTextMessageSubType isMenuMessage:<#HMessage *#>] == YES; // menu message [HjudgeTextMessageSubType isTransferMessage:<#HMessage *#>] == YES;// specify agent [HjudgeTextMessageSubType isEvaluateMessage:<#HMessage *#>] == YES;// satisfaction ratings ==== Get Conversation Details ==== * Retrieve a specified number of messages from the database. The retrieved messages are sorted by time and do not contain the reference message. If the reference message ID is empty, retrieve the latest messages. * * @param aMessageId reference message ID * @param count number of messages * @param aDirection search direction * @param aCompletionBlock callback when completed _conversation = [[HChatClient sharedClient].chat getConversation:]; [_conversation loadMessagesStartFromId:<#messageId#> count:<#(int)count#> searchDirection:<#HMessageSearchDirectionUp#> completion:^(NSArray *aMessages, HError *aError) { if (!aError && [aMessages count]) { //obtained messages aMessages } }]; ===== Conversations ===== ==== Get All Conversations ==== NSArray *conversastions = [[HChatClient sharedClient].chat loadAllConversations]; ==== Delete Conversation and History ==== // delete a conversation. parameter: conversation ID, whether to delete its messages [[HCHatClient shareClient].chat deleteConversation:<#conversationId#> deleteMessages:YES]; HConversation *conversation = [[HConversation alloc] initWithConversation:<#conversationId#>]; // delete a message from a conversation. parameter: message ID, error pointer [conversation deleteMessageWithId:<#messageId#> error:<#(HError **)#>]; // delete all messages from a conversation (without deleting the conversation) [conversation deleteAllMessages:<#(HError **)#>]; ==== Get the Number of Unread Messages ==== Hconversation *conversation = [[HChatClient sharedClient].chat getConversation:<#IM service ID#>]; int unreadCount = conversation.unreadMessagesCount; // get the number of unread messages in a specified conversation ==== Clear the Number of Unread Messages ==== Hconversation *conversation = [[HChatClient sharedClient].chat getConversation:<#IM service ID#>]; [conversation markAllMessagesAsRead:nil]; ===== Notes ===== ==== Get All Notes ==== /* @param tenantId tenant ID @param cname IM service ID @param projectId Note Project ID @param page Page number. It starts from 0. The default is 0. @param pageSize Size of each page. The default is 10. The maximum is 100. */ [[HLeaveMsgManager shareInstance] asyncGetMessagesWithTenantId:<#tenantId#> projectId:<#projectId#> cname:<#NSString *#> page:<#page#> pageSize:<#pageSize#> completion:^(id responseObject, NSError *error) { if(!error) { // request succeeded } else { // failed } }]; ==== Create Note ==== // A note includes: creator information, attachment (array) and other attributes Creator *creator = [Creator new]; creator.name = <#Creator name#>; creator.avatar = <#Avatar address#>; creator.email = <#Email#>; creator.phone = <#Phone number#>; creator.qq = <#QQ ID#>; creator.companyName = <#Company#>; creator.desc = <#Description#>; // attachments (there may or may not be attachments) LeaveMsgAttachment *attachment = [LeaveMsgAttachment new]; attachment.name = <#File name#>; attachment.type = <#Attachment type#>; attachment.url = <#URL#>; LeaveMsgRequestBody *body = [[LeaveMsgRequestBody alloc] init]; body.subject = <#Subject#>; body.content = <#Content#>; body.status = <#Default status#>; body.creator = creator; NSArray *attachments = @[attachment]; body.attachments = attachments; /* @param tenantId tenant ID @param projectId Note Project ID @param cname IM service ID @param requestBody Note parameters */ [[HLeaveMsgManager shareInstance] asyncCreateMessageWithTenantId:<#NSString *#> projectId:<#NSString *#> cname:<#NSString *#> requestBody:<#LeaveMsgRequestBody *#> completion:^(id responseObject, NSError *error) { if(error == nil){ // note sent successfully } else {// failed to send note } }]; ==== Get Note Details ==== /* @param tenantId tenant ID @param projectId Note Project ID @param cname IM service ID @param ticketId Note id */ [[HLeaveMsgManager shareInstance] asyncGetLeaveMessageDetailWithTenantId:<#NSString *#> projectId:<#NSString *#> cname:<#NSString *#> ticketId:<#NSString *#> completion:^(id responseObject, NSError *error) { if(error == nil){ // succeeded } else {// failed } }]; ==== Get All Comments for a Note ==== /* @param tenantId tenant ID @param projectId Note Project ID @param cname IM service ID @param ticketId Note id @param page Page number. It starts from 0. The default is 0. @param pageSize Size of each page. The default is 10. The maximum is 100. */ [[HLeaveMsgManager shareInstance] asyncGetLeaveMessageAllCommentsWithTenantId:<#(NSString *)#> projectId:<#(NSString *)#> cname:<#NSString *#> ticketId:<#(NSString *)#> page:<#(NSUInteger)#> pageSize:<#(NSUInteger)#> completion:^(id responseObject, NSError *error) { if(error == nil){ // succeeded } else {// failed } }]; ==== Add a Comment to a Note ==== // A comment includes: creator information, attachment (array) and other attributes Creator *creator = [Creator new]; creator.identity = <#optional, id of the person who comments#>; creator.name = <#Creator name#>; creator.avatar = <#Avatar address#>; creator.email = <#Email#>; creator.phone = <#Phone number#>; creator.qq = <#QQ ID#>; creator.companyName = <#Company#>; // attachments (there may or may not be attachments) LeaveMsgAttachment *attachment = [LeaveMsgAttachment new]; attachment.name = <#File name#>; attachment.type = <#Attachment type#>; attachment.url = <#URL#>; LeaveMsgRequestBody *body = [[LeaveMsgRequestBody alloc] init]; body.subject = <#Subject#>; body.content = <#Content#>; body.replyId = <#ID of the person who replies to the comment#> body.status = <#Default status#>; body.creator = creator; NSArray *attachments = @[attachment]; body.attachments = attachments; /* @param tenantId tenant ID @param projectId Note Project ID @param cname IM service ID @param ticketId Note id @param requestBody Request body */ [[HLeaveMsgManager shareInstance] asyncLeaveAMessageWithTenantId:<#tenant ID#> projectId:<#projectId#> cname:<#NSString *#> ticketId:<#note ID#> requestBody:<#LeaveMsgRequestBody*#> completion:^(id responseObject, NSError *error) { if(error == nil){ // succeeded } else {// failed } }]; ==== Get Working Status ==== @param tenantId tenant ID [[HLeaveMsgManager shareInstance] getWorkStatusWithTenantId:<#(NSString *)#> completion:^(BOOL isWork, NSError *error) { if (error == nil) { // succeeded if (isWork) { // work hours } else { // non-work hours } } else { // failed } }]; ===== Real-time Audio/Video Calling ===== ==== Real-time Calling ==== // settings for accepting the video invitation HCallOptions *options = [[HCallOptions alloc] init]; options.videoOff = NO; // whether to turn off the video transmission options.mute = NO; // whether to mute options.nickName = <#(NSString *)#>; // nickname options.previewView = <#(HCallLocalView*)#>; // local preview View [[HChatClient sharedClient].call setCallOptions:options]; // register for real-time call callback [[HChatClient sharedClient].call addDelegate:<#(id)#> delegateQueue:nil]; //queue defaults to main // remove real-time call callback [[HChatClient sharedClient].call removeDelegate:<#(id)#>]; // receive a video call request with the nickname of the requester - (void)onCallReceivedNickName:(NSString *)nickName; // member joins the conversation - (void)onMemberJoin:(HCallMember *)member; // member leaves the conversation - (void)onMemberExit:(HCallMember *)member; // a video stream coming in - (void)onStreamAdd:(HCallStream *)stream; // a video stream is removed [not including yourself] - (void)onStreamRemove:(HCallStream *)stream; // video stream is updated - (void)onStreamUpdate:(HCallStream *)stream; // the video call ends - (void)onCallEndReason:(int)reason desc:(NSString *)desc; // video call is over - (void)callDidEnd:(HCallSession *)aSession reason:(HCallEndReason)aReason error:(HError *)aError; // accept video request [[HChatClient sharedClient].call acceptCallCompletion:^(id obj, HError *error) { if (error == nil) { // accepted successfully } }]; // reject video request [[HChatClient sharedClient].call endCall]; // hang up the video request [[HChatClient sharedClient].call endCall]; // switch camera [[HChatClient sharedClient].call switchCameraPosition:YES]; // default front camera (YES) // turn off the microphone [[HChatClient sharedClient].call pauseVoice]; // turn on the microphone [[HChatClient sharedClient].call resumeVoice]; // turn off local video transmission [[HChatClient sharedClient].call pauseVideo]; // turn on local video transmission [[HChatClient sharedClient].call resumeVideo]; // subscribe to member videos [[HChatClient sharedClient].call subscribeStreamId:streamId view:topView completion:^(id obj, HError *error) { if (error == nil) { } else { } }]; //unsubscribe [[HChatClient sharedClient].call unSubscribeStreamId:streamId completion:^(id obj, HError *error) { if (error == nil) { } else { } }];