XDSDK v7 C++(Windows)快速接入指南
环境要求
- Windows 10 x64 及以上。
- MSVC(Visual Studio 2019+,即 MSVC 14.2+)。
- C++17 或更高标准。
- CMake ≥ 3.20(仅 CMake 接入方式需要)。
SDK 包结构
XDSDK_Win_vX.X.X/
├── include/ # C API 头文件(推荐)
│ └── xdsdk/
│ ├── xdg_common_api.h
│ └── xdg_account_api.h
├── include_cpp/ # C++ API 头文件
│ └── xdsdk/
├── lib/ # 链接库 (.lib)
├── bin/ # 运行时 DLL + resources/
├── cmake/ # CMake find_package 支持
├── XDSDK.props # Visual Studio 属性表
└── XDConfig.json.template
接入配置
方式一:Visual Studio
- 解压 SDK 到任意目录
- Visual Studio 菜单:视图 → 其他窗口 → 属性管理器
- 右键项目 → 添加现有属性表,选择
XDSDK.props
XDSDK.props 自动完成以下配置:
- 添加
include/到头文件搜索路径。 - 添加
lib/并链接xdsdk_common.lib、xdsdk_account.lib。 - 构建后自动将
bin/下所有 DLL 和resources/复制到输出目录。
属性表仅配置了
include/(C API)。如需使用include_cpp/下的 C++ API,请在项目属性中手动添加该路径。
也可以直接编辑 .vcxproj 文件,在 <ImportGroup Label="PropertySheets"> 中添加:
<ImportGroup Label="PropertySheets">
<Import Project="path\to\XDSDK_Win_vX.X.X\XDSDK.props" />
</ImportGroup>
同时确保项目设置了 C++17:
<PropertyGroup>
<LanguageStandard>stdcpp17</LanguageStandard>
</PropertyGroup>
方式二:CMake
find_package(XDSDK CONFIG REQUIRED PATHS "path/to/XDSDK/cmake")
target_link_libraries(MyGame PRIVATE XDSDK::common XDSDK::account)
# 自动将运行时 DLL 和 resources/ 复制到输出目录
xdsdk_copy_runtime_dlls(MyGame)
配置文件
将 XDConfig.json.template 重命名为 XDConfig.json,填写后放到游戏 exe 同级目录:
game.exe
XDConfig.json ← 放这里
{
"client_id": "你的 Client ID",
"region_type": "CN",
"tapsdk": {
"client_id": "TapTap Client ID",
"client_token": "TapTap Client Token",
"client_public_key": "TapTap Client Public Key",
"db_config": {
"enable": true,
"channel": "steam",
"game_version": "1.0.0"
}
}
}
国内 TapTap PC 防沉迷/实名:需
region_type为"CN"、初始化package_type为"PC-TapTap",且tapsdk.client_public_key非空——三者同时满足才会触发防沉迷(见下方「防沉迷 / 实名合规」)。缺client_public_key会导致防沉迷不生效。海外区(非 CN)不触发。
初始化
#include <xdsdk/xdg_common_api.h>
#include <xdsdk/xdg_account_api.h>
#include <windows.h>
// 前置声明
void on_user_status(int status_code, const char* message);
void on_init(int success, const char* msg); // success: 1/0;msg: 成功为 "OK"/描述,失败为错误信息
int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) {
XDG_SetUserStatusCallback(on_user_status);
// 简单初始化:从 XDConfig.json 读取配置(package_type 为空)
XDG_InitSDK(on_init);
// 带参数初始化:channel / lang / package_type / game_phase
// 国内 TapTap PC 防沉迷必须走这个,且 package_type 传 "PC-TapTap"(否则防沉迷不触发):
// XDG_InitSDKWithParam("steam", XDG_LANG_AUTO, "PC-TapTap", NULL, on_init);
MSG msg;
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
初始化参数说明(XDG_InitSDKWithParam):
| 参数 | 说明 |
|---|---|
channel | 渠道名,如 "steam"、"epic"(可传 NULL) |
lang | 语言,使用 XDG_LANG_* 常量 |
package_type | 包体类型,来自初始化参数、不是 XDConfig.json。常见值:"PC-TapTap"、"PC-Steam"。国内 TapTap PC 防沉迷要求此值为 "PC-TapTap" |
game_phase | 包体阶段,如 "dev"/"release",透传到公共参数与埋点(可传 NULL) |
⚠️ 国内接入方注意:
XDG_InitSDK不设置package_type,会导致防沉迷不触发。国内 TapTap PC 必须用XDG_InitSDKWithParam(..., "PC-TapTap", ...)初始化。
登录
void on_login_success(const char* user_json) {
// user_json: {"user_id":"...","name":"...","avatar":"...","login_type":5,"token":"..."}
}
void on_login_error(const char* error_json) {
// error_json: {"code":...,"message":"..."}
//
// 国内防沉迷/实名校验失败时:
// {"code":60001,"message":"compliance_failed",
// "detail":"{\"code\":62011,\"reason\":\"anti_addiction_blocked\",
// \"title\":\"...\",\"description\":\"...\"}"}
// detail 为 JSON 字符串,内含真实原因码/reason 及可展示的 title/description(见下方合规章节)。
}
// 在初始化回调中发起登录
void on_init(int success, const char* msg) {
if (!success) return;
XDG_Login(XDG_LOGIN_TYPE_DEFAULT, on_login_success, on_login_error);
}
登录类型
| 常量 | 值 | 说明 |
|---|---|---|
XDG_LOGIN_TYPE_DEFAULT | 0 | 默认(显示登录选择界面) |
XDG_LOGIN_TYPE_GUEST | 1 | 游客登录 |
XDG_LOGIN_TYPE_TAPTAP | 5 | TapTap 登录 |
用户状态
在调用登录前,通过 XDG_SetUserStatusCallback 注册用户状态回调。
void on_user_status(int status_code, const char* message) {
if (status_code == XDG_USER_STATUS_LOGOUT) {
// 返回登录页面并展示登录按钮
// 注意:此时不要再调用自动登录接口
}
}
状态码
| 常量 | 值 | 触发时机 |
|---|---|---|
XDG_USER_STATUS_LOGOUT | 0 | 登出 |
XDG_USER_STATUS_BIND | 1 | 绑定第三方账号完成 |
XDG_USER_STATUS_UNBIND | 2 | 解绑第三方账号完成 |
XDG_USER_STATUS_PROTOCOL_AGREED | 3 | 用户同意协议 |
XDG_USER_STATUS_SUPPORT_NO_UNREAD | 4 | 客服无未读消息 |
XDG_USER_STATUS_SUPPORT_HAS_UNREAD | 5 | 客服有未读消息 |
XDG_USER_STATUS_COMPLIANCE_TOAST | 10 | 防沉迷健康提示(轻提示) |
XDG_USER_STATUS_COMPLIANCE_ALERT | 11 | 防沉迷提示(需确认弹窗) |
XDG_USER_STATUS_COMPLIANCE_EXIT | 12 | 防沉迷要求退出(SDK 已登出,须返回登录) |
合规状态(
COMPLIANCE_TOAST/ALERT/EXIT,仅国内区)的message是 JSON 字符串:{"title":"标题","description":"正文","duration":展示秒数}。详见下方「防沉迷 / 实名合规」。
防沉迷 / 实名合规(国内)
国内区通过 TapSDK 完成实名与防沉迷校验。这是 SDK 登录链路的一部分,游戏侧无需单独调用,但必须处理下述回调与错误。
触发条件
同时满足才触发(否则直接跳过、不影响登录):
region_type为"CN";- 初始化
package_type为"PC-TapTap"; - 配置
tapsdk.client_public_key非空; - 游戏从 TapTap PC 客户端启动、且 TapTap 已登录(PC 防沉迷按 TapTap 账号执行)。
海外区(非 CN)一律跳过,直接登录成功。
时机
第三方登录成功 → XD 登录成功 → 触发实名/防沉迷校验 → 通过后才回调登录成功。也就是说:收到 on_login_success 即表示合规已通过。
登录期校验失败
登录失败回调 on_login_error 返回:
{
"code": 60001,
"message": "compliance_failed",
"detail": "{\"code\":62011,\"reason\":\"anti_addiction_blocked\",\"title\":\"...\",\"description\":\"...\"}"
}
- 对外
code统一为60001(通用失败); detail为 JSON 字符串,字段:字段 说明 code真实原因码: 62010实名未完成/取消/失败;62011防沉迷限制需退出reason机器可读原因,如 anti_addiction_blocked/realname_canceled/compliance_startup_timeout等title/description可展示文案(防沉迷拦截时有值;实名类失败可能为空)
运行期动作(登录成功后)
登录后,防沉迷限制通过用户状态回调持续推送(message 为 {"title","description","duration"} JSON):
| 状态码 | 常量 | 游戏侧应做 |
|---|---|---|
| 10 | XDG_USER_STATUS_COMPLIANCE_TOAST | 展示轻提示(可按 duration 秒自动消失) |
| 11 | XDG_USER_STATUS_COMPLIANCE_ALERT | 展示需用户确认的弹窗 |
| 12 | XDG_USER_STATUS_COMPLIANCE_EXIT | SDK 已自动登出,游戏须结束当前会话、返回登录界面(合规强制,不可忽略) |
void on_user_status(int status_code, const char* message) {
switch (status_code) {
case XDG_USER_STATUS_COMPLIANCE_TOAST: /* 解析 message JSON,弹轻提示 */ break;
case XDG_USER_STATUS_COMPLIANCE_ALERT: /* 解析 message JSON,弹确认框 */ break;
case XDG_USER_STATUS_COMPLIANCE_EXIT: /* 已登出,返回登录界面 */ break;
case XDG_USER_STATUS_LOGOUT: /* ... */ break;
}
}
⚠️ 合规是强制要求:
COMPLIANCE_EXIT与登录失败的防沉迷拦截,游戏侧都必须响应(阻断游戏 / 返回登录),不得提供绕过入口。
API 参考
Common 模块(xdg_common_api.h)
| 函数 | 说明 |
|---|---|
XDG_InitSDK(callback) | 初始化 SDK,从 XDConfig.json 读取配置 |
XDG_InitSDKWithParam(channel, lang, package_type, game_phase, callback) | 带渠道/语言/包类型/包体阶段参数初始化(game_phase 透传到公共参数与埋点,可传 NULL) |
XDG_IsInitialized() | 是否已初始化,返回 1/0 |
XDG_SetLanguage(lang) | 设置语言,使用 XDG_LANG_* 常量 |
XDG_SetTargetCountryOrRegion(code) | 设置目标国家/地区,如 "KR" |
XDG_SetGatewayOverride(primary, secondary) | 仅测试用:初始化前覆盖 XD 网关地址以切到测试环境;传 NULL/空清除,正式环境勿调用 |
XDG_OpenWebPage(url, callback) | 打开网页 |
XDG_TrackUser(user_id, props_json) | TapDB 追踪用户 |
XDG_TrackRole(role_id, name, level, server_id, props_json) | TapDB 追踪角色 |
XDG_TrackEvent(event_name, props_json) | TapDB 追踪自定义事件 |
XDG_GetDeviceId() | 获取设备 ID |
XDG_RequestAnnouncementUnread(server, channel, extra, callback) | 查询公告未读状态 |
XDG_OpenAnnouncementPage(server, channel, extra, callback) | 打开公告页面 |
XDG_GetVersion() | 获取 SDK 版本号 |
Account 模块(xdg_account_api.h)
| 函数 | 说明 |
|---|---|
XDG_Login(type, on_success, on_error) | 登录 |
XDG_Logout() | 登出 |
XDG_IsLoggedIn() | 是否已登录,返回 1/0 |
XDG_GetCurrentUser() | 获取当前用户 JSON,未登录返回 "{}" |
XDG_OpenUserCenter() | 打开用户中心 |
XDG_Bind(type, callback) | 绑定第三方账号(callback 为 XDG_OperationCallback) |
XDG_Unbind(type, callback) | 解绑第三方账号(callback 为 XDG_OperationCallback) |
XDG_GetBindList() | 获取已绑定账号列表 JSON |
XDG_SetUserStatusCallback(callback) | 注册用户状态回调(传 NULL 取消) |
回调类型
| 回调 typedef | 签名 | 用于 |
|---|---|---|
XDG_InitCallback | void(int success, const char* message) | XDG_InitSDK / XDG_InitSDKWithParam |
XDG_LoginSuccessCallback | void(const char* user_json) | XDG_Login 成功 |
XDG_LoginErrorCallback | void(const char* error_json) | XDG_Login 失败 |
XDG_UserStatusCallback | void(int status_code, const char* message) | XDG_SetUserStatusCallback |
XDG_OperationCallback | void(const char* result_json) | XDG_Bind / XDG_Unbind,result_json 形如 {"code":0,"message":"success"} |
XDG_WebCallback | void(int action, const char* data_json) | XDG_OpenWebPage / XDG_OpenAnnouncementPage;action:0=页面关闭,1=页面消息 |
XDG_AnnouncementUnreadCallback | void(int has_unread) | XDG_RequestAnnouncementUnread;has_unread:1=有未读,0=无 |
语言常量
| 常量 | 值 | 说明 |
|---|---|---|
XDG_LANG_AUTO | -1 | 自动检测 |
XDG_LANG_ZH_HANS | 0 | 简体中文 |
XDG_LANG_ZH_HANT | 1 | 繁体中文 |
XDG_LANG_EN | 2 | 英语 |
XDG_LANG_TH | 3 | 泰语 |
XDG_LANG_ID | 4 | 印尼语 |
XDG_LANG_KO | 5 | 韩语 |
XDG_LANG_JA | 6 | 日语 |
XDG_LANG_DE | 7 | 德语 |
XDG_LANG_FR | 8 | 法语 |
XDG_LANG_PT | 9 | 葡萄牙语 |
XDG_LANG_ES | 10 | 西班牙语 |
XDG_LANG_TR | 11 | 土耳其语 |
XDG_LANG_RU | 12 | 俄语 |
XDG_LANG_VI | 13 | 越南语 |
错误码
回调返回 JSON 中 code 字段的取值:
| 错误码 | 含义 | 建议处理 |
|---|---|---|
| 60000 | 成功 | — |
| 60001 | 通用失败 | 通用错误提示。防沉迷/实名校验失败也归到此码,具体原因见 error_json 的 detail(见「防沉迷 / 实名合规」) |
| 60002 | SDK 未初始化 | 检查初始化顺序 |
| 60010 | 用户取消 | 不弹错误,停留在登录页即可 |
| 60020 | 参数无效 | 检查调用参数 |
| 60030 | 服务不可用 | 提示稍后重试 |
| 60040 | 网络错误 | 提示网络异常,可重试 |
| 62001 | 登录类型不可用 | 该登录方式未配置/不支持 |
| 62002 | Token 过期 | 清理本地态并重新登录 |
| 62003 | 未登录 | 引导登录 |
| 62010 | 实名未完成/取消/失败 | 仅出现在登录失败的 detail.code(外层 code 为 60001) |
| 62011 | 防沉迷限制需退出 | 仅出现在登录失败的 detail.code(外层 code 为 60001) |
| 63001 | 商品无效 | 支付相关 |
| 63002 | 支付处理中 | 支付相关 |
62010/62011是合规真实原因码,不作为对外顶层code,而是放在登录失败detail的 JSON 里;对外顶层code统一为60001。
日志
SDK 运行日志自动写入以下路径(相对于游戏 exe):
resources/logs/xdsdk_<client_id>.log
注意事项
- C API 返回的字符串使用内部静态缓冲区,无需释放,但请在下次调用同一函数前复制。
- 所有回调在 SDK 内部线程触发,如需操作 UI 请切换到主线程。
技术支持
如有问题请联系 SDK 技术支持。