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
- Note for Developers Using GameSalad or HTML5 Plugins for IAP v1.0
- Benefits of Upgrading from IAP v1.0 to v2.0
- Summary of Changes from IAP v1.0 to v2.0
- Upgrading Your App from IAP v1.0 to v2.0
- Adding Logic to Handle Fulfillment
- Updating the Receipt Verification Service (RVS) URLs and Responses
- Testing your app
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:
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 theUserDataResponse
class. - The
Item
class is now theProduct
class. - The
PurchasingManager
class is now thePurchasingService
class. - The
PurchasingObserver
class is now thePurchasingListener
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:
- Modify your app's AndroidManifest.xml file.
- Re-factor your code to use the new class and method names for IAP v2.0.
- Implement logic related to handling the fulfillment and receipts for purchases.
- Update the appropriate URLs and responses for the Receipt Verification Service (RVS).
- 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 theFULFILLED
status after the item is fulfilled, the delivery remains pending. In this case, the delivery attempts will continue to be made through theonPurchaseUpdatesResponse()
callback the next time you callgetPurchaseUpdates()
. 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 callnotifyFulfillment()
with theUNAVAILABLE
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 foronPurchaseUpdatesResponse()
in IAP 2.0:- Add logic in your app to handle fulfillment of purchase receipts returned from the call to
getPurchaseUpdates()
. The correspondingPurchasingListener.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 theoffset
parameter. Setreset
totrue
to return all purchase receipts, or setreset
tofalse
to return the receipts for purchases made since the last call togetPurchaseUpdates()
.
- Add logic in your app to handle fulfillment of purchase receipts returned from the call to
- Entitlements:
onPurchaseUpdatesResponse()
returns receipts for canceled and active purchases of entitlements and subscriptions. Check whether the purchase was canceled withreceipt.isCanceled()
. In IAP 1.0, receipts for canceled entitlements and subscriptions were returned by callinggetRevokedSkus()
on thePurchaseUpdatesResponse
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, callnotifyFulfillment()
for thereceiptId
with theFULFILLED
status. - If the fulfillment has yet to occur, then fulfill the receipt. Store the
receiptId
to keep track of the already fulfilled items, then callnotifyFulfillment()
for thereceiptId
with theFULFILLED
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 thereceiptId
with the statusUNAVAILABLE
. Do not send this status if you encounter an interim error during receipt processing.
- Check if the fulfillment has already occurred for this
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