Receipt Verification for IAP Apps
The Receipt Verification Service (RVS) enables validation of purchases made by your app's users.
- RVS Overview
- Set up RVS
- RVS Request Syntax
- RVS Response Syntax
- Cancel Date and Renewal Date
- RVS Sandbox and Production Examples
RVS Overview
The following table shows the purchase workflow with receipt verification. RVS starts after the IAP API completes the purchase and returns the purchase receipt to the App.
Step | Component | Task |
---|---|---|
Step 1 | IAP API | IAP API interacts with the user to complete the purchase. IAP API returns a purchase receipt to the App. |
Step 2 | App | App forwards the purchase receipt to the App Server. |
Step 3 | App server | App server sends a request to RVS server for validation of the receipt. |
Step 4 | RVS server | RVS server confirms that the receipt is valid. |
Step 5 | App server | App server makes the content available to the user. |
The steps in the above table match the callouts in the following diagram:

You can also use RVS to enable access to a subscription purchased on another platform, such as your website, as long as the purchase was made through Amazon. The following scenario describes this workflow:
- Your app's user purchases a subscription through Amazon via your company's website.
- Your app receives a receipt for the purchased subscription
- To enable access, your app then sends information from the receipt to your server. Finally, your server validates this transaction by querying RVS.
Set up RVS
RVS provides two environment options, depending on whether your app is in the development/testing stage or has been published to the Amazon Appstore:
- RVS Sandbox: While developing and testing your app, use an RVS Sandbox environment to verify receipts generated by the App Tester testing tool. To set up an RVS sandbox, see Instructions for RVS Sandbox Environment.
- RVS production server: After you publish your app to the Amazon Appstore, you can use the Amazon RVS production server. See Instructions for RVS Production Environment.
RVS Request Syntax
Use RVS to validate the Receipt objects received in a PurchaseResponse
or PurchaseUpdatesResponse
. These response objects contain a User ID value that denotes a unique identifier of the user. The Receipt in the PurchaseResponse
contains a ReceiptId
, which is used in conjunction with the User ID to perform an out-of-band server-side validation of the purchase. Requests from your server require a shared secret to be passed to confirm your identity for security.
These requests use the following format:
<Protocol>//<Server>/<[_RVSSandbox_]>/version/<Operation_version_number>/verifyReceiptId/developer/<Shared_Secret>/user/<UserId>/receiptId/<ReceiptId>
Replace the terms in the angle brackets with the following values for transaction being verified:
- Protocol: Protocol being used to communicate with the server or sandbox, such as https:.
- Server: URL for the RVS server that you are communicating with.
- If you are using the RVS Sandbox, use "localhost:8080" or wherever you set up Tomcat.
- If you are using the RVS production server, the URL is "appstore-sdk.amazon.com".
- [RVSSandbox]: If you are using the RVSSandbox, use the value "RVSSandbox". If you are using the RVS production server, omit this field.
- Operation_version_number: Version number of the
verifyReceiptId
operation. This version number is independent of the IAP version number. The currentverifyReceiptId
version number is "1.0". - Shared_secret: Shared secret used to identify the developer issuing the request. Your 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. For the RVSSandbox, the Shared Secret can be any non-empty string.
- UserId: ID representing a distinct Amazon customer for your appstore app:
purchaseResponse->userData->userId.
- ReceiptId: Unique ID for the purchase:
purchaseResponse->receipt->receiptId
orpurchaseUpdatesResponse->receipts->receipt->receiptId
.
RVS Response Syntax
RVS provides a RESTful JSON API interface. As a best practice, utilize a JSON parser class for reading the JSON responses from the RVS server.
After making a request to verify a transaction, the RVS server or sandbox will return a response code indicating if the request was successful. If successful, the returned JSON response will include information about the transaction.
The following example shows a successful response:
{
"autoRenewing":false,
"betaProduct":false,
"cancelDate":null,
"cancelReason":null,
"freeTrialEndDate":null,
"gracePeriodEndDate":null,
"parentProductId":null,
"productId":"com.amazon.iapsamplev2.gold_medal",
"productType":"CONSUMABLE",
"purchaseDate":1399070221749,
"quantity":1,
"receiptId":"wE1EG1gsEZI9q9UnI5YoZ2OxeoVKPdR5bvPMqyKQq5Y=:1:11",
"renewalDate":null,
"term":null,
"termSku":null,
"testTransaction":true
}
RVS Response Codes
The Receipt Verification Service will respond with one of the following codes, which indicate the result of the validation check:
Response Code | Description |
---|---|
HTTP 200 | Success: The Receipt ID, User ID, and shared secret are all valid. Product Type is one of: "ENTITLED", "CONSUMABLE", or "SUBSCRIPTION" |
HTTP 400 | The transaction represented by this receiptId is invalid, or no transaction was found for this receiptId. |
HTTP 496 | Invalid sharedSecret |
HTTP 497 | Invalid User ID |
HTTP 500 | There was an Internal Server Error |
RVS Response Fields for Successful Transactions
The following table lists and describes the fields included in an RVS response for a successful transaction:
Field | Data Type | Description |
---|---|---|
autoRenewing |
Boolean | Indicates if customer's subscription will auto renew. |
betaProduct |
Boolean | Indicates whether the product purchased is a Live App Testing product. |
cancelDate |
Long integer | The date the purchase was cancelled, or the subscription expired. The field is null if the purchase was not cancelled. |
cancelReason |
Integer | Indicates why a product was cancelled. Possible values are null, 0, 1, or 2, where each integer represents a cancellation reason: null - The purchase was not cancelled. 0 - The cancel reason is currently unavailable and will render at a later time. 1 - Your customer cancelled the order. 2 - The purchase was cancelled by Amazon's system (For example, a customer purchases a subscription with invalid payment and the purchase could not be completed in the grace period). |
freeTrialEndDate |
Long Integer | Indicates that the subscription is in a free trial. Provides the free trial end date of the subscription in epoch (milliseconds). The field is null if the subscription is not in a free trial period. |
gracePeriodEndDate |
Long Integer | Indicates that the subscription is in grace period. Provides the grace period end date of the subscription in epoch (milliseconds). The field is null if the subscription is not in a grace period. |
parentProductId |
String | Null. Reserved for future use. |
productId |
String | The SKU that you defined for this item in your app. |
productType |
String | Type of product purchased. Valid product types are CONSUMABLE, SUBSCRIPTION, and ENTITLED. |
purchaseDate |
Long integer | The date of the purchase, stored as the number of milliseconds since the epoch. For subscription items, purchaseDate represents the initial purchase date, not the purchase date of subsequent renewals. |
quantity |
Integer | Quantity purchased. Always null or 1. |
receiptID |
String | Unique identifier for the purchase. |
renewalDate |
Long integer | The date that a subscription purchase needs to be renewed. The date is stored as the number of milliseconds since the epoch. |
term |
String | Duration that a subscription IAP will remain valid (the term starts on the date of purchase). The term consists of a number and a time period (Day, Week, Month, Year), such as 1 Week or 2 Months. |
termSku |
String | Unique SKU that corresponds to the subscription term. |
testTransaction |
Boolean | Indicates whether this purchase was made as a part of Amazon’s publishing and testing process. |
Cancel Date and Renewal Date
The renewalDate
field contains the date that an auto-renew subscription purchase next needs to be renewed. This field applies to subscription purchases only.
The cancelDate
field contains the date that a subscription purchase expired or that Amazon customer service cancelled the purchase.
The renewal date and cancel date fields are stored as time in milliseconds. You can use java.util.Date(timeInMillis)
to convert the value into a date object.
Consumable or entitlement purchase
In a valid receipt, the cancel date and renewal date both contain the null value. If the cancel date field is not null, it contains the date that Amazon customer service cancelled the purchase.
Subscription purchase
In a valid subscription receipt, the cancel date is null. If the cancelDate
field is not null, it contains the date that the subscription expired, or that Amazon customer service cancelled the purchase.
The renewalDate
field contains the date that an auto-renew subscription purchase next needs to be renewed. The field value will be null if the subscription is not set to auto-renew.
In the following example, the user has a subscription that was cancelled:
- The subscription was active from 01/01/2016 – 03/01/2016. In this receipt, the purchaseDate for this subscription is set to 01/01/2016, and the cancelDate is set to 03/01/2016.
- If this subscription is subsequently reactivated on 04/01/2016, the subscription will have a second receipt. The second receipt will show a purchaseDate of 04/01/2016 and a cancelDate of null.
RVS Sandbox and Production Examples
See RVS Examples.
Last updated: Dec 02, 2020