Tap 客服开发指南
本文介绍如何在游戏中接入 TDS 提供的客服系统。
权限说明
- Unity
- Android
- iOS
- UE4
该模块需要权限如下:
| 权限 | 使用目的 | 权限申请时机 |
|---|---|---|
| 网络权限 | 访问网络数据 | 用户首次使用该功能时会申请权限 |
| 获取网络状态 | 用于检测当前网络连接是否有效 | 用户首次使用该功能时会申请权限 |
| 读取存储权限 | 用于反馈工单时添加本地图片、视频附件 | 上传附件时申请 |
该模块将在应用 AndroidManifest.xml 中添加如下权限:
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"
android:maxSdkVersion="32" />
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES"/>
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO"/>
SDK 初始化
在 下载页 获得 TapSDK,引入 TapSupport 模块:
- Unity
- Android
- iOS
- UE4
SDK 可以通过 Unity Package Manager 导入或手动导入,二者任选其一。请根据项目需要选择。
方法一:使用 Unity Package Manager
NPMJS 安装
从 3.25.0 版本开始,TapSDK 支持了 NPMJS 安装,优势是只需要配置版本号,并且支持嵌套依赖。
在项目的 Packages/manifest.json 文件中添加以下依赖:
"dependencies":{
"com.taptap.tds.support":"3.30.1",
}
但需要注意的是,要在 Packages/manifest.json 中 dependencies 同级下声明 scopedRegistries:
"scopedRegistries": [
{
"name": "NPMJS",
"url": "https://registry.npmjs.org/",
"scopes": ["com.tapsdk", "com.taptap", "com.leancloud"]
}
]
GitHub 安装
在项目的 Packages/manifest.json 文件中添加以下依赖:
"dependencies":{
"com.taptap.tds.common":"https://github.com/TapTap/TapCommon-Unity.git#3.30.1",
"com.taptap.tds.support":"https://github.com/TapTap/TapSupport-Unity.git#3.30.1",
"com.leancloud.storage":"https://github.com/leancloud/csharp-sdk-upm.git#storage-2.3.0",
}
在 Unity 顶部菜单中选择 Window > Package Manager 可查看已经安装在项目中的包。
方法二:手动导入
-
在 下载页 找到 TapSDK Unity 下载地址,下载
TapSDK-UnityPackage.zip。 -
在 Unity 项目中依次转到 Assets > Import Packages > Custom Packages,从解压后的
TapSDK-UnityPackage.zip中,选择希望在游戏中使用的 TapSDK 包导入,其中:
TapTap_Common.unitypackageTapSDK 基础库,必选。TapTap_Support.unitypackageTapTap 客服库,必选。
- 从 LeanCloud-SDK 下载页 中下载并解压 LeanCloud-SDK-Storage-Unity.zip,然后将 Plugins 文件夹拖拽至 Unity 即可。
TapSupport SDK 依赖 TapCommon 模块:
repositories{
flatDir {
dirs 'libs'
}
}
dependencies {
...
implementation name:'TapCommon_3.30.1', ext:'aar'
implementation (name:'TapSupport_3.30.1', ext:'aar')
}
确认 AndroidManifest.xml 已添加网络权限:
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
TapSupport SDK 依赖 TapCommon 模块:
TapCommonSDK.framework
// 3.29.4 版本需要添加 LibProtocolBuffers
LibProtocolBuffers.framework
TapSupportSDK.framework
TapSupport SDK 依赖 TapCommon 模块:
PublicDependencyModuleNames.AddRange(
new string[]
{
"TapCommon",
"TapSupport"
// ... add other public dependencies that you statically link with here ...
}
);
在初始化 SDK 之前,有一些准备工作需要完成:
- 请厂商管理员或客服管理员邀请你成为客服管理员。
- 每个厂商会被分配一个专属域名,需要记下待用。你可以在客服工作台的 设置 > 开发者信息 中找到可用的域名。如果你想要使用自己的域名,可以联系厂商管理员在开发者中心游戏客服模块中绑定。
- 在客服工作台,为你的游戏创建一个产品(设置 > 管理 > 产品与分类),记下这个产品的 ID。
然后使用以下代码初始化 TapSupport 模块:
- Unity
- Android
- iOS
- UE4
using TapTap.Support;
TapSupport.Init("https://please-replace-with-your-customized.domain.com", "产品 ID");
import com.tds.tapsupport.TapSupport;
import com.tds.tapsupport.TapSupportCallback;
import com.tds.tapsupport.TapSupportConfig;
TapSupportConfig config = new TapSupportConfig("https://please-replace-with-your-customized.domain.com", "产品 ID", new TapSupportCallback() {
@Override
public void onUnreadStatusChanged(boolean hasUnread) {
// 我们会在 §未读消息通知 讨论 callback 的用法
}
})
TapSupport.setConfig(this, config);
#import <TapSupportSDK/TapSupportSDK.h>
TapSupportConfig *config = [TapSupportConfig new];
config.server = @"https://please-replace-with-your-customized.domain.com";
config.productID = @"产品 ID";
config.callback = self;
[TapSupport shareInstance].config = config;
#include "TapUESupport.h"
FTapSupportConfig Config;
Config.ServerUrl = TEXT("https://please-replace-with-your-customized.domain.com");
Config.ProductID = TEXT("产品 ID");
TapUESupport::Init(Config);
上述代码示例中,please-replace-with-your-customized.domain.com 就是准备工作 2 中获取或绑定的域名。产品 ID 是在准备工作 3 中新建的产品的 ID。
登录
为了确保玩家提交的表单等信息只有该玩家能访问,客服系统需要登录才能使用。我们提供三种不同的登录方式:
- TDS 内建账 户(TDSUser)登录
- 游戏自有账户系统关联登录
- 匿名登录
这里的登录指的是游戏玩家在游戏内使用客服系统功能时认证身份的过程(authentication)。这一步主要是游戏侧与客服系统之间的交互,通常玩家是无感知的,和游戏本身的登录是两回事(比如这里的匿名登录与游戏的游客登录无关)。
TDS 内建账户登录
如果你的游戏使用了 TDS 内建账户服务,可以直接在客户端使用已登录的 TDSUser 授权登录客服系统。
TDS 内建账户服务是 TDS 提供的支持多种登录方式的用户系统。如果你的游戏已经在使用 TapTap 登录、好友、成就、排行榜等服务,你很可能已经在使用 TDS 内建账户了。更多介绍,请参考《内建账户功能介绍》。
要使用 TDSUser 授权登录客服系统,先要使用一个已登录的 TDS 用户账号请求授权 token,然后使用该 token 调用客服模块的 TDS 登录接口:
- Unity
- Android
- iOS
- UE4
try {
string token = await TDSUser.RetrieveShortToken();
await TapSupport.LoginWithTDSCredential(token);
Debug.Log("登录 TDSUser JWT 完成");
} catch (TapException e) {
Debug.LogError($"{e.Code} : {e.Message}");
} catch (Exception e) {
Debug.Log(e);
}
TDSUser.retrieveShortTokenInBackground(tdsUser.getSessionToken()).subscribe(new Observer<JSONObject>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(JSONObject jsonObject) {
String credential = jsonObject.getString("identityToken");
TapSupport.loginWithTDSCredential(credential, new TapSupport.LoginCallback() {
@Override
public void onComplete(boolean success, Throwable error) {
if (success) {
// 登录成功
} else {
// 登录失败
Log.e("TapSupportActivity", "login:error:" + error.toString());
}
}
});
}
@Override
public void onError(Throwable error) {
// 请求授权 token 失败
}
@Override
public void onComplete() {
}
});
[TDSUser retrieveShortTokenWithCallback:^(NSString *_Nullable token, NSError *_Nullable error) {
if (error) {
// 请求授权 token 失败
} else {
[TapSupport loginWithTDSCredential:token
handler:^(BOOL succcess, NSError *_Nullable error) {
if (succcess) {
// 登录成功
} else {
// 登录失败
}
}];
}
}];
// Todo 1
if (TSharedPtr<FTDSUser> User = FTDSUser::GetCurrentUser())
{
User->RetrieveShortToken(
FStringSignature::CreateLambda([](const FString& Credential)
{
/** 获取Credential成功 */
TapUESupport::LoginWithTDSCredential(
Credential,
FSimpleDelegate::CreateLambda([]()
{
/*** 登录成功 */
}),
FTUError::FDelegate::CreateLambda([](const FTUError& Error)
{
/*** 登录失败 */
}));
}),
FLCError::FDelegate::CreateLambda([](const FLCError& Error)
{
/** 获取Credential失败 */
}));
}
异常处理
如果 SDK 在登录以及后续流程中发生了异常,开发者可以通过回调得到通知。
在这些异常中,我们需要特别处理 token 过期(EXPIRED_CREDENTIAL)异常,重新执行一遍上面的「请求授权 token,调用登录接口」的流程重新登录客服。
对于其他种类的异常,建议直接向玩家展示。由于客服功能异常通常不影响玩家的游玩体验,可以考虑仅在客服入口处提示玩家客服不可用,并提供手动触发重试的交互。
- Unity
- Android
- iOS
- UE4
if (e is TapException ex && ex.Code == 9006) {
// 登录过期
} else {
// 其他异常
}
if (e instanceof ServerException) {
try {
org.json.JSONObject errorResponse = new org.json.JSONObject(((ServerException) e).responseBody);
if(errorResponse.getInt("numCode")==9006){
// 登录过期
}
} catch (JSONException ex) {
// ignore
}
}
if (error) {
if (error.code == 9006) {
// 重新登录
} else {
// 其他异常
using TapTap.Support;
TapSupport.Init("https://please-replace-with-your-customized.domain.com", "分类 ID", new TapSupportCallback
{
OnGetUnreadStatusError = (exception) => {
if (e is TapException ex && ex.Code == 9006) {
// 登录过期,重新执行 TDSUser.RetrieveShortToken 以及 TapSupport.LoginWithTDSCredential
} else {
// 其他异常
}
}
});
import com.tds.tapsupport.TapSupport;
import com.tds.tapsupport.TapSupportCallback;
import com.tds.tapsupport.TapSupportConfig;
TapSupportConfig config = new TapSupportConfig("https://please-replace-with-your-customized.domain.com", "分类 ID", new TapSupportCallback() {
@Override
public void onGetUnreadStatusError(Throwable e) {
if (e instanceof ServerException) {
try {
org.json.JSONObject errorResponse = new org.json.JSONObject(((ServerException) e).responseBody);
if(errorResponse.getInt("numCode")==9006){
// 登录过期,重新执行 TDSUser.retrieveShortTokenInBackground 以及 TapSupport.loginWithTDSCredential
} else {
// 其他异常
}
} catch (JSONException ex) {
// ignore
}
}
}
});
TapSupport.setConfig(this, config);