CocoaPods trunk is moving to be read-only. Read more on the blog, there are 18 months to go.

V5ClientSDK 1.3.16

V5ClientSDK 1.3.16

TestsTested
LangLanguage Obj-CObjective C
License MIT
ReleasedLast Release Oct 2020

Maintained by V5KF.



V5KFClientSDK-iOS

此为V5KF智能客服iOS客户端SDK快速接入文档,包含接入客服系统的基本配置和代码接口,更全面详细的文档可参考这里

1 开发环境准备

  1. V5KF客服系统账号

没有 V5KF 账号需要前往官网注册账号。

  1. 获得应用账号、站点编号

应用账号、站点编号作为 SDK 连接服务端的身份凭证,可登录V5KF管理后台在 "系统接入" -> "移动应用APP" 配置界面获取。

  1. 填写对应平台的推送服务器地址(非必需)

为了使您的 APP 在集成本 SDK 后具有离线消息推送,建议填写您的推送服务器地址,同时也支持第三方推送平台,需要按照本文档规定填写您的 device_token 和绑定的用户 ID。

  1. 下载 SDK

您可以到 V5KF 官网或者V5KF Github*(建议)*页下载智能客服 SDK,包含了开发包和带 UI 界面的 Demo 示例工程,使用CocoaPods导入则可不用下载。

  1. 环境要求

在您集成智能客服 SDK 前环境要求如下: - 支持的最低版本 iOS 8.0。 - 支持 ARC 的 Xcode 编译器,建议使用最新版本。

2 SDK导入

2.1 Objective-C项目

把V5ClientSDK 文件夹拷贝到您的工程路径下面,然后在工程目录结构中,右键选择 Add Files to “工程名” 。或者将这个文件夹拖入 Xcode 工程目录结构中,并选择Create groups。

2.2 Swift项目

  • 按照上面的方法引入V5ClientSDK的文件。
  • 在 Bridging Header 头文件中,加入#import “V5ClientAgent.h”等相关头文件。注:如何添加 Bridging Header

注:此SDK为Objective-C开发,可能存在不适用swift的情况

2.3 引入依赖库

V5Client的实现依赖了一些系统框架,在开发应用时,要在工程里加入这些框架。开发者首先点击工程右边的工程名,然后在工程名右边依次选择 TARGETS -> General -> Linked Frameworks and Libraries,展开 Linked Frameworks and Libraries 后点击展开后下面的 + 来添加下面的依赖项:

  • libsqlite3.tbd
  • libicucore.tbd
  • stdc++.tbd
  • AVFoundation.framework
  • AudioToolbox.framework
  • CFNetwork.framework
  • Security.framework
  • MediaPlayer.framework
  • WebKit.framework

2.4 静态库

注: 针对 iOS 7+

使用CocoaPods管理依赖库的可以更方便的导入SDK。只需要在 Podfile 中加入(此处导入的SDK为静态库,动态库请参考2.5):

platform :ios, '7.0'

pod 'V5ClientSDK'

接着pod安装 即可:

$ pod install

有新版本更新时:

$ pod update V5ClientSDK

如果运行以上命令,没有搜到或者搜不到最新版本,您可以运行以下命令,更新一下您本地的 CocoaPods 源列表:

pod repo update  

2.5 动态库

注: 针对 iOS 8+

为应对不断发展的开发需求,本SDK自1.2.7版本开始提供动态库解决方案,命名为V5Client.framework,并支持使用Cocoapods和Carthage导入,静态库版本亦会继续支持。 注:动态库使用时引用头文件方式为#import <V5Client/V5ClientAgent.h>

使用CocoaPods导入

platform :ios, '8.0'
use_frameworks!

target 'ClientDemo' do
  pod 'V5Client'
end

target那里的ClientDemo改为你的target

使用Carthage引入

github "V5KF/V5KFClientSDK-iOS"

然后把Carthage/Build/iOS/V5Client.framework拖入项目配置的General->Embedded Binaries,并选择Copy items if needed

3 Info.plist配置

3.1 ATS

由于 iOS 9 的新特性默认使用 ATS,所有网络请求都需要在安全的连接下(当前 App Store 尚未强制使用iOS 9这一新特性),所以一些不兼容的服务需要进行额外的配置,本SDK使用到了语音和图片服务的 webservice 接口,需在 Info.plist 添加下述配置:

  <key>NSAppTransportSecurity</key>
  <dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
    <key>NSAllowsArbitraryLoadsInWebContent</key>
    <true/>
  </dict>

关于这一特性的详细说明和解决方案可参考: https://github.com/ChenYilong/iOS9AdaptationTips

注: 本SDK 1.1.10 以上版本已完全兼容 HTTPS,若无特殊需求,无需配置 ATS 项NSAllowsArbitraryLoads,但仍须配置NSAllowsArbitraryLoadsInWebContent。原因:本SDK在 1.1.10 版本开始支持 https,SDK 默认会将访问的网络图片(比如用户头像)和其他网络请 求进行自动转为 https 方式访问,若目标站点未支持 https 仍需要 http 访问,可通过设置[V5ClientAgent shareClient].config.autoSSL = NO来取消自动转 https,并自行配置好对应的 ATS 选项。另外1.2.9版本开始支持webview加载网页,网页URL无法确保支持https,故仍需要配置NSAllowsArbitraryLoadsInWebContent

3.2 权限

由于 SDK 中使用到相册、相机还有录音,在 Info.plist 中需要加入以下内容: (文中以 XML 格式描述)

<key>NSPhotoLibraryUsageDescription</key> 
<string>Choose photo</string> 
<key>NSCameraUsageDescription</key> 
<string>Take pictures</string>
<key>NSMicrophoneUsageDescription</key>
<string>Record voice</string>

4 SDK接口快速集成

4.1 初始化SDK

将SDK文件添加到工程后,在AppDelegateimport “V5ClientAgent.h“文件,然后在application: willFinishLaunchingWithOptions:函数中初始化 SDK 。示例如下:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch. 
    // 初始化SDK
    [V5ClientAgent initWithSiteId:@"10000"
                            appId:@"19cfb0800f474"
                   exceptionBlock:nil];
    return YES;
}

其中 siteIdaccount 分别是从 V5 后台可以获取到的站点编号和AppID。 SDK后台配置

4.2 用户信息和参数设置

使用 SDK 提供的 UI 集成,需要在启动会话界面之前进行用户信息和参数配置。配置项如下:

//需要#import "V5ClientAgent.h"
//获得V5ClientAgent配置对象
V5Config *config = [V5ClientAgent shareClient].config;

//用户信息单次设置即生效,更新用户信息或者切换用户时需调用shouldUpdateUserInfo,设置用户信息前调用
//[config shouldUpdateUserInfo];

//设置用户信息,坐席端可查看
config.nickname = @"test-张三";
config.gender = 1; //性别:0-未知 1-男 2-女
config.avatar = @"头像URL"; //客户头像URL
//openId:用户唯一ID,长度32字节以内,不同的openId消息记录单独保存,可透传到座席端提供给座席插件,替代v1.2.0之前版本的uid(uid不再使用)
//若您是旧版本SDK用户,只是想升级,为兼容旧版,避免客户信息改变可继续使用config.uid,可不用openId
config.openId = @"ios-user-id-for-test";

// 注:openId尽量不要携带特殊字符($&+,/:;=?@%#[]以及空格之类的字符),若包含则会经过urlencode编码,客席插件收到这样的oid后要相应的解码处理(decodeURIComponent)
// 添加自定义用户信息NSDictionary,(仅在开启对话页面前设置生效)
config.userInfo = @{@"商品名称": @"牛仔裤", 
					@"商品价格": @"¥168.00"};

// [1.3.8新增]设置V5系统内置的客户基本信息,区别于userInfo,这里设置的是V5系统内置字段
// 支持字段:country,province,city,language(上面的nickname,gender,avatar,vip也可在此设置)
config.baseInfo = @{@"country": @"中国",
              @"province": @"广东",
              @"city": @"深圳",
              @"language": @"zh-cn"};

nicknameopenIdavatardevice_token 等配置项配置完,下次需要修改(如App内切换了登录账号,修改了客户昵称或头像时)并向座席更新时需要在设置新信息前调用 [config shouldUpdateUserInfo],这样才会向服务端更新这几个配置项。同样若想更新站点信息,需要在onChatActivityConnect中调用 [[V5ClientAgent shareClient] updateSiteInfo]。客户信息、站点信息(包含机器人信息和转人工开场白等V5后台可设置的信息)的更新存在缓存策略,系统每隔7天更新,一般无需处理,需要即时更新时方才调用此处接口。

指定人工客服或分组设置方式:

/*
 * 连接建立后才可以调用下面接口,以下是两种转人工情况示例(在onClientViewConnect回调中执行,参考:【README.full.md】5.5 对话界面代理)
 */
// 【转】指定人工客服(调用时立即转),参数: 客服组id,客服id (以下数字仅作为示例,具体ID请前往V5后台查看客服信息)
[[V5ClientAgent shareClient] humanServiceOfGroupId:0 workerId:114052];
// 【指定人工客服】点击转人工按钮或者问题触发转人工时会转到指定人工,参数"0 132916"中两个数字先后对应需要转的客服组ID和客服ID
[[V5ClientAgent shareClient] sendMessage:[[V5ControlMessage alloc] initWithCode:4 argc:2 argv:@"0 114052"]];

4.3 启动会话界面

通过简单地添加一个在线咨询按钮即可使用智能客服客户端功能,在按钮点击事件处理中加入启动会话界面的代码:

V5ChatViewController *chatViewController = [V5ClientAgent createChatViewController];
// 不显示底部栏(有底部栏的需加此配置) 
chatViewController.hidesBottomBarWhenPushed = YES;

/* 下面为会话界面配置,非必须,可根据需求自定义配置,均有默认值 */
// 会话界面的代理V5ChatViewDelegate,详细的说明可参考[详细文档](./README.full.md)
//chatViewController.delegate = self; 
// 设备的ID(也可在config设置deviceToken),有选择推送功能的需要配置
// chatViewController.deviceToken = @"设备的deviceToken";
// 允许并设置消息铃声SystemSoundID 
chatViewController.allowSound = YES; 
chatViewController.soundID = 1007;
// 允许发送语音 
chatViewController.enableVoiceRecord = YES; 
// 允许显示头像
chatViewController.showAvatar = YES;
// 头像圆角(0~20之间)
chatViewController.avatarRadius = 6;
// 每次下拉获取历史消息最大数量,默认10 
chatViewController.numOfMessagesOnRefresh = 10;
// 开场显示历史消息数量,默认0(显示历史消息>0则无开场白)
chatViewController.numOfMessagesOnOpen = 10;
// 设置会话界面标题
chatViewController.title = @"V5客服"; // 设置标题
// 设置返回按钮标题(默认为前一页面标题)
UIBarButtonItem *myBackItem = [[UIBarButtonItem alloc] init]; 
myBackItem.title = @"返回";
self.navigationItem.backBarButtonItem = myBackItem;
// 设置开场白方式,启动会话前设置,默认ClientOpenModeDefault
// ClientOpenModeQuestion结合后台机器人培训内容可根据使用场景配置不同需求的开场消息
[chatViewController setClientOpenMode:ClientOpenModeDefault withParam:nil];

// 启动会话界面,使用导航模式推出视图
[self.navigationController pushViewController:(UIViewController *)chatViewController animated:YES];

若开启对话页面非导航模式,则需使用present方式打开

@interface ViewController () {
    // 添加的导航控制器
    UINavigationController *navVC;
}
@end

//......

// 若非导航模式,使用present方式开启,添加导航控制器包裹chatViewController,并加入关闭页面所需的按钮
navVC = [[UINavigationController alloc] initWithRootViewController:chatViewController];
chatViewController.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(closeChat:)];
[self presentViewController:navVC animated:YES completion:nil];

//......

// done按钮点击关闭页面
- (void)closeChat:(id)sender {
    [navVC dismissViewControllerAnimated:YES completion:nil];
    if ([V5ClientAgent shareClient].isConnected) {
      [[V5ClientAgent shareClient] stopClient];
    }
}

如果SDK使用在iPad里,启动会话界面可采用UIPopoverPresentationController方式,以及限制横屏状态的处理方式,具体配置如下:

// 页面呈现方式presentType默认PresentType_Push, PopoverViewController下改为PresentType_Popover
chatViewController.presentType = PresentType_Popover;
chatViewController.view.transform = CGAffineTransformMakeScale(0.8, 0.8); //缩小页面内容

//使用UIPopoverPresentationController开启对话
chatViewController.modalPresentationStyle = UIModalPresentationPopover;
chatViewController.preferredContentSize = CGSizeMake(400, 500);
UIPopoverPresentationController* popover = chatViewController.popoverPresentationController;
//设置弹出的基准视图
popover.sourceView = self.button;
popover.sourceRect = self.button.bounds;//打开页面的入口按钮的bunds
popover.delegate = self;
[self presentViewController:chatViewController animated:YES completion:nil];

// 或者使用`UIPopoverController`,iOS9.0以后不再建议使用
// UIPopoverController* popover = [[UIPopoverController alloc] initWithContentViewController:chatViewController];
// [popover setBackgroundColor:[UIColor colorWithRed:235.0/255 green:235.0/255 blue:235.0/255 alpha:1]];
// popover.popoverContentSize = CGSizeMake(chatViewController.view.frame.size.width, chatViewController.view.frame.size.height);
// [popover presentPopoverFromRect:CGRectMake(0,618,1024,50) inView:self.view permittedArrowDirections:UIPopoverArrowDirectionDown animated:YES];

/* 需要手动控制屏幕方向时使用,比如iPad横屏情况 */
// 需要**限制横屏**打开时(UIInterfaceOrientationMaskLandscape),为解决发送图片时选择图库打开页面异常问题,需要在AppDelegate做如下处理
- (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {
    if ([V5ClientAgent shareClient].isPhotoLibrary) { //必须,否则打开图库异常
        return UIInterfaceOrientationMaskAll;
    } else {
        return UIInterfaceOrientationMaskLandscape;//or UIInterfaceOrientationMaskAll 允许全部屏幕方向
    }
}

4.4 生命周期处理

在使用 UI 集成的 SDK 中, 【必须】AppDelegate 中添加下面代码:

- (void)applicationDidEnterBackground:(UIApplication *)application {
	//退出到后台时,通知 SDK 用户离线
	[[V5ClientAgent shareClient] onApplicationDidEnterBackground]; 
}

- (void)applicationWillEnterForeground:(UIApplication *)application {
	//移动到前台时,通知 SDK 用户上线并连接
	[[V5ClientAgent shareClient] onApplicationWillEnterForeground];
}

此外,不使用客服功能时需要关闭会话服务以节省资源并避免客户离线的状态未更新到座席(已配置离线推送情况下还会影响消息推送)。

下面列举几种情况下关闭会话的示例:

使用push推出页面的,在开启会话界面的前一个界面的 viewDidAppear:方法中手动调用关闭客服的方法:

- (void)viewDidAppear:(BOOL)animated { // 前一 viewController 中 
  // 不使用客服功能时(在会话 VC 关闭后)退出消息客户端 
  if ([V5ClientAgent shareClient].isConnected) {
    [[V5ClientAgent shareClient] stopClient];
  }
}

使用present弹出页面的,在关闭页面的selector中调用

// done按钮点击关闭页面的selector
- (void)closeChat:(id)sender {
    [navVC dismissViewControllerAnimated:YES completion:nil];
    if ([V5ClientAgent shareClient].isConnected) {
      [[V5ClientAgent shareClient] stopClient];
    }
}

UIPopoverPresentationController方式打开的,则需要通过实现UIPopoverPresentationControllerDelegatepopoverPresentationControllerDidDismissPopover:来调用[[V5ClientAgent shareClient] stopClient];:

- (void)popoverPresentationControllerDidDismissPopover:(UIPopoverPresentationController *)popoverPresentationController {
    // 不使用客服功能时(在会话 VC 关闭后)退出消息客户端 
    if ([V5ClientAgent shareClient].isConnected) {
        [[V5ClientAgent shareClient] stopClient];
    }
}

此外,使用UIPopoverController或者其他方式开启的也是同理,需要手动关闭会话。

4.5 第三方输入框兼容问题

使用了IQKeyboardManager的App在接入本SDK后,对话界面弹出软键盘时会有异常,这时只需要关闭IQKeyboardManager的功能即可,具体方法如下:

开启会话节面前需要设置V5ChatViewDelegate代理:

// 会话界面的代理V5ChatViewDelegate
chatViewController.delegate = self;

实现代理中关于生命周期的方法,分别在clientViewWillAppearclientViewWillDisappear添加IQKeyboardManager的关闭和开启的代码:

#pragma mark - V5ChatViewDelegate -

/**
 *  即将打开会话视图
 */
- (void)clientViewWillAppear {
    //取消输入键盘插件
    [IQKeyboardManager sharedManager].enable = NO;
    [IQKeyboardManager sharedManager].enableAutoToolbar = NO;
}

/**
 *  会话视图打开后
 */
- (void)clientViewDidAppear {
}

/**
 *  即将关闭会话视图
 */
- (void)clientViewWillDisappear {
    //开启输入键盘插件
    [IQKeyboardManager sharedManager].enable = YES;
    [IQKeyboardManager sharedManager].enableAutoToolbar = YES;
}

/**
 *  关闭会话视图后
 */
- (void)clientViewDidDisappear {
}

/**
 *  会话连接成功
 */
- (void)onClientViewConnect {
}