UE5 SDK 开发指南
本文介绍如何在 UE5 项目中接入正版验证和 DLC 校验,当前覆盖 Android 和 Tap PC。当前 UE5 插件的 iOS 正版验证桥接尚未实现,不能在 iOS 构建中使用本页的正版验证和 DLC 接口。
集成前准备
在 Tap PC 平台,开发者还需接入 UE5 启动校验示例。同时,由于游戏购买状态和 DLC 功能依赖 TapTap PC 端处理,建议在启动校验成功后添加TapTap PC 端状态监听,并在状态异常时引导玩家检查网络或重新通过 TapTap PC 端启动游戏。
权限说明
Android 权限说明
该模块需要访问设备中已安装的 Tap 客户端信息。在 Android 11 且工程 targetSdkVersion 大于 29 时,在应用 AndroidManifest.xml 中添加如下配置:
<queries>
<package android:name="com.taptap" />
<package android:name="com.taptap.pad" />
<package android:name="com.taptap.global" />
</queries>
该模块将在 Android 应用中添加如下权限:
<uses-permission android:name="android.permission.REORDER_TASKS" />
SDK 获取
参考 UE5 集成指南完成 TapCore 基础接入。再从下载页下载相同版本的 TapLicense,放入项目的 Plugins 目录并启用。
添加模块依赖
在游戏模块的 <GameModule>.Build.cs 中添加:
PublicDependencyModuleNames.AddRange(new string[]
{
"TapCore",
"TapLicense",
});
修改 Build.cs 后重新生成项目文件并编译。
正版验证
设置授权回调
在 PC 端,游戏需确保在启动校验成功后注册该回调。
正版校验结果通过 ITapLicenseCallback 返回:
#pragma once
#include "CoreMinimal.h"
#include "UObject/Object.h"
#include "TapLicenseCallback.h"
#include "MyLicenseCallback.generated.h"
UCLASS()
class UMyLicenseCallback : public UObject, public ITapLicenseCallback
{
GENERATED_BODY()
public:
virtual void OnLicenseSuccess_Implementation() override
{
// 授权成功
}
virtual void OnLicenseFailed_Implementation() override
{
// 授权失败
}
};
为了避免回调对象被回收,请将它保存在 GameInstance 等长期存在的对象中,并在调用业务接口前创建和注册:
#include "TapLicense.h"
// 在持有者类中声明成员
UPROPERTY()
TObjectPtr<UMyLicenseCallback> LicenseHandler;
// 在持有者的初始化方法中创建并注册回调对象
LicenseHandler = NewObject<UMyLicenseCallback>(this);
TScriptInterface<ITapLicenseCallback> LicenseCallback;
LicenseCallback.SetObject(LicenseHandler.Get());
LicenseCallback.SetInterface(Cast<ITapLicenseCallback>(LicenseHandler.Get()));
UTapLicense::RegisterLicenseCallback(LicenseCallback);
| 回调事件 | Android 端 | PC 端 |
|---|---|---|
授权成功 OnLicenseSuccess(C++ 实现:OnLicenseSuccess_Implementation()) | 当开发者通过 SDK 检查玩家购买状态且结果为已购买时触发,每次检查触发一次。 | 1. 当开发者通过 SDK 检查玩家购买状态且结果为已购买时触发,每次调用触发一次。 2. 当玩家在任意场景下重新完成购买时,SDK 主动触发一次。 |
授权失败 OnLicenseFailed(C++ 实现:OnLicenseFailed_Implementation()) | 不会触发。当开发者通过 SDK 检查玩家购买状态且结果为未购买时,SDK 会主动弹出无法取消的提示窗口来阻止玩家进入游戏。 | 1. 当开发者通过 SDK 检查玩家购买状态且结果为未购买时触发,每次调用触发一次。 2. 当玩家在任意场景下完成退款时,SDK 主动触发一次。 |
不再监听时,使用原回调对象调用 UTapLicense::UnregisterLicenseCallback(LicenseCallback),再释放持有引用。避免重复创建回调对象却不注销旧对象。
检查是否购买游戏
在 Android 端,Check 方法中的参数说明如下:
false(默认值):SDK 首次触发以及在距离首次触发的第 5 天之后再一次会通过 TapTap 客户端来确认当前登录用户是否购买游戏。true:每次接口调用都会通过 TapTap 客户端来确认当前登录用户是否购买过游戏。
在 PC 端 Check 方法中参数无效,SDK 始终会通过 TapTap PC 端完成校验。Tap PC 上必须在启动校验成功后调用。
#include "TapLicense.h"
// 普通检查
UTapLicense::CheckLicense(false);
// 强制检查
UTapLicense::CheckLicense(true);
Android 11 及更高版本的适配
Android 11(API level 30)之后加强了隐私保护策略,引入了大量变更和限制,其中一个重要变更——软件包可见性,将会导致第三方应用无法拉起 TapTap 客户端,从而影响 TapTap 相关功能的正常使用,包括但不限于更新唤起 TapTap、购买验证等功能。
如果没有完成适配,Android 版本为 11 及更高版本的客户端打开游戏会提示「本游戏需要最新版 TapTap 服务支持」,无法正常进入游戏。异常呈现如下图所示:

对此提供如下两种适配方案:
方案一:
编译时将 targetSdkVersion 改为 29(目前设置成 >= 30 会触发该问题)。
方案二:
-
将 gradle build tools 改为 4.1.0+:
classpath 'com.android.tools.build:gradle:4.1.0' -
在 AndroidManifest.xml 里添加
<queries>标签中的内容:<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="string"><application. . .</application><!--添加如下 queries 标签的内容,直接在 manifest 标签下--><queries><package android:name="com.taptap" /><package android:name="com.taptap.pad" /><package android:name="com.taptap.global" /></queries></manifest>
DLC
请确保:
- DLC 商品已正确创建并审核通过,否则 DLC 查询和购买不会成功。DLC 商品配置事项详见 DLC 商品文档。
- 商店资料(路径:商店 - 游戏资料 - 商店资料)中填写 APK 包名并处于已上线状态。
设置查询和购买回调
DLC 回调包含查询回调和购买回调,在 PC 端,游戏需确保在启动校验成功后注册该回调。
DLC 查询和订单变化共用同一个 ITapDLCCallback 回调对象,只需统一注册一次:
#pragma once
#include "CoreMinimal.h"
#include "UObject/Object.h"
#include "TapLicenseCallback.h"
#include "MyDlcCallback.generated.h"
UCLASS()
class UMyDlcCallback : public UObject, public ITapDLCCallback
{
GENERATED_BODY()
public:
virtual void OnQueryCallback_Implementation(
ETapLicenseQueryCode Code, const TMap<FString, bool>& Results) override
{
// 查询回调
}
virtual void OnOrderCallback_Implementation(
const FString& Sku, ETapDLCPurchasedCode Status) override
{
// 购买回调
// 在 Android 端当用户购买成功/失败时触发
// 在 PC 端当用户在 TapTap PC 端完成商品购买或退款时触发
}
};
为了避免回调对象被回收,请将它保存在 GameInstance 等长期存在的对象中,并在初始化成功后创建和注册:
#include "TapLicense.h"
// 在持有者类中声明成员
UPROPERTY()
TObjectPtr<UMyDlcCallback> DlcHandler;
// 在持有者的初始化方法中创建并注册回调对象
DlcHandler = NewObject<UMyDlcCallback>(this);
TScriptInterface<ITapDLCCallback> DlcCallback;
DlcCallback.SetObject(DlcHandler.Get());
DlcCallback.SetInterface(Cast<ITapDLCCallback>(DlcHandler.Get()));
UTapLicense::RegisterDLCCallback(DlcCallback);
不再监听时,用原回调对象构造接口并注销,再释放持有引用:
TScriptInterface<ITapDLCCallback> DlcCallback;
DlcCallback.SetObject(DlcHandler.Get());
DlcCallback.SetInterface(Cast<ITapDLCCallback>(DlcHandler.Get()));
UTapLicense::UnregisterDLCCallback(DlcCallback);
DlcHandler = nullptr;
Android 端:购买回调仅在主动调用购买商品接口时触发。
PC 端:任何在 TapTap 客户端完成支付或退款操作均会触发购买回调,与是否调用购买商品接口无关。
回调参数说明
查询回调中参数 ETapLicenseQueryCode 表示查询结果:
| 回调值 | 数值 | 说明 |
|---|---|---|
OK | 0 | 查询成功。 |
NotInstallTapTap | 1 | 未安装 TapTap 客户端,仅 Android 端返回。 |
Error | 2 | 查询失败。 |
Undefined | 255 | 未知错误。 |
查询成功时,Results 为键值对类型的具体数据:
| 字段 | 说明 |
|---|---|
| key | 查询的商品 SKU ID。 |
| value | 该 DLC 的购买状态:false 表示未购买,true 表示已购买。 |
购买回调中参数 Sku 为购买的商品 SKU ID,参数 ETapDLCPurchasedCode 为购买结果:
| 回调值 | 说明 |
|---|---|
NotPurchased | 未完成支付或已退款。 |
Purchased | 支付成功。 |
ReturnError / Undefined | 支付状态异常。 |
查询购买状态
通过商品 SKU ID 数组批量查询多个商品购买状态,结果通过查询回调返回。
TArray<FString> SkuIds{
TEXT("skuId1"),
TEXT("skuId2")
};
UTapLicense::QueryDLC(SkuIds);
购买商品
由于购买时 SDK 需获取商品的完整配置,开发者需确保已通过查询购买状态接口获得该商品的状态。
通过商品 SKU ID 发起购买,结果通过购买回调返回。
UTapLicense::PurchaseDLC(TEXT("skuId"));
SKU ID
请前往 DLC 商品 查看如何创建 DLC 商品并获得 SKU ID。
如何测试
完成 SDK 接入后,买断制游戏白名单中的用户即可自测。详细自测流程参考接入与自测。