RVS for Subscriptions
The Receipt Verification Service (RVS) for the Appstore Billing Compatibility SDK lets you validate purchases made by your app's users. For an overview of RVS, see Receipt Verification Service Overview.
RVS for the Appstore Billing Compatibility SDK has two REST APIs, one for verifying consumable and entitlement purchases, and another for verifying subscription purchases. This page describes the requests and responses of the REST API used for subscription purchases.
- purchases.subscriptionsv2.get API request
- purchases.subscriptionsv2.get API response
- Response codes and error messages
- Response fields for successful transactions
- Promotions in RVS
- Data types
- Unsupported fields for purchases.subscriptionsv2.get API
- Cancel date and renewal date
- Related topics
purchases.subscriptionsv2.get API request
Use the purchases.subscriptionsv2.get API to verify the receipts of subscription purchases made through the Appstore Billing Compatibility SDK.
Upon successful purchase of an item, the Appstore Billing Compatibility SDK returns a Purchase
object. To perform a server-side validation of the purchase, extract the purchase token from this object and pass it, along with the app package name and your shared secret to the RVS server. For security, when you make a request from your server, you must pass a shared secret to confirm your identity.
The request uses the following format:
https://appstore-sdk.amazon.com/version/{operation-version-number}/developer/{shared-secret}/applications/{package-name}/purchases/subscriptionsv2/tokens/{token}
The curly brackets contain placeholders for the request parameters. In your request, replace the placeholders with the values from the transaction you want to verify. The following table lists descriptions of the request parameters.
Request parameter | Description |
---|---|
operation-version-number | Version number of the purchases.subscriptionsv2.get operation. This version number is independent of the Appstore Billing Compatibility SDK version number. The current purchases.subscriptionsv2.get 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. |
package-name | The package name of the application in which the in-app product was sold. For example, 'com.amazon.sample.iap.consumable'. You can get the package name from your app by calling getApplicationContext().getPackageName() or you can find it in the AndroidManifest.xml file. |
token | Unique ID for the purchase obtained from the Purchase object's getPurchaseToken() method. |
purchases.subscriptionsv2.get API response
The purchases.subscriptionsv2.get API provides a RESTful JSON API interface. As a best practice, use a JSON parser class, such as OkHttp or Apache HttpClient, for reading the JSON responses from the RVS server.
After you make a request to the RVS server to verify a transaction, the RVS server 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:
{
"cancelDate": 1638906732000,
"canceledStateContext": {
"developerInitiatedCancellation": null,
"replacementCancellation": null,
"systemInitiatedCancellation": {},
"userInitiatedCancellation": null
},
"deferredDate": null,
"freeTrialEndDate": null,
"fulfillmentDate": null,
"fulfillmentResult": null,
"gracePeriodEndDate": null,
"kind": "androidpublisher#subscriptionPurchaseV2",
"lineItems": [
{
"autoRenewingPlan": {
"autoRenewEnabled": true
},
"deferredItemReplacement": null,
"expiryTime": "1638906732000",
"offerDetails": {
"basePlanId": "amzn1.appstore.iap.compatibility.baseplan.termsku.pom.subscription.weekly",
"offerId": "amzn1.appstore.iap.compatibility.offer.termsku.pom.subscription.weekly"
},
"productId": "pom.subscription"
}
],
"promotions": null,
"purchaseTimeMillis": "1638465681000",
"purchaseToken": "s_gaorSDP-W8R0xucVkDIcR5gQuHrqX37cn8MzQoOHo=:3:14",
"renewalDate": null,
"startTime": "Tue Dec 07 17:21:21 UTC 2021",
"subscriptionState": "SUBSCRIPTION_STATE_EXPIRED",
"term": "1 Day",
"testPurchase": null,
"testTransaction": false
}
Response codes and error messages
The Receipt Verification Service responds with one of the following codes, which indicate the result of the validation check.
HTTP response code | Description |
---|---|
200 | The purchase is valid. |
400 | The purchase token is invalid. |
401 | The developer secret is invalid or doesn't match the given purchase token. |
404 | The package name is invalid or doesn't match the given purchase token. |
410 | The transaction represented by this receiptId is no longer valid. Treat it as a canceled receipt. |
429 | The request was throttled. Reduce your calling rate and retry after some time. |
500 | There was an Internal Server Error. |
Response fields for successful transactions
The following table describes the fields included in a purchases.subscriptionsv2.get response for a successful transaction. Some fields have the same name and data type as Google's purchases.subscriptionsv2.get API. Those fields are listed under Fields that match Google's purchases.subscriptionsv2.get API. Fields listed under Additional fields are different from Google APIs and present purchase details provided by the Amazon Appstore.
Field | Data type | Description |
---|---|---|
Fields that match Google's purchases.subscriptionsv2.get API | ||
kind |
String | Represents a SubscriptionPurchaseV2 object in the androidpublisher service. |
lineItems |
List<SubscriptionPurchaseLineItem> | Item-level information for a subscription purchase. |
startTime |
String | Time at which the subscription was granted. |
subscriptionState |
Enum (SubscriptionState) | The current state of the subscription. |
canceledStateContext |
CanceledStateContext | Additional context around canceled subscriptions. Only present if the subscription currently has subscriptionState SUBSCRIPTION_STATE_EXPIRED . |
testPurchase |
TestPurchase | Indicates whether this subscription purchase is a test purchase. |
Additional fields | ||
purchaseTimeMillis |
String | The date of the purchase, stored as the number of milliseconds since the epoch (Jan 1, 1970). purchaseTimeMillis represents the initial purchase date, not the purchase date of subsequent renewals. |
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. |
testTransaction |
Boolean | Indicates whether this purchase was made as a part of Amazon's publishing and testing process. |
renewalDate |
Boolean | The date that a subscription purchase needs to be renewed. The date is stored as the number of milliseconds since the epoch. |
purchaseToken |
String | Unique identifier for the purchase. |
term |
String | Duration of the subscription period for the IAP item. The term starts on the date of purchase. The term consists of a number and a time period (which can be Day, Week, Month, or Year), such as 1 Week or 2 Months. |
deferredDate |
Long integer | Date when the current productId will be replaced by a new productId . |
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. |
purchaseMetadataMap |
Map <String, String> | Always null. Reserved for future use. |
promotions |
List<Promotion> | Details of the retention offer of a subscription purchase. Null if there is no retention offer. See Promotions in RVS. |
fulfillmentDate |
String | 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. |
fulfillmentResult |
Long integer | In a subscription purchase, the status of fulfillment. Valid values:
|
Promotions in RVS
The JSON response described in the previous section includes a promotions
field. This section explains the promotions
field in more detail. If a customer is renewing a subscription with a retention offer discount, the receipt returned through RVS includes the promotion details. For details on how to set up a retention offer, see Retention Offers.
Promotion details are present only on a receipt that corresponds to a customer's purchase of 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:
Retention Offer |
promotionStatus |
String | Status of the promotion for this customer. Valid values:
InProgress - The customer is currently enjoying a retention offer. |
Example:
"promotions": [
{
"promotionType":"Retention Offer",
"promotionStatus":"InProgress"
}
]
Data types
The following sections describe data types you might encounter in the purchases.subscriptionsv2.get response.
SubscriptionPurchaseLineItem
Item-level information for a subscription purchase.
Field | Data type | Description |
---|---|---|
productId |
String | The product ID of the purchased product. |
expiryTime |
String | Time at which the subscription expired or will expire unless the access is extended (the subscription is renewed). |
autoRenewingPlan |
AutoRenewingPlan | The item is auto-renewing. |
offerDetails |
OfferDetails | The offer details for this item. |
deferredItemReplacement |
DeferredItemReplacement | Always null. Reserved for future use. |
AutoRenewingPlan
Information related to an auto-renewing plan.
Field | Data type | Description |
---|---|---|
autoRenewEnabled |
Boolean | Indicates if customer's subscription will auto-renew. |
OfferDetails
Offer details information related to a purchase line item.
Field | Data type | Description |
---|---|---|
basePlanId |
String | The base plan ID. Present for all base plan and offers. |
offerId |
String | The offer ID. Only present for discounted offers. |
SubscriptionState
Indicates the current state of a subscription. For example, whether a subscription is active or expired.
Enum | Description |
---|---|
SUBSCRIPTION_STATE_UNSPECIFIED |
Unspecified subscription state |
SUBSCRIPTION_STATE_ACTIVE |
Subscription is active |
SUBSCRIPTION_STATE_IN_GRACE_PERIOD |
Subscription is in grace period |
SUBSCRIPTION_STATE_EXPIRED |
Subscription is expired |
CanceledStateContext
Information specific to a subscription in canceled state.
Field | Data type | Description |
---|---|---|
userInitiatedCancellation |
UserInitiatedCancellation | Subscription was canceled by user. |
systemInitiatedCancellation |
SystemInitiatedCancellation | Subscription was canceled by the system, for example because of a billing problem. |
developerInitiatedCancellation |
DeveloperInitiatedCancellation | Always null. Reserved for future use. |
replacementCancellation |
ReplacementCancellation | Always null. Reserved for future use. |
UserInitiatedCancellation
Information specific to cancellations initiated by users.
Field | Data type | Description |
---|---|---|
cancelTime |
String | The time at which the subscription was canceled by the user. |
SystemInitiatedCancellation
This type has no fields.
Information specific to cancellations initiated by Amazon system.
TestPurchase
This type has no fields.
If the subscription purchase is a test purchase, this appears as an empty object {}
. Null if not a test purchase.
Unsupported fields for purchases.subscriptionsv2.get API
The following fields that are available in the Google Play Developer API, aren't supported in the Appstore Billing Compatibility RVS API.
regionCode
lineItems[].autoRenewingPlan.priceChangeDetails
lineItems[].prepaidPlan
lineItems[].offerDetails.offerTags
latestOrderId
linkedPurchaseToken
pausedStateContext
canceledStateContext.userInitiatedCancellation.cancelSurveyResult
acknowledgementState
externalAccountIdentifiers
subscribeWithGoogleInfo
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 thecancelDate
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 acancelDate
of null.
Related topics
- RVS for Consumables and Entitlements
- RVS Production Setup for Appstore Billing Compatibility
- RVS Examples for Appstore Billing Compatibility
Portions of this page are modifications based on work created and shared by Google and used according to terms described in the Creative Commons 4.0 Attribution License. Sources: https://developers.google.com/android-publisher/api-ref/rest/v3/purchases.subscriptionsv2/get, https://developers.google.com/android-publisher/api-ref/rest/v3/purchases.subscriptionsv2.
Last updated: Oct 14, 2024