跳到主要内容
版本:v3

实名认证和防沉迷开发指南

提示

使用 TDS 实名认证和防沉迷服务之前,需要在开发者中心后台 > 游戏服务 > 生态服务 > 合规认证 处开通服务,可选择「已有版号」或「暂无版号」方案。

SDK 配置

可以在 下载页 获得 TapSDK,引入防沉迷模块。

Unity 模块是通过引入 iOS 和 Android 模块后增加桥接文件打包出的 .unitypackage,方便以 Unity 开发的游戏直接引入。其他引擎/平台的游戏可以通过 iOS/Android 原生的方式接入,详见 iOS/Android 接入文档。

Unity 开发环境要求:Unity 2019.4 或更高版本

支持版本:

  • Android:最低支持 5.0
  • iOS:最低支持 iOS 10.0

SDK 可以通过 Unity Package Manager 导入或手动导入,二者任选其一。请根据项目需要选择。

方法一:使用 Unity Package Manager

在项目的 Packages/manifest.json 文件中添加以下依赖:

"dependencies":{
"com.tapsdk.antiaddiction":"https://github.com/taptap/TapAntiAddiction-Unity.git#3.16.1",
"com.leancloud.storage": "https://github.com/leancloud/csharp-sdk-upm.git#storage-0.10.18",
"com.taptap.tds.common":"https://github.com/TapTap/TapCommon-Unity.git#3.16.1",
}

在 Unity 顶部菜单中选择 Window > Package Manager 可查看已经安装在项目中的包。

方法二:手动导入

下载页 找到 TapSDK Unity 和 LeanCloud C# SDK 下载地址,分别下载 TapSDK-UnityPackage.zip 和 LeanCloud-SDK-Storage-Unity.zip。

  • TapSDK-UnityPackage.zip 解压后,导入其中的 TapTap_Common_3.16.1.unitypackageTapTap_AntiAddiction_3.16.1.unitypackage

iOS 平台配置:

使用 Xcode 13.0 beta 5 编译,检查 Unity 输出的 Xcode 工程:

  1. 请确保设置 Xcode - General - Frameworks, Libraries, and Embedded Content 中的 AntiAddictionService.frameworkAntiAddictionUI.frameworkDo Not Embed
  2. 如果编译报错找不到头文件或者模块,请确保 Xcode-Build Settings - Framework Search Paths 中的路径以保证 Xcode 正常编译。
  3. 确保 Xcode 工程的 Build SettingsSwift Compile Language/Swfit Language VersionSwift5
  4. 添加依赖库 libz.tbd libc++.tdb
  5. 开始代码接入
  6. AntiAddiction-Unity/Assets/Plugins/iOS/Resource/AntiAdictionResources.bundle 拷贝到游戏项目下 (如果 unity 项目没有正确导入 AntiAddictionResources.bundle)

防沉迷 SDK 需要联网和发送请求数据的权限,请开发者注意在项目中声明相应权限。

初始化

初始化防沉迷 UI 模块,设置启动防沉迷功能的配置,注册防沉迷的消息监听。请注意,触发回调需要调用防沉迷认证接口。

using TapTap.AntiAddiction;
using TapTap.AntiAddiction.Model;

AntiAddictionConfig config = new AntiAddictionConfig()
{
gameId = "your_client_id", // TapTap 开发者中心对应 Client ID
useTapLogin = true, // 是否启动 TapTap 快速认证
showSwitchAccount = false, // 是否显示切换账号按钮
};

Action<int, string> callback = (code, errorMsg) => {
//code == 500; //登录成功
//code = 1000; //用户登出
//code = 1001; //切换账号
//code = 1030; //用户当前无法进行游戏
//code = 1050; //时长限制
//code = 9002; //实名过程中点击了关闭实名窗
UnityEngine.Debug.LogFormat($"code: {code} error Message: {errorMsg}");
};

AntiAddictionUIKit.Init(config, callback);

参数说明

  • config 是防沉迷功能的配置,包括如下参数:

    • gameId 游戏的 Client ID,可以在控制台查看(开发者中心 > 你的游戏 > 游戏服务 > 应用配置)。

    • useTapLogin 是否使用 TapTap 快速认证。建议使用这个功能,方便已经在 TapTap 上实名认证过的玩家快速完成防沉迷认证步骤。

    • showSwitchAccount 是否显示切换账号按钮。如果游戏没有切换账号功能,可以在初始化阶段配置隐藏切换账号按钮;如果游戏选择显示切换账号按钮(如下图所示),玩家点击之后会触发 1001 回调,游戏可根据这个回调 code 做相应处理。

  • callback 是防沉迷的在各种情况下,通知用户的回调接口,包含参数如下:

    • code 不同情况下的回调类型,详情可以参考下面的回调类型

    • errorMsg 在执行不同业务时,发生错误时的错误消息。

切换账号界面

回调类型

回调 code回调类型触发逻辑
500LOGIN_SUCCESS玩家登录后判断当前玩家可以进行游戏
1000EXITED退出账号
1001SWITCH_ACCOUNT点击切换账号按钮
1030PERIOD_RESTRICT未成年玩家当前无法进行游戏
1050DURATION_LIMIT时长限制
9002REAL_NAME_STOP实名过程中点击了关闭实名窗

防沉迷认证

SDK 支持两种防沉迷认证方式:

  1. 使用 TapTap 快速认证,可令玩家授权游戏使用 TapTap 上的年龄段信息完成实名。
  2. 不使用 TapTap 快速认证,玩家在 SDK 提供的界面中手动输入身份证号等实名信息。

TDS 云端会根据实名信息判断玩家是否可以进行游戏,并将相关信息上报至中宣部防沉迷实名认证系统。

我们推荐使用第一种方式,对于玩家而言,不需要手动输入信息,可以快速完成认证、进入游戏,体验更佳。

TapTap 快速认证

信息

防沉迷 v3.7.1 开始,使用快速认证不再依赖 TapTap 登录 SDK,但快速认证需要玩家在已登录状态下授权游戏使用其在 TapTap 上的年龄段信息完成实名,请确保完成了以下工作

  • 开通 TapTap 登录功能。若此项未完成,快速认证时玩家会遇到「应用未开通 TapTap 登录服务」提醒。
  • 后台配置签名证书。若此项未完成,快速认证拉起 TapTap 客户端会提示「授权失败」。
  • 后台添加测试用户,或者点击「开放全量用户」按钮。若此项未完成,快速认证时玩家会遇到「抱歉,该游戏 / 应用暂未开放」提醒。

初始化 SDK 时将是否使用 TapTap 快速认证参数设置为 true

传入玩家唯一标识 userIdentifier,即可开始 TapTap 快速认证。SDK 会拉起 TapTap 开始快速认证,如果 SDK 检测到玩家设备中未安装 TapTap 客户端,则会打开 WebView,玩家可授权游戏使用其在 TapTap 上的年龄段信息来完成游戏内的实名流程。

其中的玩家唯一标识 userIdentifier,如果接入 TDS 内建账户系统,可以用玩家的 objectId;如果使用单纯 TapTap 用户认证则可以用 openidunionid

string userIdentifier = "玩家的唯一标识";
AntiAddictionUIKit.Startup(userIdentifier);

注意:Unity 项目如果没有接入登录模块,则项目导出的 Xcode 工程打包 iOS 时需要配置 URLSchema

查看 Xcode 工程如何配置 URLSchema

打开 info.plist,添加如下配置(请替换 clientID 为你在控制台获取的 Client ID):

<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLName</key>
<string>taptap</string>
<key>CFBundleURLSchemes</key>
<array>
<!-- 这里注意下,中括号需要去掉,最终是 Client ID 前拼接上 `tt` 的形式,例如:ttFwFdCxxxxxxxQDQwQN -->
<string>tt[clientID]</string>
</array>
</dict>
</array>

<key>LSApplicationQueriesSchemes</key>
<array>
<string>tapiosdk</string>
<string>tapsdk</string>
</array>

手动输入实名信息

如果不使用 TapTap 快速认证,初始化 SDK 时将是否使用 TapTap 快速认证参数设置为 false,调用认证接口。

需要传入的玩家唯一标识 userIdentifier,由游戏自己定义。

登出

玩家在游戏内退出账号时调用,重置防沉迷状态。

AntiAddictionUIKit.Exit();

获取玩家年龄段

调用该接口可获取玩家所处年龄段:

int ageRange = AntiAddictionUIKit.AgeRange;

上例中的 ageRange 是一个整数,表示玩家所处年龄段的下限(最低年龄)。 特别地,-1 表示「未知」,说明该用户还未实名。

类型数值含义
-1未知
00 到 7 岁
88 到 15 岁
1616 到 17 岁
18成年玩家

获取剩余时长(单位:秒)

获取玩家当前剩余时长:

int remainingTimeInSeconds = AntiAddictionUIKit.RemainingTime;

获取剩余时长(单位:分钟)

获取玩家当前剩余时长:

int remainingTimeInMinutes = AntiAddictionUIKit.RemainingTimeInMinutes;

检查消费上限

根据年龄段的不同,未成年玩家的消费金额有不同的上限。 如果启用消费限制功能,开发者需要在未成年玩家消费前检查是否受限,并在成功消费后上报消费金额。

游戏在收到玩家的付费请求后,调用以下接口当前玩家的付费行为是否被限制:

long amount = 100;
AntiAddictionUIKit.CheckPayLimit(amount,
(result) => {
// status 为 1 时可以支付
int status = result.status;
if (status == 1) {
// 可以进行支付
}
},
(exception) => {
// 处理异常
}
);

消费金额的单位为分。

检查消费上限需要游戏事先上报未成年玩家的消费金额。 建议开发者在服务端上报,服务端上报方式参见 相关 REST API 用法说明。 开发者也可以调用 SDK 提供的接口,当未成年玩家消费成功后,在客户端上报消费金额,在客户端上报的可靠性低于在服务端上报,主要适用于无服务端的单机游戏。

long amount = 100;
AntiAddictionUIKit.SubmitPayResult(amount,
() => {
// 成功
}, (exception) => {
// 处理异常
}
);

上报消费金额时,传入的消费金额的单位同样为分。

上报游戏时长

已登录的玩家,开始游戏时调用此接口,之后 SDK 会自动轮询上报游戏时长。

AntiAddictionUIKit.EnterGame();

相应地,已登录的玩家,停止游戏时调用此接口,之后 SDK 停止轮询上报时长。

AntiAddictionUIKit.LeaveGame();

REST API

请求格式

REST API 请求的主体为 JSON 格式,HTTP header 的 Content-Type 需要设置为 application/json

请求通过 Authorization TOKEN HTTP 头进行鉴权。 开发者需要在客户端通过 SDK 接口获取 TOKEN 后传给服务端,然后在服务端凭借此 TOKEN 调用防沉迷服务的 REST API。

API Base 为 https://tds-tapsdk.cn.tapapis.com

获取鉴权 Token

string token = AntiAddictionUIKit.CurrentToken;

鉴权 Token 永久有效。

检查玩家当前能否游戏

curl -X POST \
-H "Content-Type: application/json" \
-H 'Authorization: {{token}}' \
https://tds-tapsdk.cn.tapapis.com/anti-addiction/v1/clients/{{clientId}}/users/{{userIdentifier}}/playable

其中:

  • {{token}} 需替换为客户端获取的鉴权 token
  • {{clientId}} 需替换为 开发者中心后台游戏服务 > 应用配置 中的 Client ID。
  • {{userIdentifier}} 需替换为游戏在调用 防沉迷认证 时使用的玩家唯一标识

以下情况的响应状态码均为 200:

// 实名认证失败
{
"success": true,
"data": {
"status": 2,
"anti_addiction_token": "",
"age_limit": 18,
"has_auth_record": false
}
}

// 成年玩家
{
"success":true,
"data":{
"code":200,
"can_play":true,
"message":"游戏时间不受限制",
"remain_time":60,
"cost_time":0,
"restrict_type":0,
"title":"健康游戏提示",
"description":"当前为成年人账号"
}
}

// 未成年玩家,当前可以游戏
{
"success":true,
"data":{
"code":200,
"can_play":true,
"message":"游戏允许时间",
"remain_time": {{remainTime}},
"cost_time": {{costtime}},
"restrict_type":1,
"title":"健康游戏提示","description":"你当前为未成年账号,已被纳入防沉迷系统。根据国家相关规定,周五、周六、周日及法定节假日 20 点 - 21 点之外为健康保护时段。你今日游戏时间还剩余${remainTime}分钟,请注意适当休息。"
}
}

// 未成年玩家,当前不可游戏
{
"success":true,
"data":{
"code":200,
"can_play":false,
"message":"游戏时间耗尽",
"remain_time": 0,
"cost_time": 60,
"restrict_type":1,
"title":"健康游戏提示",
"description":"你当前为未成年账号,已被纳入防沉迷系统。根据国家相关规定,周五、周六、周日及法定节假日 20 点 - 21 点之外为健康保护时段。当前时间段无法游玩,请合理安排时间。"
}
}

Token 解析错误会返回 401 错误:

{
"success":false,
"data":{
"code":16,
"error":"实名认证失败",
"error_description":"未实名用户不能进入游戏",
"msg":"该账号没有通过实名认证"
}
}

检查玩家消费是否受限

充值金额以分为单位,比如检查玩家是否可以消费 1 元(100 分):

curl -X POST \
-H "Content-Type: application/json" \
-H 'Authorization: {{token}}' \
-d '{"amount": 100}' \
https://tds-tapsdk.cn.tapapis.com/anti-addiction/v1/clients/{{clientId}}/users/{{userIdentifier}}/payable

消费受限和不受限时响应的状态码都是 200:

// 受限
{
"success":true,
"data":{
"code":200,
"status":false,
"message":"限额提示",
"title":"健康消费提示",
"description":"允许充值根据国家相关规定,未满8周岁:不提供付费服务;8-16周岁以下:单笔付费不超过50元,每月累计不超过200元;16-18周岁以下:单笔付费不超过100元,每月累计不超过400元。"
}
}

// 允许
{
"success":true,
"data":{
"code":200,
"status":true,
"message":"限额提示",
"title":"健康消费提示",
"description":"允许充值根据国家相关规定,未满8周岁:不提供付费服务;8-16周岁以下:单笔付费不超过50元,每月累计不超过200元;16-18周岁以下:单笔付费不超过100元,每月累计不超过400元。"
}
}

金额格式异常时返回 400 错误:

{
"success":false,
"data":{
"code":3,
"error":"上传金额不正确",
"error_description":"金额大于等于0并小于100_000_000_000","msg":"请输入正确的金额格式"
}
}

实名认证失败(包括 Token 解析错误)时返回 401 错误:

{
"success":false,
"data":{
"code":16,
"error":"实名认证失败",
"error_description":"未实名用户不能进入游戏",
"msg":"该账号没有通过实名认证"}
}
}

上报消费金额

玩家充值 1 元(100 分),提交消费金额:

curl -X POST \
-H "Content-Type: application/json" \
-H 'Authorization: {{token}}' \
-d '{"amount": 100}' \
https://tds-tapsdk.cn.tapapis.com/anti-addiction/v1/clients/{{clientId}}/users/{userIdentifier}/payments

上报成功时响应的状态码为 200,返回结果:

{
"success":true,
"data":{"message":"上传金额成功"}
}

金额格式异常时返回 400 错误:

{
"success":false,
"data":{
"code":3,
"error":"上传金额不正确",
"error_description":"金额大于等于0并小于100_000_000_000","msg":"请输入正确的金额格式"
}
}

常见问题

如何开通实名认证与防沉迷服务

可以在 开发者中心后台 > 游戏服务 > 生态服务 > 合规认证 处自助开通服务。目前提供两种方案,游戏开通时选择其中一种:

  • 有版号。完成控制台提示的前置条件,点击开通,然后配置好中宣部参数
    • 将中宣部系统后台的游戏备案识别码、应用标识、应用密钥填写到 TapTap 开发者中心后台对应处。
    • 将 TapTap 开发者中心后台显示的 IP 白名单地址复制、填写到中宣部系统后台。
  • 暂无版号。无版号游戏无法配置中宣部参数,可直接选择开通,等游戏有了版号,可以配置中宣部参数并切换到有版号方案。切换后客户端代码不受影响,不需要修改。

SDK 自带哪些用户界面(UI)

实名认证和防沉迷 SDK 提供的用户界面主要在防沉迷授权阶段,可参考功能介绍文档中的界面预览。

授权失败

在实名认证时使用 TapTap 快速认证服务提示「授权失败」,请至后台配置签名证书

未查询到实名认证配置

实名认证时使用手动输入实名信息服务提示「未查询到实名认证配置」,原因是未开启实名认证服务,需要在 开发者中心后台 > 游戏服务 > 生态服务 > 合规认证 处自助开通服务。

userIdentifier is empty

调用认证接口时需要传入的玩家唯一标识 userIdentifier 参数值为空,建议开发者对此做非空判断。

未弹出实名认证窗口/未收到回调

这种情况一般是仅调用了初始化防沉迷 UI 模块代码,也就是说只完成了 SDK 的初始化,同时注册防沉迷的消息监听。

触发实名认证弹窗必须调用 认证接口,之后才会收到回调。

重复认证

我们预期同一个玩家认证过一次之后不再触发弹窗,防沉迷服务直接使用第一次认证的结果,这样用户体验更好。

如果出现重复认证,可以按照以下思路排查:

  • 首先确认游戏使用的 玩家唯一标识 userIdentifier 符合要求。如果同一个玩家用的 userIdentifier 会发生改变,在防沉迷服务中会被视为不同用户,导致重复认证。这个时候需要游戏传入合适的 userIdentifier,建议接入 TDS 内建账户系统,用 objectId 作为玩家唯一标识;或者使用单纯 TapTap 用户认证,传入 openidunionid 作为玩家唯一标识。
  • 如果是有版号游戏,请确认在开发者中心后台填写的参数无误,尤其需要注意游戏方是否在中宣部配置 IP 白名单,如果没有配置,请求中宣部接口会失败,导致重复认证。

注意事项

玩家唯一标识 userIdentifier 参数说明

第一次认证会触发实名认证弹窗,让玩家授权游戏获取 TapTap 实名信息或输入身份信息,认证通过后,后面每一次以同样的 userIdentifier 调用认证接口都会直接拿到第一次认证的结果,不再触发弹窗。

因此,同一个用户的唯一标识应该要保证唯一性。