实现Google Play Billing接口
本页详细介绍了如何使用与Google Play Billing API兼容的Appstore SDK实现应用内购买。如果已将应用程序与Google Play Billing Library 集成,则在大多数步骤中都无需更改代码或只需进行极少的更改。
有关详细的API参考,请参阅与Google Play Billing API兼容的Appstore SDK v4.0.0参考。
初始化BillingClient
此处无需更改代码。
按照与Google Play Billing兼容的Appstore SDK中的步骤操作,初始化BillingClient
实例。BillingClient
可实现Appstore SDK和您应用之间的通信。BillingClient
为许多常用计费操作提供了异步便捷方法。
和Google Play Billing一样,强烈建议您一次仅实例化一个BillingClient
实例。但是,使用Appstore SDK,一次实例化多个BillingClient
实例的做法不会导致单个购买事件出现多个PurchasesUpdatedListener
回调。相反,每个新的BillingClient
实例化都会将PurchasesUpdatedListener
更新为提供的新侦听器,即使对于其他BillingClient
实例也是如此。
使用newBuilder()
方法创建BillingClient
。要接收购买方面的更新,请通过调用setListener()
添加侦听器。将PurchasesUpdatedListener
对象传递给setListener()
方法。
enablePendingPurchases()
方法只能作为无操作方法使用。它不支持待处理的购买。
以下代码展示了如何初始化BillingClient
。
private PurchasesUpdatedListener purchasesUpdatedListener = new PurchasesUpdatedListener() {
@Override
public void onPurchasesUpdated(BillingResult billingResult, List<Purchase> purchases) {
// 待实现
}
};
private BillingClient billingClient = BillingClient.newBuilder(context)
.setListener(purchasesUpdatedListener)
.enablePendingPurchases()
.build();
连接到亚马逊应用商店
此处无需更改代码。
和在Google Play中建立连接的要求不同,亚马逊应用商店没有任何保持连接的概念。由于亚马逊应用商店不需要保持连接,因此您无需监测连接是否中断。与连接相关的 API以无操作方法的形式受到支持,该方法假定连接始终就绪。
调用startConnection()
时,BillingClientStateListener
总会收到包含BillingResponseCode.OK
的回调。onBillingServiceDisconnected()
方法以无操作方法的形式提供,Appstore SDK从不调用该方法。
以下示例演示了如何连接到亚马逊应用商店。
billingClient.startConnection(new BillingClientStateListener() {
@Override
public void onBillingSetupFinished(BillingResult billingResult) {
if (billingResult.getResponseCode() == BillingResponseCode.OK) {
// 在Appstore SDK中,BillingClientStateListener总会收到
// 包含BillingResponseCode.OK的回调。
// 在此处查询产品和购买。
}
}
@Override
public void onBillingServiceDisconnected() {
// 这是一种无操作方法,Appstore SDK从不调用该方法。
}
});
显示可供购买的产品
此处无需更改代码。
在向用户展示产品之前,请务必查询产品详细信息以获取本地化产品信息。可以调用queryProductDetailsAsync()
或querySkuDetailsAsync()
以查询应用内产品详细信息。
Appstore SDK返回的错误响应代码只有BillingResponseCode.DEVELOPER_ERROR
和BillingResponseCode.ERROR
。也可使用Google Play Billing支持的其他错误响应代码,但从不返回这些代码。
QueryProductDetailsAsync API
可以使用queryProductDetailsAsync()
方法查询产品详细信息。此方法采用QueryProductDetailsParams
的实例。QueryProductDetailsParams
对象会指定一个列表,其中包含您在亚马逊开发者控制台中创建的产品ID字符串,同时会指定ProductType
。对于消费品和权利,ProductType
为ProductType.INAPP
。
要处理异步操作的结果,queryProductDetailsAsync()
方法还需要侦听器。此侦听器是ProductDetailsResponseListener
接口的实现,会覆盖onProductDetailsResponse()
。onProductDetailsResponse()
方法会在产品详细信息查询完成后通知侦听器,如以下示例所示。
QueryProductDetailsParams queryProductDetailsParams =
QueryProductDetailsParams.newBuilder()
.setProductList(
ImmutableList.of(
Product.newBuilder()
.setProductId("product_id_example")
.setProductType(ProductType.INAPP)
.build()))
.build();
billingClient.queryProductDetailsAsync(
queryProductDetailsParams,
new ProductDetailsResponseListener() {
public void onProductDetailsResponse(BillingResult billingResult,
List<ProductDetails> productDetailsList) {
if (billingResult.getResponseCode() == BillingResponseCode.OK) {
// 处理返回的skuDetailsList。
} else if (billingResult.getResponseCode() == BillingResponseCode.ERROR) {
// 处理错误响应。
} else if (billingResult.getResponseCode() == BillingResponseCode.DEVELOPER_ERROR) {
// 处理开发者错误响应。
} else {
// 也可使用其他错误代码,但从不返回这些代码。
// Appstore SDK。
}
}
}
);
和Google Play Billing不同,ProductDetails.getTitle()
不包含应用名称。
QuerySkuDetailsAsync API
可以使用querySkuDetailsAsync()
方法查询SKU详细信息。此方法采用SkuDetailsParams
实例,该实例会指定一个列表,其中包含在亚马逊开发者控制台中创建的SKU字符串,同时会指定SkuType
。对于消费品和权利,SkuType
是SkuType.INAPP
。
要处理异步操作的结果,querySkuDetailsAsync()
还需要侦听器。此侦听器是SkuDetailsResponseListener
接口的实现,会覆盖onSkuDetailsResponse()
。onSkuDetailsResponse()
方法会在SKU详细信息查询完成后通知侦听器,如以下示例所示。
SkuDetailsParams skuDetailsParams =
SkuDetailsParams.newBuilder()
.setType(BillingClient.SkuType.INAPP)
.setSkusList(skusList)
.build();
billingClient.querySkuDetailsAsync(
skuDetailsParams,
new SkuDetailsResponseListener() {
public void onSkuDetailsResponse(BillingResult billingResult,
List<SkuDetails> skuDetailsList) {
if (billingResult.getResponseCode() == BillingResponseCode.OK) {
// 处理返回的skuDetailsList。
} else if (billingResult.getResponseCode() == BillingResponseCode.ERROR) {
// 处理错误响应。
} else if (billingResult.getResponseCode() == BillingResponseCode.DEVELOPER_ERROR) {
// 处理开发者错误响应。
} else {
// 也可使用其他错误代码,但从不返回这些代码。
// Appstore SDK。
}
}
}
);
启动购买流程
此处可能需要对代码进行极少的更改。
和Google Play Billing不同,Appstore SDK允许在单次购买中使用最多一种产品。如果列表中有多个项目,则会返回错误BillingResponseCode.FEATURE_NOT_SUPPORTED
。
要让应用启动购买流程,请从应用的主线程调用launchBillingFlow()
。launchBillingFlow()
方法采用BillingFlowParams
对象,其中包含ProductDetails
对象。可以通过调用queryProductDetailsAsync()
来获取ProductDetails
。使用BillingFlowParams.Builder
类创建BillingFlowParams
对象。以下示例展示了如何启动结算流程。
// 启动结算流程的活动参考
Activity activity = ...;
ImmutableList productDetailsParamsList =
ImmutableList.of(
ProductDetailsParams.newBuilder()
// 调用queryProductDetailsAsync获取productDetails
.setProductDetails(productDetails)
.build()
);
BillingFlowParams billingFlowParams = BillingFlowParams.newBuilder()
.setProductDetailsParamsList(productDetailsParamsList)
.build();
// 启动结算流程
BillingResult billingResult = billingClient.launchBillingFlow(activity, billingFlowParams);
或者,可以使用通过调用querySkuDetailsAsync()
获得的SkuDetails
来初始化BillingFlowParams
对象,如下所示。
BillingFlowParams billingFlowParams = BillingFlowParams.newBuilder()
.setSkuDetails(skuDetails)
.build();
当初始化BillingClient
时,使用了setLister()
将PurchasesUpdatedListener
的实现添加为侦听器。此侦听器会覆盖onPurchasesUpdated()
方法,该方法可提供购买结果。onPurchasesUpdated()
的实现必须处理可能出现的响应代码,如以下示例所示。
@Override
void onPurchasesUpdated(BillingResult billingResult, List<Purchase> purchases) {
if (billingResult.getResponseCode() == BillingResponseCode.OK) {
for (Purchase purchase : purchases) {
handlePurchase(purchase);
}
} else if (billingResult.getResponseCode() == BillingResponseCode.ERROR) {
// 处理购买流程中的错误。
} else if (billingResult.getResponseCode() == BillingResponseCode.DEVELOPER_ERROR) {
// 处理购买流程中的开发者错误。
} else {
// 也可使用其他错误代码,但Appstore SDK从不返回这些代码。
}
}
Appstore SDK返回的错误响应代码只有BillingResponseCode.DEVELOPER_ERROR
和BillingResponseCode.ERROR
。也可使用Google Play Billing支持的其他错误响应代码,但从不返回这些代码。
成功购买后,会生成购买令牌。购买令牌是某次购买的唯一标识,代表了与该次购买相关的用户和产品ID。
不支持的字段
Appstore SDK不支持Google Play Billing提供的以下字段。请从代码中删除对这些字段的引用。
请求字段:
- Account identifiers(Obfuscated Account ID和Obfuscated Profile ID)
- VR Purchase Flow
响应字段:
- Account identifiers(Obfuscated Account ID和Obfuscated Profile ID)
- Order ID
- Signature
- Package name
- Acknowledged
注意: Appstore SDK仅支持IAB-4.0规范中存在的字段,不包括上面列出的字段。
处理购买
此处可能需要对代码进行极少的更改。
用户完成购买后,您的应用需要处理该购买。应用通常会通过PurchasesUpdatedListener
收到购买通知。但是,在某些情况下,应用会使用queryPurchasesAsync()
来提取购买,如提取购买中所述。
完成购买后,应用应该向客户提供相应的内容。对于权利,请使用acknowledgePurchase()
确认内容的交付。对于消费品,请调用consumeAsync()
以确认交付并将相应商品标记为已消费。
查看亚马逊应用商店的Google Play Billing API接口和Google Play Billing Library之间的以下区别:
- 对消费品调用
acknowledgePurchase()
不仅会确认该商品,还会消费该商品。对权利调用consumeAsync()
只能确认该商品,而不会消费该商品。之所以发生这种情况,是因为和Google Play Billing不同,Appstore SDK在内部将消费品和权利视为独立的实体。 - Appstore SDK允许再次购买消费品,即使已经购买过该消费品但尚未消费(如果上次购买时未调用
consumeAsync()
,则可能发生这种情况)。 - 如果未确认购买,则用户不会自动收到退款。这不同于Google Play Billing,后者会撤销未在三天内收到确认的购买,如Android开发者文档所详述。
以下示例展示了如何使用关联的购买代币消费产品:
void handlePurchase(Purchase purchase) {
// 从queryPurchasesAsync或PurchasesUpdatedListener检索的购买。
if (purchase.getPurchaseState() != PurchaseState.PURCHASED) {
return;
}
// 向用户交付商品。
// 消费商品。
ConsumeParams consumeParams =
ConsumeParams.newBuilder()
.setPurchaseToken(purchase.getPurchaseToken())
.build();
ConsumeResponseListener listener = new ConsumeResponseListener() {
@Override
public void onConsumeResponse(BillingResult billingResult, String purchaseToken) {
if (billingResult.getResponseCode() == BillingResponseCode.OK) {
// 处理消费操作成功的情况。
} else if (billingResult.getResponseCode() == BillingResponseCode.ERROR) {
// 处理错误响应。
} else {
// 也可使用其他错误代码,但Appstore SDK从不返回这些代码。
}
}
};
billingClient.consumeAsync(consumeParams, listener);
}
类似地,以下示例展示了如何使用关联的购买令牌确认购买:
void handlePurchase(Purchase purchase) {
if (purchase.getPurchaseState() == PurchaseState.PURCHASED) {
AcknowledgePurchaseParams acknowledgePurchaseParams =
AcknowledgePurchaseParams.newBuilder()
.setPurchaseToken(purchase.getPurchaseToken())
.build();
AcknowledgePurchaseResponseListener acknowledgePurchaseResponseListener = ...
billingClient.acknowledgePurchase(
acknowledgePurchaseParams,
acknowledgePurchaseResponseListener);
}
}
Appstore SDK在消费商品时返回的错误响应代码只有BillingResponseCode.ERROR
。也可使用Google Play Billing支持的其他错误响应代码,但从不返回这些代码。
提取购买
此处可能需要对代码进行极少的更改。
尽管应用会在通过PurchasesUpdatedListener
进行侦听时收到购买通知,但某些场景可能会导致应用不知道用户进行了购买。应用可能会不知道用户进行了购买的场景包括:
- 网络问题: 用户成功购买,但在通过
PurchasesUpdatedListener
收到购买通知之前,他们的设备发生了网络连接故障。 - 多台设备: 用户在一台设备上购买了一件商品,切换到另一台设备,希望看到购买的商品。
可以通过在onResume()
方法中调用queryPurchasesAsync()
来处理这些场景。这样可确保成功处理所有购买,如处理购买中所述。
queryPurchasesAsync()
方法仅返回权利和消费品的未消费应用内购买。以下示例展示了如何提取用户的应用内购买:
billingClient.queryPurchasesAsync(
QueryPurchasesParams.newBuilder()
.setProductType(ProductType.INAPP)
.build(),
new PurchasesResponseListener() {
public void onQueryPurchasesResponse(BillingResult billingResult, List purchases) {
if (billingResult.getResponseCode() == BillingResponseCode.OK) {
// 处理返回的购买列表(显示用户拥有的应用程序内商品)。
} else if (billingResult.getResponseCode() == BillingResponseCode.ERROR) {
// 处理错误响应。
} else if (billingResult.getResponseCode() == BillingResponseCode.DEVELOPER_ERROR) {
// 处理开发者错误响应。
} else {
// 也可使用其他错误代码,但Appstore SDK从不返回这些代码。
}
}
}
);
或者,可以使用指定SkuType
的字符串来调用queryPurchasesAsync()
,而不是使用QueryPurchasesParams
对象,如下所示。
billingClient.queryPurchasesAsync(
SkuType.INAPP,
purchasesResponseListener
);
Appstore SDK返回的错误响应代码只有BillingResponseCode.DEVELOPER_ERROR
和BillingResponseCode.ERROR
。也可使用Google Play Billing支持的其他错误响应代码,但从不返回这些代码。
和Google Play Billing不同,只有在进行购买时使用的设备上才会返回未消费(如果未调用consumeAsync()
)的消费品,而在其他设备上不会返回。如果同一台设备上的应用版本有所变化(例如在应用升级后),则可能不会立即返回尚未消费的消费品,但最终会返回。
不支持的字段
Appstore SDK在响应中不支持Google Play Billing提供的以下字段。请从代码中删除对这些字段的引用。
- Account identifiers(Obfuscated Account ID和Obfuscated Profile ID)
- Order ID
- Signature
- Package name
- Acknowledged
注意: Appstore SDK仅支持IAB-4.0规范中存在的字段,不包括上面列出的字段。
不支持的功能
与Google Play Billing API兼容的Appstore SDK不支持以下功能和API。
- 订阅。包括所有订阅专用字段和API。
queryPurchaseHistoryAsync
API。有关此API的详细信息,请参阅Android开发者文档。showInAppMessages
API。有关此API的详细信息,请参阅Android开发者文档。
测试您的应用
要测试您的应用并验证与兼容Google Play Billing API的Appstore SDK的集成,请遵循以下指南。