Developer Console

Set Up Quick Subscribe

For an overview of Quick Subscribe, see Quick Subscribe Overview. When you're ready to get started, contact your Amazon representative to have them enable Quick Subscribe on your account. Then, follow the steps on this page.

Prerequisites

Integrate with the Appstore SDK version 3.0.6 or higher. For details, see Integrate the Appstore SDK.

Step 1: Configure Quick Subscribe in the Developer Console

Important

Any subscriptions available for customers to purchase in-app should also be available to purchase through Quick Subscribe, and any subscriptions available in Quick Subscribe should be available to purchase in-app. An exception to this is if you have five or more subscriptions available in-app. Then you must choose four subscriptions and offer them through Quick Subscribe.

To configure Quick Subscribe for your app, follow these steps

  1. Sign in to the Developer Console.
  2. In your app list, find the app you want to set up with Quick Subscribe.
  3. In the In-App Items column, click the link to open the In-App Items screen.
  4. Select Create Quick Subscription.
  5. An overlay pop-up appears as shown in the following image.
    Create new quick subscription. Choose default subscription. Select term. Choose target devices. Available action buttons are Cancel, Create Quick Subscription for Test, and Create Quick Subscription for Test and Live.
    Create new quick subscription dialog

    In the Choose default subscription drop down, the list is populated with your existing IAP subscriptions. Choose the subscription on which you want to enable Quick Subscribe.

  6. In the Select term drop down, choose a term for the quick subscription.
  7. If you would like to offer additional subscriptions for Quick Subscribe, select Add another quick subscription. You can add a maximum of four quick subscriptions.
  8. Choose your target devices for Quick Subscribe by checking the boxes.
  9. Choose whether to create the quick subscription for Live App Testing (LAT) only or for both LAT and your live app.
    • To create a quick subscription for LAT only, select Create Quick Subscription for Test.
    • To create the quick subscription for both LAT and the live app, select Create Quick Subscription for Test and Live.

After you create a quick subscription, you can delete or modify it by selecting Actions next to the Quick Subscribe item.

Step 2: Configure security profile

To configure a security profile for your app, follow these steps

  1. Sign in to the Developer Console.
  2. Open the app list and select your app.
  3. Select App Services and scroll to the Security Profile section.
  4. Click Select existing security profile or create new to expand the options.
  5. Use the drop-down to select the security profile that you want to map to this app, then click Enable Security Profile. Alternatively, you can create a new security profile by clicking Create Security Profile.

Step 3: Implement getPurchaseUpdates

The getPurchaseUpdates() method gets the user's receipts. Quick Subscribe uses the information from getPurchaseUpdates() to verify your user's purchase status, ensuring that the user has access to the content to which they are entitled.

Call getPurchaseUpdates() in the onResume() method. The getPurchaseUpdates() method takes one boolean parameter, reset. Set reset to false to return only the new receipts since the last time you called this method. Set reset to true to return all of the receipts for this user.

@Override
protected void onResume() {
  super.onResume();

//...

  PurchasingService.getUserData();

//...

  PurchasingService.getPurchaseUpdates(false);
}

For more information on how to integrate the getPurchaseUpdates() method, see IAP API documentation:

Implementation requirements

Follow these requirements to properly implement the getPurchaseUpdates() method.

  • You must call getPurchaseUpdates() in the onResume() lifecycle method of the Android activity.
  • Always use the false flag while calling getPurchaseUpdates() in onResume() to get the latest receipts. If you use the true flag, it returns the full history of receipts, and you would have to add extra filtering logic to handle the response.
  • Add a "Restore Purchases" option in your app which calls getPurchaseUpdates() with the true flag when selected by a customer.
  • The receipts received through getPurchaseUpdates() must always be persisted and must be mapped to the app's login ID. Use this mapping to unlock the subscribed content to customers when they open the app.

Step 4: Integrate with RVS

The Receipt Verification Service (RVS) lets you validate purchases made by your app's users. When you make a request to the RVS server, the JSON response returned includes a purchaseMetadataMap field. If the purchase was initiated using Quick Subscribe, the purchaseMetadataMap appears as {"QuickSubscribe":"true"}, as seen in the following example.

{
  "autoRenewing": true,
  "betaProduct": false,
  "binCountryCode": null,
  "cancelDate": 1641131573000,
  "cancelReason": 2,
  "deferredDate": null,
  "deferredSku": null,
  "freeTrialEndDate": null,
  "fulfillmentDate": 1641131345000,
  "fulfillmentResult": "FULFILLED",
  "gracePeriodEndDate": null,
  "parentProductId": null,
  "productId": "IntroFreeTrial.sku",
  "productType": "SUBSCRIPTION",
  "promotions": null,
  "purchaseDate": 1641131345000,
  "purchaseMetadataMap": {
      "QuickSubscribe": "true"
  },
  "quantity": null,
  "receiptId": "k9om1rUS7gZJIg8RMfw7AlbxA3aP56ay-vdgeLU40zw=:3:11",
  "renewalDate": null,
  "term": "1 Month",
  "termSku": null,
  "testTransaction": false
}

If the purchase wasn't initiated using Quick Subscribe, purchaseMetadataMap appears as null. The following table provides a description for all fields in the response object.

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.

For more details on RVS, see Receipt Verification Service for Appstore SDK IAP.

Step 5: Send fulfillment result to Amazon

When you send a fulfillment result, you ensure that Amazon can confirm whether users can access the content that they paid for. Always communicate the fulfillment result to Amazon. To do this, use the notifyFulfillment() method included in the Appstore SDK.

After a customer signs in, call notifyFulfillment() with status FULFILLED when the subscription is fulfilled. If the customer already has a subscription, call notifyFulfillment() with status UNAVAILABLE to indicate that the customer has signed in but the purchase isn't applicable. For more information about the notifyFulfillment() method, see Send fulfillment result to Amazon and grant item to the user.

If you've previously integrated with the Acknowledge Receipt API, you can continue to use it in place of the notifyFulfillment() method. You must use either the notifyFulfillment() method or the Acknowledge Receipt API in your app to communicate the fulfillment result to Amazon.

Implementation requirements

Follow these requirements to properly implement the notifyFulfillment() method.

Acknowledge Receipt API

Step 6: Integrate with RTN

With Quick Subscribe, customers subscribe to your app through Amazon, rather than through your app. This could lead to your app missing some information about a customer's purchase state. The getPurchaseUpdates() method sends data only when an app is opened.

Real Time Notifications (RTN) provides customer purchase information for all transactions, including the ones that occur outside your app. When your server receives a purchase notification from Amazon's RTN server, use the Receipt Verification Service for Appstore SDK IAP (RVS) to validate the receipt.

For details about how to set up RTN, see Use Real-Time Notifications.

Step 7: Integrate one-click account information sharing

Use this guide to integrate your app with the one-click account information sharing feature.

Update app manifest

To indicate to the Appstore that your app supports the one-click account information sharing feature, update your app's manifest with the following code.

<uses-feature android:name="amazon.lwa.quicksignup.supported"/>

Implement getUserData changes

To determine whether a customer has explicitly consented to share their Amazon account details with your app, you must implement the following process during your app's initialization.

In the onCreate() method of your app's main activity:

The following example shows how to build a UserDataRequest object and pass it to getUserData().

@Override
protected void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    
    //...
    
    // Pass the reference of PurchasingListener to be registered
    PurchasingService.registerListener(this.getApplicationContext(), purchasingListener);
    
    // Pass the reference of UserProfileAccessListener to be registered
    PurchasingService.registerUserProfileAccessListener(this.getApplicationContext(), userProfileAccessListener);
     
    // Implement logic to identify customer logged in status inside isLoggedIn()
    if (!isLoggedIn()) {
        PurchasingService.getUserData(UserDataRequest.newBuilder().setFetchUserProfileAccessConsentStatus(true).build());
    }
    //...
}

Implement the onUserDataResponse() callback method to get the UserDataResponse object, which contains customer consent data. The following code shows how to handle the consent data received from the UserDataResponse object.

@Override
public void onUserDataResponse(final UserDataResponse response) {

    UserDataResponse.RequestStatus status = response.getRequestStatus();

    switch (status) {
        case SUCCESSFUL:
            if (UserProfileAccessConsentStatus.CONSENTED.equals(response.getUserData().getUserProfileAccessConsentStatus())) {
                // Initiate the custom loader screen or spinner.
                PurchasingService.requestUserProfileAccess();
            }
            break;

        case FAILED:
        case NOT_SUPPORTED:
            // Fail gracefully.
            break;
    }
}

If a customer provides consent, the UserProfileAccessConsentStatus of the UserData object has the status CONSENTED. If a customer doesn't provide consent or if the consent token expires, UserProfileAccessConsentStatus has the status UNAVAILABLE.

If the customer provides consent, call the requestUserProfileAccess() method and update your server with the authorization code found in the response object. Then, use the REST APIs provided by Appstore SDK to get an access token and the customer profile. Create an account in your system with the user information shared.

The following code shows how to extract the user profile access authorization code from the UserProfileAccessResponse object.

@Override
public void onUserProfileAccessResponse(final UserProfileAccessResponse response) {
    
    UserProfileAccessResponse.RequestStatus status = response.getRequestStatus();
    
    switch (status) {
        case SUCCESSFUL:
            // Here you should update your server with the userProfileAccessAuthCode 
            // to further interact with Appstore SDK REST APIs to get access token and customer profile.
            final String userProfileAccessAuthCode = response.getUserProfileAccessAuthCode();
            break;
    
        case FAILED:
        case NOT_SUPPORTED:
            // Fail gracefully.
            break;
    } 
}

If the customer doesn't provide consent, show your own sign-in screen. The customer can then enter their credentials using the keyboard to sign in to your app.

Get Access Token API

The Appstore SDK provides the Get Access Token REST API for you to obtain an access token. This section describes the request, response, and errors.

Access token request

After the app receives an authorization response with a valid authorization code, it can use that code to obtain an access token. With an access token, the client can read a customer profile.

The Get Access Token API must use a POST request rather than a GET request, as shown in the following example.

POST https://appstore-sdk.amazon.com/version/1.0/auth/o2/token?
grant_type=authorization_code
&code=SplxlOBezQQYbYS6WxSbIA
&client_id=foodev
&client_secret=foosecret

The following table describes the access token request parameters.

Access token request parameters
Request parameter Description
grant_type Required. The type of access grant requested. Must be authorization_code.
code Required. The authorization code returned by the requestUserProfileAccess() method.
client_id Required. The client identifier.
client_secret Required. The secret value assigned to the client during registration. Don't use the client secret in browser-based apps because client secrets can't be reliably stored on web pages.

Access token response

To access customer data, you must provide an access token to the Appstore SDK Get User Profile API. An access token is an alphanumeric code 350 characters or more in length, with a maximum size of 2048 bytes. Access tokens begin with the characters Atza|.

Response parameters are encoded using the application/json media type. For more information, see RFC4627. The following is an example response from an access token request.

{
"access_token":"Atza|IQEBLjAsAhRmHjNgHpi0U-Dme37rR6CuUpSR...",
"token_type":"bearer",
"expires_in":3600,
"refresh_token":"Atzr|IQEBLzAtAhRPpMJxdwVz2Nn6f2y-tpJX2DeX..."
}

The following table describes the access token response parameters.

Access token response parameters
Response parameter Description
access_token The access token for the user account. Maximum size of 2048 bytes.
token_type The type of token returned. Value is bearer.
expires_in The number of seconds before the access token becomes invalid.
refresh_token A refresh token that can be used to request a new access token. Maximum size of 2048 bytes.

An access token is a bearer token and can be used by another client. For more information, see The OAuth 2.0 Authorization Framework: Bearer Token Usage.

Access token errors

For some errors, the authorization service may return an HTTP 401 (Unauthorized) status code. This includes cases where the client passed the client_id and client_secret values in the authorization header and the client could not be authenticated.

The following table describes the error parameters in an unsuccessful response.

Access token error response parameters
Error parameter Description
error An ASCII error code with an error code value.
error_description A human-readable ASCII string with information about the error, useful for client developers.
request_id ID associated to your access token request.

The following error codes can be returned as the value for error.

Access token error response codes
Error code Description
invalid_request The request is missing a required parameter, has an invalid value, or is otherwise improperly formed.
invalid_client The client authentication failed. This is used in cases when the authorization service does not return an HTTP 401 (Unauthorized) status code.
invalid_grant The authorization code is invalid, expired, revoked, or was issued to a different client_id.
unauthorized_client The client is not authorized to use authorization codes. Can be caused by invalid code_verifier.
unsupported_grant_type The client specified the wrong token_type.
ServerError The server encountered a runtime error.

Get User Profile API

The Appstore SDK provides the Get User Profile REST API to get user profile data. This section describes the request, response, and errors.

User profile request

To access authorized user profile data, use the Get User Profile API to submit the access token to the Appstore. The Get User Profile API uses an HTTPS GET request and takes the access token that you received from the Get Access Token API as it's only parameter.

The following example shows a GET request to obtain user profile data.

GET https://appstore-sdk.amazon.com/version/1.0/user/profile?
access_token=Atza|IQEBLjAsAhRmHjNgHpi0U-Dme37rR6CuUpSR...
User profile request parameters
Request parameter Description
access_token Required. The access token received from the Get Access Token API.

User profile response

If your access token is valid, you receive the customer's profile data as an HTTP response in JSON, as shown in this example.

{
"user_id": "amznl.account.K2LI23KL2LK2",
"email":"mhashimoto-04@plaxo.com",
"name" :"Mork Hashimoto",
"postal_code": "98052"
}

If there is a problem fulfilling your profile request, you receive an HTTP error and might receive a JSON payload with more information, as shown in the following example.

{
"error": "machine-readable error code",
"error_description": "human-readable error description",
"request_id": "bef0c2f8-e292-4l96-8c95-8833fbd559df"
}

The following table describes the error codes that can be returned in an unsuccessful user profile request.

User profile error response codes
Status Error Code Description
200 Success The request was successful.
400 invalid_request The request is missing a required parameter or otherwise malformed.
400 invalid_token The access token provided is expired, revoked, malformed, or invalid for other reasons.
401 insufficient_scope The access token provided does not have access to the required scope.
500 ServerError The server encountered a runtime error.

Flow diagram

The following diagram shows the code flow for Quick Subscribe with one-click account information sharing.

See text description.
Click to enlarge

Best practices for account setup

Follow these best practices for setting up customer accounts.

  • If UserProfileAccessConsentStatus has the value CONSENTED in the getUserData() response, do the following:
    • Fetch the user information from the Appstore SDK Get User Profile API. Use this information to create a login account with a temporary password. Sign the customer in to the app without requesting a password reset or additional details from the customer.
    • Later, ask the customer to reset the password through email.
  • If UserProfileAccessConsentStatus is UNAVAILABLE, use the default app sign-up experience for the customer.

Step 8: Test Quick Subscribe with LAT

To test Quick Subscribe with Live App Testing (LAT), first configure Quick Subscribe for LAT in the Developer Console using the steps in Configure Quick Subscribe in the Developer Console. You can configure Quick Subscribe for LAT only, or configure it for both your live and LAT apps, as shown in the following image.

For LAT only, choose Create Quick Subscription for Test. For LAT and live, choose Create Quick Subscription for Test and Live.

If you choose to configure Quick Subscribe for LAT only, you can later promote the configuration to your live app by selecting Actions > Promote to Live as shown in the following image.

Actions menu with options Edit, Turn Off, and Promote to Live

If you configured Quick Subscribe for your LAT app differently than your live app, a TEST label appears in the quick subscription details for the LAT app as shown in the following image.

TEST label appears at the top of the in-app item

You can test the Quick Subscribe flow through the Amazon retail website or on a Fire device. When you start a live app test, you can send invitations to testers. Testers receive an email with a link to the Amazon website with the LAT version of the app.

Test Quick Subscribe on the website

From the LAT invitation email, select the Amazon website for your marketplace. On the app detail page, select the subscription option, which appears as a paid option for a subscription term, such as $20.00 monthly. Then, select a device to deliver to, and click Get App.

Test Quick Subscribe on the device

To get started with testing Quick Subscribe on the device, you can use the LAT invitation email or the device notification.

To test from the LAT invitation:

  1. Use the link in the invitation email to go to the app detail page on the Amazon website.
  2. Select the App Only option.
  3. In the Deliver to: drop-down menu, select Cloud Only.
  4. Click Get App.
  5. On a Fire TV device associated with the Amazon account, click the icon for Your Apps & Channels (the icon appears on the navigation bar as three squares and a plus sign).
  6. Find the LAT version of your app, which has a TEST banner on the app icon. You might need to click App Library to see the app.
  7. Select the app icon to open the app detail page on the device.
  8. Select Subscription Options and download the app.

To test from the notification:

After you send a LAT invite, the test devices associated with the tester email receive a notification. If you open the notification when it appears, you are taken to the LAT app detail page. This notification appears for 5-10 seconds. If you miss the notification when it first appears, you can click the settings icon (the gear icon) and select Notifications to see it. You can then read the notification and go to the app detail page. Select Subscription Options and download the app.

Important

  • Testing Quick Subscribe through LAT isn't supported in the following cases:
    • Using the App Only option on the website when you choose a specific device to deliver to.
    • Using the App Only option on a device.
  • To test the app through LAT for a purpose other than Quick Subscribe, you can use the App Only option and select a specific device to deliver the app to.

  • Turn off accelerated subscriptions while testing Quick Subscribe.

  • To reset Quick Subscribe for a test account, go to the Developer Console to reset subscriptions for LAT. For details, see Reset in-app items for all testers in the LAT or Manage individual testers.

  • If you want to accelerate the 30-day cancellation window to a 1-day window for testing, contact your Amazon representative.

Last updated: Dec 18, 2024