Developer Console

Integrate Tiered Subscriptions in Android Apps

After you assign separate SKUs for these IAP items, use the Modify Subscription API to implement tiered subscriptions in your app. The Modify Subscription API is part of a custom version of the Amazon Appstore SDK.

Modify Subscription API

The implementation process is similar to using the Purchase API.

When you call the purchase() method, the Appstore SDK invokes the onPurchaseResponse() callback. Similarly, when you call the modifySubscription() method, the Appstore SDK invokes the onModifySubscriptionResponse() callback.

The main differences between the Purchase API and the Modify Subscription API are as follows:

  • The modifySubscription() method takes a ProrationMode parameter, which is a value specifying the time of plan modification, and a SKU parameter in the request, while a purchase() method takes only SKU.
  • The ModifySubscriptionResponse object uses a list of receipts, while the PurchaseResponse object uses only one receipt.

The modify subscription request uses the SKU of the term that the customer moves to. It also uses ProrationMode, which is an enum with the value of IMMEDIATE or DEFERRED. The modifySubscription() method identifies the corresponding customer subscription and modifies it with the new term SKU. The ProrationMode value specifies when the modification takes effect. The ModifySubscriptionResponse object provides a list of receipts associated with the modification of the plan.

Modify subscription proration modes

The proration mode of a subscription is set with the ProrationMode enum. This section describes the two possible values for ProrationMode, which are IMMEDIATE and DEFERRED, in more detail.

Immediate proration mode

With ProrationMode set to IMMEDIATE, the customer's current subscription plan ends, and the new plan takes effect immediately. The customer gets a refund for the remaining period of the ended subscription, and is charged for the new subscription plan. The customer also receives an email specifying the refund amount for the old plan and the details of the new plan.

Since the current plan ends with prorated refund, and the new plan starts with a different order, the API contains two receipts:

  • The last active receipt for the subscription, which contains cancellation date confirming the termination of the old subscription plan
  • The new receipt for the newly changed plan

You must process both receipts to deliver immediately what the customer paid for.

Immediate response sample

In this example, a customer moves from term SkuX to term SkuY, effective immediately. The purchase happens on January 16. The original purchase of SkuX happened on January 2. In this scenario, Amazon returns a message that contains the following:

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"
   }]

Deferred proration mode

With ProrationMode set to DEFERRED, the subscription plan changes at the time of the upcoming renewal. The customer continues to have access to the current plan until renewal. The customer will be charged for the new plan at the time of renewal. The customer also receives an email with the deferred subscription details and the date of the upcoming modification.

Because the previous subscription plan remains active with no plan termination, the modify subscription response object only contains the active receipt. This receipt contains the deferred term SKU and the deferred date. You must use the data in the receipt to verify and deliver access to the new plan on the specified date. After the renewal, the same receipt ID will still be valid, but will be updated with the latest subscription details.

Deferred response sample

In this example, a customer moves from SkuA to term SkuB, effective at the time of renewal as specified in 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"
   }]


Implement Modify Subscription API

The following code examples outline proper handling of the Modify Subscription API requests and responses within your app.

Sample request

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

Sample response

An onModifySubscriptionResponse() method handles responses from the Modify Subscription API. The method stores the status in a ModifySubscriptionResponse.RequestStatus variable by using getRequestStatus(). Based on the status, it either outputs receipts by using getReceipts(), or handles errors.

@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: Receipt in json:" + receipt.toJSON());
                iapManager.handleReceipt(response.getRequestId().toString(), receipt, response.getUserData());
            }
            break;
        case INVALID_SKU:
            Log.d(TAG,
                    "onModifySubscriptionResponse: Invalid SKU, onProductDataResponse should have already disabled the buy button.");
            break;
        case FAILED:
        case NOT_SUPPORTED:
            Log.d(TAG, "onModifySubscriptionResponse: Failed, so remove purchase request from local storage.");
            iapManager.purchaseFailed(response.getRequestId().toString());
            break;
    }
}


Last updated: Dec 03, 2024