跳到主要内容
版本:v4

API 参考

注意事项

初始化要求

除了 TapSDK_RestartAppIfNecessary 之外,调用其他所有 API 函数前必须先成功调用 TapSDK_Init 进行初始化。 未初始化或初始化失败时调用其他函数将返回错误或者非预期结果。

数据类型定义

基础类型

typedef char ErrMsg[1024];       // 错误信息,最大长度 1023 字节 + '\0'
typedef void (T_CALLTYPE *callback_t)(TapEventID, void *); // 回调函数类型
typedef int64_t TapSDK_ErrorCode; // 错误码,取值请参考枚举值 TapSDK_ErrorCode_*

#pragma pack(push, 8)

// 错误信息结构体
typedef struct {
TapSDK_ErrorCode code; // 错误码
const char* message; // 错误信息
} TapSDK_Error;

#pragma pack(pop)

枚举类型

TapSDK_Init_Result

SDK 初始化结果枚举:

enum class TapSDK_Init_Result : uint32_t {
OK = 0, // 初始化成功
FailedGeneric = 1, // 其他错误
NoPlatform = 2, // 未找到 TapTap 平台
NotLaunchedByPlatform = 3, // 未通过 TapTap 启动
PlatformVersionMismatch = 4 // 平台版本过旧,请引导用户升级 TapTap 至最新版本,再重新运行游戏
};

TapUser_AsyncAuthorize_Result

用户授权请求结果枚举:

enum class TapUser_AsyncAuthorize_Result : uint32_t {
Unknown = 0, // 未知错误,通常由于未初始化(未调用 TapSDK_Init)或初始化失败导致
OK = 1, // 成功发起授权流程
Failed = 2, // 发起授权流程失败,建议提示用户重试
InFlight = 3 // 授权流程正在执行中,建议忽略错误或提示用户等待
};

TapEventID

事件 ID 枚举:

enum class TapEventID : uint32_t {
Unknown = 0,
AuthorizeFinished = 2002, // 授权完成事件
GamePlayableStatusChanged = 4001, // 游戏可玩状态变更事件
DLCPlayableStatusChanged = 4002, // DLC 可玩状态变更事件

CloudSaveList = 6001, // 获取云存档列表
CloudSaveCreate = 6002, // 创建云存档
CloudSaveUpdate = 6003, // 更新云存档
CloudSaveDelete = 6004, // 删除云存档
CloudSaveGetData = 6005, // 获取云存档数据
CloudSaveGetCover = 6006, // 获取云存档封面
};

TapSDK_ErrorCode

错误码枚举:

enum {
TapSDK_ErrorCode_Success = 0, // 请求执行成功
TapSDK_ErrorCode_Unknown = 1, // 未知错误
TapSDK_ErrorCode_Unauthorized = 2, // 用户凭证失效,请引导用户重新登录 TapTap
TapSDK_ErrorCode_MethodNotAllowed = 3, // 不允许的接口请求
TapSDK_ErrorCode_Unimplemented = 4, // 接口未实现
TapSDK_ErrorCode_InvalidArguments = 5, // 参数错误
TapSDK_ErrorCode_Forbidden = 6, // 用户没有当前动作的权限
TapSDK_ErrorCode_UserIsDeactivated = 7, // 用户被冻结
TapSDK_ErrorCode_InternalServerError = 8, // 服务器内部错误
TapSDK_ErrorCode_InternalSdkError = 9, // SDK内部错误
TapSDK_ErrorCode_NetworkError = 10, // 网络错误

TapSDK_ErrorCode_CloudSave_InvalidFileSize = 400000, // 非法的存档文件/封面大小
TapSDK_ErrorCode_CloudSave_UploadRateLimit = 400001, // 存档上传频率超限
TapSDK_ErrorCode_CloudSave_FileNotFound = 400002, // 存档文件不存在
TapSDK_ErrorCode_CloudSave_FileCountLimitPerClient = 400003, // 用户在该用下存档文件数量超限
TapSDK_ErrorCode_CloudSave_StorageSizeLimitPerClient = 400004, // 用户在该应用下使用存储空间超限
TapSDK_ErrorCode_CloudSave_TotalStorageSizeLimit = 400005, // 用户总使用存储空间超限
TapSDK_ErrorCode_CloudSave_Timeout = 400006, // 请求超时,通常是由于网络卡顿,创建/更新存档耗时过长导致
TapSDK_ErrorCode_CloudSave_ConcurrentCallDisallowed = 400007, // 不允许并发调用的请求
TapSDK_ErrorCode_CloudSave_StorageServerError = 400008, // 存储服务故障
TapSDK_ErrorCode_CloudSave_InvalidName = 400009, // 存档名称不合法
};

结构体类型

AuthorizeFinishedResponse

授权完成响应结构体:

struct AuthorizeFinishedResponse {
bool is_cancel; // 用户是否取消授权
char error[1024]; // 错误信息
char token_type[32]; // Token 类型
char kid[8*1024]; // Key ID
char mac_key[8*1024]; // MAC 密钥
char mac_algorithm[32]; // MAC 算法
char scope[1024]; // 权限范围
};

GamePlayableStatusChangedResponse

游戏可玩状态变更响应结构体:

struct GamePlayableStatusChangedResponse {
bool is_playable; // 游戏本体是否可玩
};

DLCPlayableStatusChangedResponse

DLC 可玩状态变更响应结构体:

struct DLCPlayableStatusChangedResponse {
char dlc_id[32]; // DLC ID
bool is_playable; // DLC 是否可玩
};

SDK 核心接口

TapSDK_RestartAppIfNecessary

检查是否需要重启应用。

bool TapSDK_RestartAppIfNecessary(const char *clientID);

参数:

  • clientID:客户端 ID

返回值:

  • true:需要重启,TapTap 将重新打开游戏,请立即退出游戏进程
  • false:不需要重启,可以继续初始化

使用示例:

const char* clientID = "your_client_id";
if (TapSDK_RestartAppIfNecessary(clientID)) {
std::cout << "需要重启应用" << std::endl;
return 0; // 立即退出
}

注意事项:

  • 此函数必须在TapSDK_Init之前调用
  • 如果返回 true,应立即退出程序,等待 TapTap 重启游戏

TapSDK_Init

初始化 SDK。

TapSDK_Init_Result TapSDK_Init(ErrMsg *errMsg, const char *pubKey);

参数:

  • errMsg:错误信息缓冲区,长度为 1024 字节
  • pubKey:从 TapTap 开发者中心获取的公钥

返回值:

  • TapSDK_Init_Result:初始化结果枚举

使用示例:

ErrMsg errMsg;
const char* pubKey = "your_public_key";
TapSDK_Init_Result result = TapSDK_Init(&errMsg, pubKey);

switch (result) {
case TapSDK_Init_Result::OK:
std::cout << "初始化成功" << std::endl;
break;
case TapSDK_Init_Result::NoPlatform:
std::cout << "未找到 TapTap 平台,请下载并安装 TapTap 启动器" << std::endl;
std::cout << "下载地址:https://www.taptap.cn/mobile" << std::endl;
break;
case TapSDK_Init_Result::NotLaunchedByPlatform:
std::cout << "游戏未通过 TapTap 启动器启动,请从启动器重新打开游戏" << std::endl;
break;
case TapSDK_Init_Result::PlatformVersionMismatch:
std::cout << "平台版本不匹配,请升级 TapTap 启动器或游戏到最新版本" << std::endl;
break;
default:
std::cout << "初始化失败: " << errMsg << std::endl;
std::cout << "请关闭游戏,并从 TapTap 重新打开" << std::endl;
break;
}

TapSDK_Shutdown

关闭 SDK,释放资源。

bool TapSDK_Shutdown();

返回值:

  • true:成功关闭
  • false:关闭失败(通常由于未初始化(未调用 TapSDK_Init)或初始化失败导致)

使用示例:

if (TapSDK_Shutdown()) {
std::cout << "SDK 已成功关闭" << std::endl;
} else {
std::cout << "SDK 关闭失败" << std::endl;
}

TapSDK_GetClientID

获取当前客户端 ID。

bool TapSDK_GetClientID(char *buffer);

参数:

  • buffer:用于存储客户端 ID 的缓冲区,固定长度 256 字节

返回值:

  • true:成功获取
  • false:获取失败(通常由于未初始化(未调用 TapSDK_Init)或初始化失败导致)

使用示例:

char clientID[256];
if (TapSDK_GetClientID(clientID)) {
std::cout << "Client ID: " << clientID << std::endl;
} else {
std::cout << "获取 Client ID 失败,请检查 SDK 是否已正确初始化" << std::endl;
}

回调相关功能

内存管理
  • 回调函数中的数据指针 data 指向的内存由 SDK 管理,调用者无需释放
  • 回调函数返回后,SDK 会自动释放该内存,如需长期使用,请自行复制一份

TapSDK_RegisterCallback

注册事件回调。

void TapSDK_RegisterCallback(TapEventID eventID, callback_t callback);

参数:

  • eventID:事件 ID
  • callback:回调函数

使用示例:

void T_CALLTYPE OnAuthorizeFinished(TapEventID eventID, void* data) {
if (eventID == TapEventID::AuthorizeFinished) {
AuthorizeFinishedResponse* response = (AuthorizeFinishedResponse*)data;
// 处理授权完成事件
}
}

// 注册回调
TapSDK_RegisterCallback(TapEventID::AuthorizeFinished, OnAuthorizeFinished);

TapSDK_UnregisterCallback

注销事件回调。

void TapSDK_UnregisterCallback(TapEventID eventID, callback_t callback);

参数:

  • eventID:事件 ID
  • callback:要注销的回调函数

使用示例:

// 注销回调
TapSDK_UnregisterCallback(TapEventID::AuthorizeFinished, OnAuthorizeFinished);

TapSDK_RunCallbacks

处理回调事件,建议每帧调用。

void TapSDK_RunCallbacks();

使用示例:

// 在游戏主循环中调用
while (gameRunning) {
TapSDK_RunCallbacks(); // 处理 SDK 事件

// 游戏逻辑
UpdateGame();
RenderGame();

Sleep(16); // 控制帧率
}

用户相关功能

TapUser_AsyncAuthorize

异步请求用户授权(简化版本)。

TapUser_AsyncAuthorize_Result TapUser_AsyncAuthorize(const char* scopes);

参数:

  • scopes:权限范围字符串,多个权限用逗号分隔

返回值:

  • TapUser_AsyncAuthorize_Result::Unknown:未知错误,通常由于未初始化或初始化失败导致
  • TapUser_AsyncAuthorize_Result::OK:成功发起授权流程,等待用户确认
  • TapUser_AsyncAuthorize_Result::Failed:发起授权流程失败,建议提示用户重试
  • TapUser_AsyncAuthorize_Result::InFlight:授权流程正在执行中,建议忽略或提示用户等待

常用权限范围:

  • "public_profile":基础用户信息
  • "user_friends":好友信息
  • "public_profile,user_friends":多个权限

使用示例:

// 注册授权完成回调
TapSDK_RegisterCallback(TapEventID::AuthorizeFinished, OnAuthorizeFinished);

// 请求基础用户信息权限
TapUser_AsyncAuthorize_Result result = TapUser_AsyncAuthorize("public_profile");
switch (result) {
case TapUser_AsyncAuthorize_Result::OK:
std::cout << "授权请求已发送,等待用户确认" << std::endl;
break;
case TapUser_AsyncAuthorize_Result::Failed:
std::cout << "发起授权失败,请重试" << std::endl;
break;
case TapUser_AsyncAuthorize_Result::InFlight:
std::cout << "授权流程正在进行中,请等待" << std::endl;
break;
case TapUser_AsyncAuthorize_Result::Unknown:
std::cout << "授权失败,请检查 SDK 初始化状态" << std::endl;
break;
}

TapUser_GetOpenID

获取用户 OpenID。

bool TapUser_GetOpenID(char *buffer);

参数:

  • buffer:用于存储 OpenID 的缓冲区,固定长度 256 字节

返回值:

  • true:成功获取
  • false:获取失败(通常由于未初始化、初始化失败)

使用示例:

char openID[256];
if (TapUser_GetOpenID(openID)) {
std::cout << "用户 OpenID: " << openID << std::endl;
} else {
std::cout << "获取 OpenID 失败,请检查 SDK 初始化状态和用户授权状态" << std::endl;
}

正版验证功能

TapApps_IsOwned

检查用户是否拥有当前游戏。

使用说明
  • 仅付费游戏需要调用:免费游戏无需验证所有权
  • 初始化时已验证TapSDK_Init 成功时已验证游戏本体所有权
  • 运行时监控:游戏运行过程中,只有当用户失去所有权(如退款)时才会返回 false
bool TapApps_IsOwned();

返回值:

  • true:用户拥有当前游戏
  • false:用户未拥有当前游戏(通常发生在退款等情况)

使用示例:

// 仅付费游戏需要检查
if (TapApps_IsOwned()) {
std::cout << "用户拥有此游戏,可以继续运行" << std::endl;
// 继续游戏逻辑
} else {
std::cout << "用户已失去游戏所有权(可能已退款)" << std::endl;
// 保存进度并退出游戏
SaveGameAndExit();
return -1;
}

DLC 相关功能

TapDLC_IsOwned

查询用户是否拥有指定的 DLC。

bool TapDLC_IsOwned(const char *dlc_id);

参数:

  • dlc_id:DLC ID

返回值:

  • true:用户拥有该 DLC
  • false:用户未拥有该 DLC

使用示例:

const char* dlcID = "expansion_pack_1";
if (TapDLC_IsOwned(dlcID)) {
std::cout << "用户拥有 DLC: " << dlcID << std::endl;
EnableDLCContent(dlcID);
} else {
std::cout << "用户未拥有 DLC: " << dlcID << std::endl;
DisableDLCContent(dlcID);
}

TapDLC_ShowStore

显示指定 DLC 的商店页面。

bool TapDLC_ShowStore(const char *dlc_id);

参数:

  • dlc_id:DLC ID

返回值:

  • true:成功显示商店页面
  • false:显示失败

使用示例:

const char* dlcID = "expansion_pack_1";
if (!TapDLC_IsOwned(dlcID)) {
// 用户未拥有 DLC,引导购买
if (TapDLC_ShowStore(dlcID)) {
std::cout << "已打开 DLC 商店页面" << std::endl;
} else {
std::cout << "打开 DLC 商店页面失败" << std::endl;
}
}

事件处理示例

完整的事件处理示例

#include "taptap_api.h"
#include <iostream>

// 授权完成事件处理
void T_CALLTYPE OnAuthorizeFinished(TapEventID eventID, void* data) {
if (eventID == TapEventID::AuthorizeFinished) {
AuthorizeFinishedResponse* response = (AuthorizeFinishedResponse*)data;

if (response->is_cancel) {
std::cout << "用户取消了授权" << std::endl;
} else if (strlen(response->error) > 0) {
std::cout << "授权失败: " << response->error << std::endl;
} else {
std::cout << "授权成功!" << std::endl;
std::cout << "Token 类型: " << response->token_type << std::endl;
std::cout << "权限范围: " << response->scope << std::endl;

// 获取用户信息
char openID[256];
if (TapUser_GetOpenID(openID)) {
std::cout << "用户 OpenID: " << openID << std::endl;
}
}
}
}

// 游戏可玩状态变化事件处理
void T_CALLTYPE OnGameStatusChanged(TapEventID eventID, void* data) {
if (eventID == TapEventID::GamePlayableStatusChanged) {
GamePlayableStatusChangedResponse* response = (GamePlayableStatusChangedResponse*)data;

if (response->is_playable) {
std::cout << "游戏现在可以继续运行" << std::endl;
} else {
std::cout << "游戏不再可用,可能已被退款" << std::endl;
// 应该保存游戏进度并退出
SaveGameAndExit();
}
}
}

// DLC 状态变化事件处理
void T_CALLTYPE OnDLCStatusChanged(TapEventID eventID, void* data) {
if (eventID == TapEventID::DLCPlayableStatusChanged) {
DLCPlayableStatusChangedResponse* response = (DLCPlayableStatusChangedResponse*)data;

std::cout << "DLC " << response->dlc_id
<< (response->is_playable ? " 现在可用" : " 现在不可用") << std::endl;

if (response->is_playable) {
EnableDLCFeatures(response->dlc_id);
} else {
DisableDLCFeatures(response->dlc_id);
}
}
}

void SetupEventHandlers() {
// 注册所有事件回调
TapSDK_RegisterCallback(TapEventID::AuthorizeFinished, OnAuthorizeFinished);
TapSDK_RegisterCallback(TapEventID::GamePlayableStatusChanged, OnGameStatusChanged);
TapSDK_RegisterCallback(TapEventID::DLCPlayableStatusChanged, OnDLCStatusChanged);
}