Developer Console

Receipt Verification Service for Appstore SDK IAP

The Receipt Verification Service (RVS) for Amazon In-App Purchasing (IAP) lets you validate purchases made by your app's users. For an overview of RVS, see Receipt Verification Service Overview.

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 Cloud 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 Cloud Sandbox, see Use RVS Cloud Sandbox.
  • RVS production server: After you publish your app to the Amazon Appstore, you can use the Amazon RVS production server. See RVS Production Setup for Appstore SDK IAP.

RVS request syntax

Use RVS to validate the PurchaseResponse object, or the PurchaseUpdatesResponse object. From these response objects, you can extract a user ID string, which denotes a unique identifier of the user. The PurchaseResponse object contains a ReceiptId, which is used in conjunction with the user ID to perform 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}[/{sandbox}]/version/{operation-version-number}/verifyReceiptId/developer/{shared-secret}/user/{user-id}/receiptId/{receipt-id}

The curly brackets contain placeholders and request parameters—replace them with values from the transaction you want to verify. The following table lists descriptions of the required parameters.

Parameter Description
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. Both the RVS Cloud Sandbox server and the RVS production server use the URL "appstore-sdk.amazon.com".
sandbox If you are using the RVS Cloud Sandbox server, use the value "sandbox". If you are using the RVS production server, omit this parameter.
operation-version-number Version number of the verifyReceiptId operation. This version number is independent of the IAP version number. The current verifyReceiptId 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 in the Developer Console: https://developer.amazon.com/sdk/shared-key.html. For the RVS Cloud Sandbox, the shared secret can be any non-empty string.
user-id ID representing a distinct Amazon customer for your Appstore app. Obtain the user ID from PurchaseResponse.getUserData().getUserId().
receipt-id Globally unique ID for the purchase. Obtain the reciept ID from PurchaseResponse.getReceipt().getReceiptId() or PurchaseUpdatesResponse.getReceipts()Receipt.getReceiptId().

RVS response syntax

RVS provides a RESTful JSON API interface. As a best practice, use 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 returns a response code indicating if the request was successful. If successful, the returned JSON response includes information about the transaction.

The following example shows a successful response:

   {
    "autoRenewing":false,
    "betaProduct":false,
    "cancelDate":null,
    "cancelReason":null,
    "freeTrialEndDate":null,
    "fulfillmentDate":null,
    "fulfillmentResult":null,
    "gracePeriodEndDate":null,
    "parentProductId":null,
    "productId":"com.amazon.iapsamplev2.gold_medal",
    "productType":"CONSUMABLE",
    "promotions":null,
    "purchaseDate":1399070221749,
    "purchaseMetadataMap":null,
    "quantity":1,
    "receiptId":"wE1EG1gsEZI9q9UnI5YoZ2OxeoVKPdR5bvPMqyKQq5Y=:1:11",
    "renewalDate":null,
    "term":null,
    "termSku":null,
    "testTransaction":true
    }

RVS response codes

The Receipt Verification Service responds 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 410 The transaction represented by this receiptId is no longer valid. Treat it as a canceled receipt.
HTTP 429 The request was throttled. Reduce your calling rate and retry after some time.
HTTP 496 Invalid shared secret
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 canceled, or the subscription expired. The field is null if the purchase was not canceled. Time is in milliseconds.
cancelReason Integer Indicates why a product was canceled. Possible values are null, 0, 1, or 2, where each integer represents a cancellation reason:
null - The purchase was not canceled.
0 - The cancel reason is currently unavailable and will render at a later time.
1 - Your customer canceled the order.
2 - The purchase was canceled by Amazon's system. For example, a customer purchases a subscription with an invalid payment and the purchase could not be completed in the grace period. This code is also returned if Amazon customer support canceled the order at the request of a customer.
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.
fulfillmentDate Long integer In a subscription purchase, the date of the acknowledgement of fulfillment. Stored as the number of milliseconds since the epoch. Null if subscription fulfillment isn't confirmed. Always null for consumables and entitlements.
fulfillmentResult String In a subscription purchase, the status of fulfillment. Valid values:
  • FULFILLED: You provided the content and the customer consumed the content.
  • UNAVAILABLE: You were unable to provide the content to the customer.
Null if subscription fulfillment isn't confirmed. Always null for consumables and entitlements.
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.
promotions List<Promotion> Details of the promotional pricing or retention offer of a subscription purchase. Null if there is no promotion. See Promotions in RVS.
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.
purchaseMetadataMap Map <String, String> If the purchase was initiated via Quick Subscribe, the value is {"QuickSubscribe":"true"}. Otherwise null.
quantity Integer Quantity purchased. Always null or 1.
receiptId String Globally 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.

Promotions in RVS

For details on how to set up a promotional pricing offer, see Set Up Promotional Pricing. For details on how to set up a retention offer, see Retention Offers. If a customer purchased a subscription with promotional pricing or is renewing a subscription with a retention offer discount, the receipt returned through RVS includes the promotion details. The JSON response described in the previous section includes a promotions field. This section explains the promotions field in more detail. Promotion details are present only on a receipt that corresponds to a customer's purchase of a subscription with promotional pricing or a retention offer discount.

The promotions field is null if there is no promotion associated with the receipt. Otherwise, the field contains a list of Promotion objects, with the following fields.

Field Data Type Description
promotionType String Type of promotion. Valid values:
  • Introductory Price - All Customers
  • Promotional Price - Lapsed Customers
  • Retention Offer
For details, see Valid value descriptions.
promotionStatus String Status of the promotion for this customer. Valid values:
  • Queued
  • InProgress
  • Completed
For details, see Valid value descriptions.

Example:

"promotions": [
    {
            "promotionType":"Introductory Price - All Customers",
            "promotionStatus":"Completed"
    }
]

Valid value descriptions

Valid values for the promotionType field are:

  • Introductory Price - All Customers— An offer available to all customers (includes new and lapsed customers).
  • Promotional Price - Lapsed Customers— An offer available to lapsed customers only.
  • Retention Offer— An offer available to eligible subscribers planning to cancel their subscriptions.

Valid values for the promotionStatus field are:

  • Queued— The customer purchased a subscription with a promotional pricing offer. Currently, they're on a free trial and have yet to start the promotion period. This field isn't applicable to retention offers.
  • InProgress— The customer is currently enjoying promotional pricing or a retention offer.
  • Completed— The customer has completed the promotional period of the promotional pricing offer. This field isn't applicable to retention offers.

Promotions FAQ

The following are frequently asked questions (FAQ) about promotions in RVS.

Q: Are the promotion details available in all the receipts for a customer's subscription?
No, the promotion details are present only on the receipt corresponding to the subscription purchase with a promotional offer.
Q: Are the promotion details present after the receipt is canceled?
Yes, for promotional pricing, the promotion details are present as Completed if the customer's subscription is canceled. However, after a customer has enjoyed a retention offer, their subscription renews at the regular price, and promotional details aren't available in the receipt.
Q: For promotional pricing, what is the promotion status if the customer cancels the subscription during the free trial, before renewing to the promotional plan?
Since the customer didn't start the promotional period, the receipt doesn't have any promotion details associated with it.

Cancel date and renewal date

The cancelDate field contains the date that a subscription purchase expired or that Amazon customer service canceled the purchase. The cancel date represents the date when the customer lost access to the content. When a customer cancels their subscription by turning off autorenew, the cancel date is when the renewal date would have been.

The renewalDate field contains the date that an autorenew subscription purchase next needs to be renewed. This field applies to subscription purchases only. If a customer has a monthly subscription, the subscription renews monthly on the same date the customer first subscribed. In the case where the next month does not include the exact date, the renewal date is the closest prior date. For example:

  • If a customer subscribed on January 2, the next three renewal dates are February 2, March 2, and April 2.
  • If a customer subscribed on January 31, the next three renewal dates are February 28 (or February 29 if it is a leap year), March 31, and April 30.

The renewalDate and cancelDate 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 canceled 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 canceled the purchase.

The renewalDate field contains the date that an autorenew subscription purchase next needs to be renewed. The field value will be null if the subscription is not set to autorenew.

In the following example, the user has a subscription that was canceled:

  • The subscription was active from January 1, 2023 to March 1, 2023. In this receipt, the purchaseDate for this subscription is set to January 1, 2023, and the cancelDate is set to March 3, 2023.
  • If this subscription is subsequently reactivated on April 1, 2023, the subscription will have a second receipt. The second receipt will show a purchaseDate of April 1, 2023 and a cancelDate of null.

RVS sandbox and production examples

See RVS Examples for Appstore SDK IAP.


Last updated: Jun 13, 2024