Developer Console

Migrate from IAP v1.0 to IAP v2.0

In-App Purchasing (IAP) v1.0 is now deprecated and has been replaced by IAP v2.0. The updated version of the IAP API enables your apps to retrieve unfulfilled consumable items, to notify Amazon upon fulfillment of consumable purchases, and to provide unique transaction IDs. This page describes how to upgrade your app from using the IAP v1.0 code base to the IAP v2.0 code base.

Note for Developers using the Corona Plugin

As of May 11, 2016, the Corona plugin for IAP v1.0 is deprecated for new and updated apps being submitted to the Amazon Appstore. If your app uses the Corona plugin, migrate your app to using the newer IAP v2.0 Corona plugin:

Note for Developers Using GameSalad or HTML5 Plugins for IAP v1.0

Although Amazon does not currently provide an IAP v2.0 plugin for GameSalad, or HTML5 development, your already-published app may still use these plugins even though IAP v1.0 was deprecated as of May 11, 2016.

If you plan to submit an app that uses either of these plugins, please contact the Amazon Appstore immediately after you submit your app to properly route your app through the submission process, otherwise it may be rejected. When you contact Amazon Appstore, include your app name, app key, live ASIN, and the exact SDK that your app uses (GameSalad or HTML5) so that your app can be flagged for approval:

Amazon Appstore Contact Form

Benefits of Upgrading from IAP v1.0 to v2.0

The main benefit of upgrading your IAP code base from v1.0 to v2.0 is to enable your apps to retrieve unfulfilled consumable items. This upgrade also allows for the ability of your apps to notify Amazon when consumable purchases are fulfilled.

Summary of Changes from IAP v1.0 to v2.0

This section gives a high level overview of how the IAP API was changed from v1.0 to v2.0. Use the list in this section as a guideline to verify that you have addressed each of these changes (if applicable) in your code base before testing and submitting your app.

Code refactoring

The following list gives a high-level view of the naming changes made in IAP v2.0. See the table in Refactoring Your App's Source Code for more details on these changes.

  • The GetUserIdResponse class is now the UserDataResponse class.
  • The Item class is now the Product class.
  • The PurchasingManager class is now the PurchasingService class.
  • The PurchasingObserver class is now the PurchasingListener class.
  • The substring "product" replaces the substring "item" in methods and enums.
  • The substring "UserData" replaces the substring "UserId" in methods and enums.
  • The substring "get" replaces the substring "initiate" in methods.

Other changes and new features

The following list describes other changes and new features implemented for IAP 2.0:

  • Each transaction now has a unique transaction ID.
  • The value for the android:name attribute in the AndroidManifest.xml file has changed.
  • For subscription transactions, the start date and the stop date are now referred to as the purchase date and the cancel date.
  • IAP v2.0 contains a new notifyFulfillment API for tracking the fulfillment status of a purchase.
  • The Receipt Verification Service (RVS) has new URLs and new response mappings.
  • The App Tester tool replaces the SDK Tester for testing your app locally.

Upgrading Your App from IAP v1.0 to v2.0

Perform the following tasks to migrate your app from IAP v1.0 to IAP v2.0:

  1. Modify your app's AndroidManifest.xml file.
  2. Re-factor your code to use the new class and method names for IAP v2.0.
  3. Implement logic related to handling the fulfillment and receipts for purchases.
  4. Update the appropriate URLs and responses for the Receipt Verification Service (RVS).
  5. If you were using the SDK Tester to test your app locally, uninstall the SDK Tester and install the new App Tester app.

Modifying the AndroidManifest.xml File

You can determine whether you are using the previous version or the current version by inspecting the AndroidManifest.xml file:

  • previous version:
<receiver android:name = "com.amazon.inapp.purchasing.ResponseReceiver">
  • current version:
<receiver android:name = "com.amazon.device.iap.ResponseReceiver">

The following example shows the correct value for the android:name in the receiver element for an app using IAP v2.0:

<application>
  ...
  <receiver android:name = "com.amazon.device.iap.ResponseReceiver"
      android:permission = "com.amazon.inapp.purchasing.Permission.NOTIFY" >
    <intent-filter>
      <action android:name = "com.amazon.inapp.purchasing.NOTIFY" />
    </intent-filter>
  </receiver>
  ...
</application>

Refactoring Your App's Source Code

A number of class and method names changed from IAP v1.0 to IAP v2.0. Use the following table to help refactor your code to use the correct names for IAP v2.0:

IAP v1.0 element name IAP v2.0 element name Element type
GetUserIdResponse UserDataResponse class
GetUserIdResponse.getUserId() UserDataResponse.getUserData() method
GetUserIdResponse.GetUserIdRequestStatus UserDataResponse.RequestStatus enum
Item Product class
Item.getItemType Product.getProductType method
Item.ItemType ProductType enum constant
ItemDataResponse ProductDataResponse class
ItemDataResponse.getItemData() ProductDataResponse.getProductData method
ItemDataResponse.ItemDataRequestStatus ProductDataResponse.RequestStatus enum constant
PurchasingManager PurchasingService class
PurchasingManager.initiateItemDataRequest(java.util.Set <java.lang.String> skus) PurchasingService.getProductData(java.util.Set <java.lang.String> skus) method
PurchasingManager.initiatePurchaseUpdatesRequest (Offset offset) PurchasingService.getPurchaseUpdates(boolean reset) method
PurchasingManager.initiateGetUserIdRequest() PurchasingService.getUserData() method
PurchasingObserver PurchasingListener class
PurchasingObserver.onGetUserIdResponse (GetUserIdResponse getUserIdResponse) PurchasingListener.onUserDataResponse (UserDataResponse userDataResponse) method
PurchasingObserver.onItemDataResponse(ItemDataResponse itemDataResponse) PurchasingListener.onProductDataResponse (ProductDataResponse productDataResponse) method
Receipt.getPurchaseToken Receipt.getReceiptId method
token receiptId property

Implementing the marketplace property

To determine the marketplace in use by a customer, use the marketplace property of the UserData class. Use the marketplace property to identify the Amazon Marketplace in use by a customer. Older versions of Appstore may not have marketplace information available.

Adding Logic to Handle Fulfillment

One new feature of IAP v2.0 is the addition of new methods to track the fulfillment of a purchase. These methods check the status of purchase receipts and notify Amazon about the status of an item's fulfillment.

Implementing notifiyFulfillment

IAP 2.0 provides a new API that you can use to track the fulfillment status of a purchase. To track the fulfillment status of a purchase, implement the notifyFulfillment() API. Implement this call after the item is fulfilled to send the status of the purchase to Amazon.

  • If you do not call notifyFulfillment() with the FULFILLED status after the item is fulfilled, the delivery remains pending. In this case, the delivery attempts will continue to be made through the onPurchaseUpdatesResponse() callback the next time you call getPurchaseUpdates(). Eventually, the order may be canceled if Amazon does not receive explicit acknowledgement of fulfillment with this API.

  • If you can never fulfill the item, use the UNAVAILABLE status. You can call notifyFulfillment() with the UNAVAILABLE status from your app anytime.

This call is immutable. If an order is marked as FULFILLED or UNAVAILABLE via notifyFulfillment(), the status cannot be changed again.

Implementing getPurchaseUpdates

Implement getPurchaseUpdates() in the onStart() or onResume() method of the activity. Also, to prevent over-fulfillment of an order, de-duplicate the receipts with receiptId. See below for implementation details concerning the differences between consumables, entitlements, and subscriptions.

  • Consumables: The getPurchaseUpdates() method returns unfulfilled and canceled purchase receipts for consumables. Note the following for onPurchaseUpdatesResponse()in IAP 2.0:

    • Add logic in your app to handle fulfillment of purchase receipts returned from the call to getPurchaseUpdates(). The corresponding PurchasingListener.onPurchaseUpdatesResponse() callback may run when your app opens, or any other time, so use caution when referencing user interface (UI) elements or objects that may not be available.
    • Use the boolean reset parameter instead of the offset parameter. Set reset to true to return all purchase receipts, or set reset to false to return the receipts for purchases made since the last call to getPurchaseUpdates().
  • Entitlements: onPurchaseUpdatesResponse() returns receipts for canceled and active purchases of entitlements and subscriptions. Check whether the purchase was canceled with receipt.isCanceled(). In IAP 1.0, receipts for canceled entitlements and subscriptions were returned by calling getRevokedSkus() on the PurchaseUpdatesResponse object.
  • Subscriptions: Same as Entitlements.

Processing receipts

Implement fulfilled acknowledgements for each receipt. When processing receipts, first check whether the receipt is cancelled. Depending on the cancellation status, do one of the following:

  • If the receipt is canceled, and the item has not been revoked already, then revoke the item.
  • If the receipt is not canceled:

    • Check if the fulfillment has already occurred for this receiptId. If so, call notifyFulfillment() for the receiptId with the FULFILLED status.
    • If the fulfillment has yet to occur, then fulfill the receipt. Store the receiptId to keep track of the already fulfilled items, then call notifyFulfillment() for the receiptId with the FULFILLED status.
    • If the fulfillment can not occur because the item was for a previous game state or the game does not support that item, then call notifyFulfillment() for the receiptId with the status UNAVAILABLE. Do not send this status if you encounter an interim error during receipt processing.

Updating the Receipt Verification Service (RVS) URLs and Responses

The Receipt Verification Service (RVS) underwent several changes from IAP v1.0 to IAP v2.0. If you are using RVS to verify receipts from your app, you will need to update the RVS URLs and response mappings.

For testing with RVS, after you register the listener (registerListener(PurchasingListener listener)) you can then query PurchaseService.IS_SANDBOX_MODE(). This method returns true if the app is in sandbox mode, and false if the app is in production mode.

Note: You no longer need to call the renewal endpoint for subscriptions on RVS in IAP v2.0. RVS for IAP v2.0 only exposes the service named verifyReceiptId. You do not need to renew anything in the request parameters like purchaseToken of IAP v1.0 RVS.

Updating the RVS URLs

In IAP 1.0, calls were made using the following URL:

  • https://appstore-sdk.amazon.com/version/2.0/verify/developer/_<developerSecret>_/user/_<userId>_/purchaseToken/_<purchaseToken>_

In IAP 2.0, receiptId replaces purchaseToken, and uses the following URL:

  • https://appstore-sdk.amazon.com/version/1.0/verifyReceiptId/developer/_<SharedSecret>_/user/_<userId>_/receiptId/_<receiptId>_

Note: In the RVS URLs, the "version" field refers to the version number of RVS, not the version number of the IAP APIs.

  • If you are using IAP v1.0, the correct RVS version is 2.0.

  • If you are using IAP v2.0, the correct RVS version is 1.0.

In the above URLs:

  • _<SharedSecret>_ is accessible on the developer portal after you create an account. The Shared Secret pins an IAP transaction to a particular vendor and validates that as a developer, you have the right to validate the receipt for the transaction.

    The shared secret can be found on the Shared Key page for your developer account with the Amazon Appstore:

    https://developer.amazon.com/sdk/shared-key.html

  • _<receiptId>_ and _<userId>_ are provided by IAP 2.0.

Re-mapping the Response Fields

The following table shows the mapping of response fields from IAP 1.0 to IAP 2.0:

IAP 1.0 IAP 2.0
itemType productType
startDate purchaseDate
endDate cancelDate
sku productId
purchaseToken receiptId

The following code snippet shows a sample response from RVS in IAP v2.0:

{
  "betaProduct": false,
  "cancelDate": null,
  "parentProductId": null,
  "productId": "my.app.sku",
  "productType": "CONSUMABLE",
  "purchaseDate": 138474794983,
  "quantity": 1,
  "receiptId": "WNkddEp39kcA387948nDDhd699C48jdklEnsQQL_Y=:1:31",
  "testTransaction": true
}

Testing your app

The SDK Tester tool is for testing IAP v1.0 apps. This tool has been replaced by the App Tester tool for IAP v2.0.

App Tester is not compatible with the SDK Tester, so when you upgrade your app's code to use IAP v2.0, uninstall the SDK Tester from any mobile devices that you are using for testing. Once the SDK Tester is uninstalled, follow the instructions and links in Testing In-App Purchasing (IAP) to install and use App Tester.

After you finish testing your app locally, you can use the Live App Testing service to beta test your app in a production environment with a select group of users.


Last updated: Mar 13, 2023