开发者控制台

在Android应用中集成分级订阅

在Android应用中集成分级订阅

在更新应用的代码之前,请务必使用单独的SKU创建应用内订阅商品。有关如何设置应用内商品的说明,请参阅在开发者控制台中设置分级订阅。现在,您可以使用修改订阅请求在应用中实现分级订阅。

修改订阅请求

实现过程与使用亚马逊应用商店应用内购买 (IAP) purchase() 方法类似。要查看有关purchase() 方法的详细信息,请参阅PurchasingService

当您调用purchase() 方法时,Appstore SDK会调用onPurchaseResponse() 回调。与之类似,当您调用modifySubscription() 方法时,Appstore SDK会调用onModifySubscriptionResponse() 回调。

购买请求和修改订阅请求之间的主要区别如下:

  • modifySubscription() 方法在请求中使用ProrationMode参数和SKU参数,而purchase() 方法仅使用SKU。ProrationMode参数指定方案修改生效的时间。
  • ModifySubscriptionResponse对象使用收据列表,而PurchaseResponse对象仅使用一个收据。

modifySubscription() 方法会识别当前客户订阅,并使用新的期限SKU对其进行修改。在修改订阅请求中传递的SKU是客户要转移到的期限SKU。在请求中传递的ProrationMode是一个枚举,其值为IMMEDIATEDEFERRED,指定修改生效的时间。ModifySubscriptionResponse对象会提供方案修改相关收据的列表。

修改订阅按比例分配模式

您需要使用ProrationMode枚举来设置订阅的按比例分配模式。本节将详细介绍ProrationMode的两个可能取值:IMMEDIATEDEFERRED

即时按比例分配模式

如果ProrationMode设置为IMMEDIATE,则客户的当前订阅方案将立即结束,新方案将立即生效。客户可获得已结束订阅剩余时间的退款,并按新订阅方案支付费用。客户还会收到一封电子邮件,其中会说明旧方案的退款金额及新方案的详情。

由于当前方案以按比例退款结束,而新方案以另一个订单开始,因此响应将包含两个收据:

  • 订阅的最后一个有效收据,其中包含确认旧订阅方案终止的取消日期
  • 新更改方案的新收据

您必须处理这两个收据,从而立即向客户进行交付。

即时响应示例

在此示例中,客户从SkuX期限转换为了SkuY期限,立即生效。购买日期为1月16日,而最初购买SkuX的日期为1月2日。在此情景下,亚马逊返回的消息将包含以下内容:

receipts: [{
       "receiptId": "oeUY1ip2mJWgLoOuGtAxndQS1LDJRGvmKLr6kq4u9G8=:3:11",
       "sku": "baseSku",
       "itemType": "SUBSCRIPTION",
       "purchaseDate": "Thu Jan 16 09:25:25 GMT+05:30 2020",
       "termSku": "SkuY"
   }, {
       "receiptId": "1bxFJrJVLPr8qpub8SijMWdAqXqWWGNUYPDpynoSusE=:3:11",
       "sku": "baseSku",
       "itemType": "SUBSCRIPTION",
       "purchaseDate": "Thu Jan 02 12:41:44 GMT+05:30 2020",
       "endDate": "Thu Jan 16 09:25:26 GMT+05:30 2020",
       "termSku": "SkuX"
   }]

延迟按比例分配模式

如果ProrationMode设置为DEFERRED,则订阅方案会在下一次续订时更改。直到续订前,客户都可以继续使用当前方案。客户将在续订时支付新方案的费用。客户还会收到一封电子邮件,其中包含延迟订阅的详情和即将进行修改的日期。

由于之前的订阅方案仍然有效而没有终止,因此修改订阅请求对象仅包含有效收据。此收据包含延迟期限SKU和延迟日期。您必须使用收据中的数据进行验证,并在指定日期交付新方案的访问权限。续订后,同一收据ID仍然有效,但会使用最新订阅详情进行更新。

延迟响应示例

在此示例中,客户从SkuA转移到了SkuB期限,生效时间为deferredDate中指定续订时间。

receipts: [{
       "receiptId": "oeUY1ip2mJWgLoOuGtAxndQS1LDJRGvmKLr6kq4u9G9=:3:11",
       "sku": "baseSku",
       "itemType": "SUBSCRIPTION",
       "purchaseDate": "Thu Jan 16 10:25:25 GMT+05:30 2020",
       "deferredDate": "Thu Jan 23 10:25:26 GMT+05:30 2020",
       "deferredSku": "SkuA",
       "termSku": "SkuB"
   }]


实现修改订阅

以下代码示例简述了如何正确处理应用中的修改订阅请求和响应。

示例请求

RequestId requestId = PurchasingService.modifySubscription("SKU", ProrationMode);

示例响应

onModifySubscriptionResponse() 方法会处理来自修改订阅请求的响应。该方法会使用getRequestStatus()将状态储存在ModifySubscriptionResponse.RequestStatus变量中。根据状态,它会使用getReceipts()输出收据或处理错误。

@Override
public void onModifySubscriptionResponse(ModifySubscriptionResponse response) {
    final String requestId = response.getRequestId().toString();
    final String userId = response.getUserData().getUserId();

    final ModifySubscriptionResponse.RequestStatus status = response.getRequestStatus();
    Log.d(TAG, "onModifySubscriptionResponse: requestId (" + requestId
            + ") userId ("
            + userId
            + ") modifySubscriptionRequestStatus ("
            + status
            + ")");
    Log.d(TAG, "ModifySubscriptionResponse " + response.toString());

    switch (status) {
        case SUCCESSFUL:
            for(Receipt receipt : response.getReceipts()) {
                Log.d(TAG, "onModifySubscriptionResponse: Json格式收据:" + receipt.toJSON());
                iapManager.handleReceipt(response.getRequestId().toString(), receipt, response.getUserData());
            }
            break;
        case INVALID_SKU:
            Log.d(TAG,
                    "onModifySubscriptionResponse: 无效SKU,onProductDataResponse应已将购买按钮禁用。");
            break;
        case FAILED:
        case NOT_SUPPORTED:
            Log.d(TAG, "onModifySubscriptionResponse: 失败,因此从本地储存中删除购买请求。");
            iapManager.purchaseFailed(response.getRequestId().toString());
            break;
    }
}


Last updated: 2025年4月7日