Android 集成指南
环境要求
- Gradle 版本不低于 6.1.1,Android AGP 插件版本不低于 4.0.1;
准备
- 参照 准备工作 所述创建 app,配置 app 参数
- 参照 TapSDK 快速开始 配置包名和签名
SDK 指南
SDK 集成
打开项目的 project/app/build.gradle
文件,添加 gradle 配置如下:
dependencies {
...
// TapTapIAP dependency
implementation 'com.taptap.android.payment:iap:4.5.1'
implementation 'com.taptap.android.payment:base:4.5.1'
implementation 'com.taptap.android.payment:stripe:4.5.1'
implementation 'com.taptap.android.payment:braintree:4.5.1'
implementation 'com.taptap.android.payment:alipay:4.5.1'
}
SDK 初始化
TapTapIAP 模块依赖于 TapTapSDK 初始化,具体参考 TapSDK 集成
import com.taptap.sdk.core.TapTapRegion;
import com.taptap.sdk.core.TapTapSdk;
import com.taptap.sdk.core.TapTapSdkOptions;
/* 必选配置 */
// 开发者中心对应 Client ID
String clientId = "";
// 开发者中心对应 Client Token
String clientToken = "";
// 是否开启 log,建议 Debug 开启,Release 关闭,默认关闭 log
boolean enableLog = BuildConfig.DEBUG;
TapTapSdkOptions tapSdkOptions = new TapTapSdkOptions(
clientId, // 游戏 Client ID
clientToken, // 游戏 Client Token
TapTapRegion.GLOBAL // 游戏可玩区域: [TapTapRegion.CN]=国内 [TapTapRegion.GLOBAL]=海外
);
tapSdkOptions.setEnableLog(enableLog);
// 初始化 TapSDK
TapTapSdk.init(context, tapSdkOptions);
创建 TapTapIAP
,请使用 newBuilder()
这里会根据SDK.init所设置的 ClientID
和 ClientToken
校验是否有权限使用 TapTapIAP
。
// 创建 TapTapIAP 实例
TapTapIAP tapTapIAP = TapTapIAP.newBuilder().build();
展示可供购买的商品
初始化完成 TapTapIAP
后,您就可以查询可售的商品并将其展示给用户了。
查询应用内商品详情,请调用 queryProductDetailsAsync()
。为了处理该异步操作的结果,您还必须指定实现 ProductDetailsResponseListener
接口的监听器。然后,您可以替换 onProductDetailsResponse()
,该方法会在查询完成时通知监听器,如以下示例所示:
List<Product> queryProductList = new ArrayList<>();
// 支持批量查询 Product, 设置好对应的 ProductID、ProductType
// ProductType 目前仅支持 ProductType.INAPP
for (int i = 0; i < products.length; i++) {
String productId = products[i];
Product product = Product.newBuilder()
.setProductId(productId)
.setProductType(ProductType.INAPP)
.build();
queryProductList.add(product);
}
QueryProductDetailsParams params = QueryProductDetailsParams.newBuilder()
.setProductList(queryProductList).build();
tapTapIAP.queryProductDetailsAsync(params, new ProductDetailsResponseListener() {
@Override
public void onProductDetailsResponse(TapPaymentResult result,
List<ProductDetails> productDetails, List<String> unavailableProductIds) {
...
// check TapPaymentResult
// process returned productDetails
}
});
启动购买流程
如需从应用发起购买请求,请从应用的主线程调用 launchBillingFlow()
方法。此方法接受对 BillingFlowParams
对象的引用,该对象包含通过调用 queryProductDetailsAsync()
获取的相关 ProductDetails
对象。如需创建 BillingFlowParams
对象,请使用 BillingFlowParams.Builder
类。
// An activity reference from which the billing flow will be launched.
Activity activity = ...;
ProductDetailsParams productDetailsParams =
ProductDetailsParams.newBuilder()
// retrieve a value for "productDetails" by calling queryProductDetailsAsync()
.setProductDetails(productDetails)
.build();
BillingFlowParams billingFlowParams = BillingFlowParams.newBuilder()
.setProductDetailsParams(productDetailsParams)
.setObfuscatedAccountId("xxx") //Specifies an optional obfuscated string that is uniquely associated with the order(or another information) in your app.
.build();
// Launch the billing flow
TapPaymentResult result = tapTapIAP.launchBillingFlow(activity,
billingFlowParams,
new PurchaseUpdatedListener() {
@Override
public void onPurchaseUpdated(TapPaymentResult result, Purchase purchases) {
// To be implemented in a later section.
}
}
);
launchBillingFlow()
方法会返回 TapPaymentResponseCode
中列出的几个响应代码之一。请务必检查此结果,以确保在启动购买流程时没有错误。TapPaymentResponseCode
为 OK
表示成功启动。成功调用 launchBillingFlow()
后,会向用户展示收银台。
购买流程中订单状态监听
在购买流程中, TapTapIAP
会调用 onPurchasesUpdated()
,以将购买的订单状态变更实时传给实现 PurchasesUpdatedListener 接口的监听器。您可以在初始化时使用 setListener()
方法指定监听器。您必须实现 onPurchasesUpdated()
来处理可能的响应代码。以下提供了一个 onPurchasesUpdated()
示例 :
@Override
public void onPurchaseUpdated(TapPaymentResult result, Purchase purchase) {
if (result.getResponseCode() == TapPaymentResponseCode.OK
&& purchases != null) {
handlePurchase(purchase);
} else if (result.getResponseCode() == TapPaymentResponseCode.USER_CANCELED) {
// Handle an error caused by a user cancelling the purchase flow.
} else {
// Handle any other error codes.
}
}
进行商品的发放,且完成订单
在用户进行完了任意商品的购买, 请确认为该用户发放对应的商品或者解锁对应的关卡。在确定商品发放之后需要调用 finishPurchaseAsync
告知 TapTapIAP
已完成商品的发放。以下是个代码实例:
Purchase purchase = ...;
FinishPurchaseParams params = FinishPurchaseParams.newBuilder()
.setId(purchase.getOrderId()) // Required
.setPurchaseToken(purchase.getPurchaseToken()) // Required
.build();
tapTapIAP.finishPurchaseAsync(params, new FinishPurchaseResponseListener() {
@Override
public void onFinishPurchaseResponse(TapPaymentResult result, Purchase purchase) {
}
});
确认发放商品非常重要, 如果您没有调用 finishPurchaseAsync
来完成订单, 用户将无法再次购买该商品,且该订单将会在 3天后自动退款。
获取未完成的订单列表
使用 PurchasesUpdatedListener
监听购买交易变更,无法完全确保您的应用会处理所有购买交易。有时您的应用可能不知道用户进行了部分购买交易。在下面这几种情况下,您的应用可能会跟踪不到或不知道购买交易的发生:
- 在购买过程中出现网络问题:用户成功购买了商品并收到了对应渠道的确认消息,但用户设备在通过
PurchasesUpdatedListener
收到购买交易的通知之前失去了网络连接。 - 多部设备:用户在一部设备上购买了一件商品,然后在切换设备时期望看到该商品。
- 异常崩溃:用户在外部购买成功时,应用出现了崩溃的情况。
为了处理这些情况,请确保您的应用在 onResume()
方法中调用 tapTapIAP.queryUnfinishedPurchaseAsync()
,以确保所有购买交易都得到正确处理。
以下示例展示了如何提取用户的未完成订单列表:
tapTapIAP.queryUnfinishedPurchaseAsync(new PurchasesResponseListener() {
@Override
public void onQueryPurchasesResponse(TapPaymentResult result, List<Purchase> purchases) {
if (purchases != null) {
// Process Purchases.
...
...
}
}
});
处理 TapPaymentResult 响应代码
当使用 TapTapIAP
结算库调用触发操作时,该库会返回 TapPaymentResult
响应,并将结果告知开发者。例如,如果您使用 queryProductDetailsAsync
且返回 OK
,并提供正确的 ProductDetails
对象;或者返回了其他类型,代表了无法提供 ProductDetails
对象的原因。
并非所有类型都是错误。下面列举了一些 TapPaymentResponseCode
不是错误的:
TapPaymentResponseCode.OK
:代表业务已成功执行。TapPaymentResponseCode.USER_CANCELED
:代表用户没有完成流程,就离开了页面
其他的一些错误类型可以用于调试和上报使用:
可重试的 CODE | 问题 | 可以尝试的解决方案 |
---|---|---|
NETWORK_ERROR | 此错误代表设备和 TapTapIAP 系统之间的网络连接出现问题 | 可以使用简单的重试策略或指数退避算法 |
ITEM_ALREADY_OWNED | 这个类型表明用户已经购买过 非消耗品 商品, 再次购买时会返回该错误 | 为了避免出现这个问题, 在展示商品界面就提示用户已经购买该商品, 且无法点进进行购买流程. |
USER_CANCELED | 用户已退出结算流程 | |
ITEM_UNAVAILABLE | 商品无效, 有可能是商品已经过期或者商品已经被下架 | 确保您通过 queryProductDetailsAsync 刷新商品详情。如果商品无效则不在界面上展示给用户 |
DEVELOPER_ERROR | 这是一个严重错误,表明您未正确使用 API。例如,向 launchBillingFlow 提供不正确的参数可能会导致此错误 |