跳到主要内容

开发指南

TapPayments-Global 是一项可让你在游戏中销售虚拟商品的服务。

你可以在 TapPayments-Global 中销售以下类型的商品:

  • 消耗型商品
  • 非消耗型商品

商品类型介绍:

类型描述
消耗型商品消耗型商品是指当用户消耗该商品时,游戏会分配相关联的游戏内容,而用户随后可以再次重复购买的商品。例如游戏货币、道具等。
非消耗型商品非消耗型商品是指购买一次便能永久使用的商品。例如付费升级和关卡包等。

游戏侧可以通过在 TapTap 开发者中心创建游戏内商品以及接入 TapPayments-Global 的服务来进行游戏商品的销售。

SDK 接入

环境要求

Gradle 版本高于 5.6.4,Android AGP 插件版本高于 3.6.0。

  • 支持 Unity 2019.4 或更高版本

关于 Unity 支持 Android 11 和高版本 Gradle 的相关文档,请参考 Android 11 支持

使用内建账户方式进行 SDK 初始化

接入前准备

  1. 参考 准备工作 创建应用、开启应用配置;
  2. 参考 快速开始 配置应用包名与签名证书;

使用 TapPayments-Global 前提是必须依赖以下库:

  • TapTap.Login
  • TapTap.Common
  • TapTap.Bootstrap

获取 SDK

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

方法一:使用 Unity Package Manager

"dependencies":{
"com.taptap.tds.login":"https://github.com/TapTap/TapLogin-Unity.git#3.26.0",
"com.taptap.tds.common":"https://github.com/TapTap/TapCommon-Unity.git#3.26.0",
"com.taptap.tds.bootstrap":"https://github.com/TapTap/TapBootstrap-Unity.git#3.26.0",
"com.taptap.tds.payments.global":"https://github.com/taptap/TapPayments-Global-Unity.git#3.26.0",
"com.leancloud.realtime": "https://github.com/leancloud/csharp-sdk-upm.git#realtime-2.3.0",
"com.leancloud.storage": "https://github.com/leancloud/csharp-sdk-upm.git#storage-2.3.0",
"com.taptap.tds.androiddependencyresolver": "https://github.com/TapTap/Android_Dependency_Resolver#1.1.5"
}

方法二:手动导入

  1. 下载页 找到 TapSDK UnityLeanCloud C# SDK 下载地址,分别下载 TapSDK-UnityPackage.zipLeanCloud-SDK-Realtime-Unity.zip

  2. 在 Unity 项目中依次转到 Assets > Import Packages > Custom Packages,从解压后的 TapSDK-UnityPackage.zip 中,选择希望在游戏中使用的 TapSDK 包进行导入,其中:

    • TapTap_Bootstrap.unitypackage TapSDK 启动器,必选。
    • TapTap_Common.unitypackage TapSDK 基础库,必选。
    • TapTap_Login.unitypackage TapTap 登录,必选。
    • TapTap_PaymentsGlobal.unitypackage TapTap 支付模块,必选。
    • TapTap_Android_Dependency_Resolver.unitypackage TapTap Android 依赖导入工具,必选。
  3. 解压后的 LeanCloud-SDK-Realtime-Unity.zip 为 Plugins 文件夹,拖拽至 Unity 即可。

提示

其中 kotlin-stdlibokhttp 的版本不做要求。

TapSDK 初始化

如果你已经参考快速开始完成了初始化,这里只需要引入支付模块即可。

var config = new TapConfig.Builder()
.ClientID(clientId) // 必须,开发者中心对应 Client ID
.ClientToken(clientToken) // 必须,开发者中心对应 Client Token
.ServerURL(serverUrl) // 必须,开发者中心 > 你的游戏 > 游戏服务 > 基本信息 > 域名配置 > API
.RegionType(RegionType.IO) // 必须,CN 表示中国大陆,IO 表示其他国家或地区
.ConfigBuilder();
TapBootstrap.Init(config);

关于内建账户登录的后续的操作,请参考 一键完成 TapTap 登录

使用单独 TapTap 授权方式进行 SDK 初始化

接入前准备

  1. 参考 准备工作 创建应用、开启应用配置;
  2. 参考 快速开始 配置应用包名与签名证书;

使用 TapPayments-Global 前提是必须依赖以下库:

  • TapTap.Login
  • TapTap.Common

获取 SDK

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

方法一:使用 Unity Package Manager

"dependencies":{
"com.taptap.tds.login":"https://github.com/TapTap/TapLogin-Unity.git#3.26.0",
"com.taptap.tds.common":"https://github.com/TapTap/TapCommon-Unity.git#3.26.0",
"com.taptap.tds.payments.global":"https://github.com/taptap/TapPayments-Global-Unity.git#3.26.0",
"com.taptap.tds.androiddependencyresolver": "https://github.com/TapTap/Android_Dependency_Resolver#1.1.5"
}

方法二:手动导入

  1. 下载页 找到 TapSDK UnityLeanCloud C# SDK 下载地址,分别下载 TapSDK-UnityPackage.zipLeanCloud-SDK-Realtime-Unity.zip

  2. 在 Unity 项目中依次转到 Assets > Import Packages > Custom Packages,从解压后的 TapSDK-UnityPackage.zip 中,选择希望在游戏中使用的 TapSDK 包进行导入,其中:

    • TapTap_Common.unitypackage TapSDK 基础库,必选。
    • TapTap_Login.unitypackage TapTap 登录,必选。
    • TapTap_PaymentsGlobal.unitypackage TapTap 支付模块,必选。
    • TapTap_Android_Dependency_Resolver.unitypackage TapTap Android 依赖导入工具,必选。
提示

其中 kotlin-stdlibokhttp 的版本不做要求。

TapSDK 初始化

如果你已经参考快速开始完成了初始化,这里只需要引入支付模块即可。

var config = new TapConfig.Builder ()
.RegionType ( RegionType.IO ) // 必须为 IO, 表示其他国家或地区
.ClientID ( "clientId" ) // 必须,开发者中心对应 Client ID
.ClientToken("clientToken") // 必须,开发者中心对应 Client Token
.ConfigBuilder ();
TapCommon.Init ( config );
TapLogin.Init ( "client", false, true ); // 初始化登录模块

关于单独 TapTap 授权登录的后续的操作,请参考 TapTap 登录并获取登录结果

如果你的游戏自己实现了账户系统,也不打算使用好友、成就等 TapSDK 提供的其他功能,仅仅需要接入「单独 TapTap 授权方式进行 SDK 初始化」功能,那么你可以使用第一种「单独 TapTap 授权方式进行 SDK 初始化」方式接入 TapTap 登录。

警告

使用内建账户和仅接入Tap登录的方式二选一即可,不可同时使用。

支付模块初始化

当游戏通过 Unity 接入 TapTap SDK 后,可以通过以下方法初始化支付模块:

通过 Unity 的 LauncherManifest.xml 将 Application tag 的 android:name 设置为 com.taptap.payment.api.UnityApplication 来进行初始化。

<application 
android:name="com.taptap.payment.api.UnityApplication">
...
</application>

如果你需要自定义 Android 的 Application 类,请参考 Android 示例。

SDK 开发指南

查询商品

string language = "zh_CN";

string[] itemIds = new [] { "product01", "product02", "product03" };

TapPayment.QueryItems (language, itemIds, new ITapPayment.Callback < Item [] > ()
{
OnFinish = items =>
{
if ( items == null || items.Length == 0 )
{
Console.WriteLine ( "未查询到相关商品" );
}
else
{
foreach ( var item in items )
{
Console.WriteLine ( item );
}
}
},

OnError = error =>
{
Console.WriteLine ( error );
}
} );

// 或者使用无语言参数版本的函数,将由 SDK 根据用户的国家或地区自动选择对应的语言
TapPayment.QueryItems (itemIds, new ITapPayment.Callback < Item [] > ()
{
...
} );

参数说明:

  • String language: 需要的国际化语言代码,例如:zh_CN、en_US、ja_JP 等。如无需自定义语言国家或使用 TapSDK 进行统一设置,则可以使用无语言参数版本的函数,将由 SDK 根据用户的国家或地区自动选择对应的语言
  • String[] itemIds: 需要查询商品 ID 数组。商品 ID 是游戏在 开发者中心 > 你的游戏 > 游戏服务 > TapTap Payments > 商品与订单 中定义的商品的 ID,Item> 是查询到存在的商品信息的回调结果。
  • Callback<Item[]> callback: 回调对象
    • 成功时回调类型为商品信息 Item 的数组: (Array<Item> items)
    • 失败时回调类型为异常 Error: (Error error)

启动应用内购买

using TapTap.Payments.Global;
using TapTap.Payments.Global.bean;

string language = "zh_CN";

string itemId = "product01";

int quantity = 1;

string extraInfo = "自定义扩展信息";

TapPayment.RequestPayFlow ( language, itemId, quantity, extraInfo, new TapPayment.PayCallback ()
{
OnCancel = ( extra ) =>
{
Console.WriteLine ( $"支付已取消\n{extra}" );
},

OnError = ( error, extra ) =>
{
Console.WriteLine ( $"错误代码:{error.code}\n错误信息:{error.Message}\n{extra}");
},


OnFinish = ( order, extra ) =>
{
Console.WriteLine ( $"订单信息:{order}\n{extra}" );
}
} );

// 或者使用无语言参数版本的函数,将由 SDK 根据用户的国家或地区自动选择对应的语言
TapPayment.RequestPayFlow ( itemId, quantity, extra, new TapPayment.PayCallback ()
{
...
} );

参数说明:

  • String language: 需要的国际化语言代码,例如:zh_CN、en_US、ja_JP 等。如无需自定义语言国家或使用 TapSDK 进行统一设置,则可以使用无语言参数版本的函数,将由 SDK 根据用户的国家或地区自动选择对应的语言
  • String itemId: 需要购买的商品 ID。商品 ID 是游戏在 开发者中心 > 你的游戏 > 游戏服务 > TapTap Payments > 商品与订单 中定义的商品的 ID.
  • Int quantity: 需要购买的商品数量。
  • String extra: 额外的扩展信息,将在支付流程结是回调中返回。若订单成功被创建(即使订单未能支付)也会和订单进行绑定。
  • PayCallback: 回调对象。
    • 完成支付流程时回调类型为订单信息 Order 和自定义扩展信息: (Order, String extra)
    • 支付流程失败时回调类型为异常 Error 和自定义扩展信息: (Error, String extra)
    • 用户取消支付流程时回调类型为自定义扩展信息: (String extra)

查询订单

String orderId = "订单ID";

TapPayment.QueryOrder ( orderId, new ITapPayment.Callback < Order > ()
{
OnFinish = ( order ) =>
{
Console.WriteLine ( $"订单信息:{order}" );
},

OnError = ( error ) =>
{
Console.WriteLine ( $"错误代码:{error.code}\n错误信息:{error.Message}" );
}
} );

// 或者直接传递一个已存在的订单对象
Order order = new Order();
order.id = "订单 ID";
TapPayment.QueryOrder ( orderId, new ITapPayment.Callback < Order > ()
{
...
} );

参数说明:

  • String orderId: 需要查询的订单 ID。
  • Callback<Order> callback: 回调对象
    • 成功时回调类型为订单信息 Order: (Order order)
    • 失败时回调类型为异常 Error: (Error error)

参数说明:

  • Order order: 已存在的订单对象。
  • Callback<Order> callback: 回调对象
    • 成功时回调类型为订单信息 Order: (Order order)
    • 失败时回调类型为异常 Error: (Error error)
传入参数说明

订单信息中包含订单 ID,可以直接传入,也可以只传入订单 ID,查询成功时,回调的 (Order order) 订单信息中的状态 [State state] 字段可能会更新。

验证订单

String orderId = "订单ID";
String orderToken = "订单Token";

TapPayment.ConsumeOrder ( orderId, orderToken, new ITapPayment.Callback < Order > ()
{
OnFinish = ( order ) =>
{
Console.WriteLine ( $"订单信息:{order}" );
},

OnError = ( error ) =>
{
Console.WriteLine ( $"错误代码:{error.code}\n错误信息:{error.Message}" );
}
} );

// 或者直接传递一个已存在的订单对象
Order order = 已经存在的订单对象
TapPayment.ConsumeOrder ( order, new ITapPayment.Callback < Order > ()
{
...
} );

参数说明:

  • String orderId: 需要验证的订单 ID。
  • String orderToken: 需要验证的订单 Token。
  • Callback<Order> callback: 回调对象
    • 成功时回调类型为订单信息 Order: (Order order)
    • 失败时回调类型为异常 Error: (Error error)

参数说明:

  • Order order: 已存在的订单对象。
  • Callback<Order> callback: 回调对象
    • 成功时回调类型为订单信息 Order: (Order order)
    • 失败时回调类型为异常 Error: (Error error)
传入参数说明

订单信息中包含订单 ID 和订单的 Token,可以直接传入,也可以只传入订单 ID 和 订单 Token。验证订单成功时,回调的 (Order order) 订单信息中的状态 [State state] 会更新为 COMPLETED

订单列表

用于打开用户在当前游戏中的订单列表。

string lang = "zh_CN";
TapPayment.OpenUserOrderList ( lang );

相关数据结构

商品信息 Item

字段类型说明
typeint商品类型
idstring商品ID
namestring商品名称
descriptionstring商品描述
pricedecimal商品价格
currencystring货币单位
regionIdstring商品地区
languageIdstring商品语言

订单 Order

字段类型说明
itemIdstring商品 ID
pricedecimal商品价格
taxdecimal税费
currencyString货币单位
quantityint购买的商品数量
extraString开发者自定义的信息
idString订单 ID
tokenString订单 Token
stateState订单状态
channelString支付渠道
feedecimal渠道费率
clientIdString客户端 ID
userIdString用户 OpenID
regionIdString用户地区 ID
订单状态 Order.State
枚举说明
UNKNOWN0未知状态。
PAYMENT_PENDING2支付中。
PAID3已支付。
COMPLETED4订单已完成支付,道具已发放。
PAYMENT_TIMEOUT5支付超时。
REFUNDING20退款中。
REFUNDED21退款成功。
REFUND_FAILED22退款失败。
REFUND_REJECTED23退款被驳回。

异常 Error

/// <summary>
/// TapPayment 异常类
/// </summary>
public class Error : Exception
{
/// <summary>
/// 错误代码
/// </summary>
public Code code;

/// <summary>
/// Error 的构造函数
/// 创建一个支付错误对象,其中包含支付错误代码和信息。
/// </summary>
/// <param name="code">错误代码</param>
/// <param name="message">错误信息</param>
public Error ( Code code, string message ) : base ( message )
{
this.code = code;
}

public override string ToString ()
{
return "Error(" + "code=" + code + ", message=" + this.Message + ')';
}
}
枚举说明
UNKNOWN-1未知错误
OK0正常
ILLEGAL_ARGUMENT1传递参数非法
NETWORK_ERROR2网络错误
INTERNAL_SERVER_ERROR3服务器出现问题
NOT_LOGIN401用户未登录
TOO_MANY_REQUEST1003请求过于频繁
ITEM_NOT_FOUND1001商品不存在
ITEM_INFO_CHANGE1017商品信息已变更
REPEAT_PURCHASE_NON_CONSUMABLE_GOODS1002重复购买非消耗性商品
ORDER_NOT_FOUND1004订单不存在
ORDER_CREATE_FAILED1005创建订单失败
ORDER_PAID1006订单已支付
ORDER_TIMEOUT1008订单超时
ORDER_VERIFY_ERROR1018验证订单错误
REGION_NOT_EDITABLE1007地区不可更改

支付回调对象 PayCallback

/// <summary>
/// PayCallback 用作支付请求函数的异步回调通知,相关函数为:
/// <ul>
/// <li><see cref="RequestPayFlow(string,int,string,TapTap.TapPay.TapPayment.PayCallback)"/></li>
/// <li><see cref="RequestPayFlow(string,string,int,string,TapTap.TapPay.TapPayment.PayCallback)"/></li>
/// </ul>
/// </summary>
public class PayCallback
{
/// <summary>
/// 取消支付
/// 当用户取消支付操作时的异步回调。
/// </summary>
/// <param name="extra"> 开发者自定义的信息
/// </param>
public delegate void CancelType ( string extra );

/// <summary>
/// 支付错误
/// 当支付过程中出现错误时的异步回调。
/// </summary>
/// <param name="error"> 错误信息
/// 支付中发生错误时回调的错误信息,详见<see cref="Error"/>。
/// </param>
/// <param name="extra"> 开发者自定义的信息
///</param>
public delegate void ErrorType ( Error error, string extra );


/// <summary>
/// 支付流程结束
/// 当支付流程完成时的异步回调。
/// 注意:建议请求服务器以确定订单状态,并不要依赖此回调。此回调不能保证被调用时订单一定支付成功。
/// </summary>
/// <param name="order">订单信息
/// 支付流程结束时回调的订单对象,详见<see cref="Order"/>。
/// </param>
/// <param name="extra">开发者自定义的信息</param>
public delegate void FinishType ( Order order, string extra );

public CancelType OnCancel { get; set; }
public ErrorType OnError { get; set; }
public FinishType OnFinish { get; set; }
}

回调对象 Callback<T>

/// <summary>
/// Callback 接口用于相关函数的异步回调结果,支持的函数有:
/// <ul>
/// <li><see cref="QueryItems(string,string[],Callback{TapTap.TapPay.bean.Item[]})"/></li>
/// <li><see cref="QueryItems(string[],Callback{TapTap.TapPay.bean.Item[]})"/></li>
/// <li><see cref="QueryOrder"/></li>
/// <li><see cref="ConsumeOrder(string,string,Callback{TapTap.TapPay.bean.Order})"/></li>
/// <li><see cref="ConsumeOrder(Order,Callback{TapTap.TapPay.bean.Order})"/></li>
/// </ul>
/// </summary>
/// <typeparam name="T">回调结果类型的泛型参数</typeparam>
public class Callback < T >
{
/// <summary>
/// 请求错误
/// </summary>
/// <param name="error">错误
/// 发生错误时错误信息,详见 <see cref="Error"/>。
/// </param>
public delegate void ErrorType ( Error error );

/// <summary>
/// 请求结果
/// </summary>
/// <param name="result">结果</param>
public delegate void FinishType ( T result );

public ErrorType OnError { get; set; }
public FinishType OnFinish { get; set; }
}

国际化相关支持

语言代码列表

使用 ISO 639-1 中定义的双小写字母语言代码(例如,en 表示英语,jp 表示日语),但:

  • 由于 Android 系统的历史原因,印尼语使用 in 表示,而不是 id
  • 仅使用语言代码无法表示所需语言时,附加 ISO 3166-1 中定义的地区代码(例如,zh_CN 表示简体中文)

当前已对 8 种进行国际化支持,语言代码如下:

代码语言
en英语
zh_CN简体中文
zh_TW繁体中文
in印尼语
ja日文
ko韩文
pt_BR巴西(葡语)
th泰语

此外 DC 后台设置商品名称时,同样也支持多语言,传递的语言参数会影响返回对应的国际化商品名称。

默认语言

如果没有匹配到相应语言,会使用英语作为默认语言。