Developer Console

IAP Best Practice - Track Customer Purchase Trends

This guide outlines tracking your customers’ purchase trends by monitoring the canceled receipts rate as a strategy to make the most out of your app.

Use the Appstore UserId

The UserId is a unique identifier for every customer that uses IAP. You can retrieve your customer’s UserId by invoking the PurchasingService.getUserData() method. For details, see Get User Information.

If you have implemented your app in Unity, fetch the UserId by implementing IAmazonExtensions. For details, see Amazon Appstore and Amazon Underground Store Extended Functionality. Alternatively, use the getUserData() method of the Amazon IAP plugin. In that case, see GetUserData for details.

To track your customer's purchase history and trends, link the customer's Appstore UserId to your identity management system. Introduce an identity system to your app by integrating with an identity platform, such as Login with Amazon. Alternatively, you can use other services (for example, Facebook’s login service), or create your own system.

IAP receipt validation

Once a user completes a purchase, process the receipt in your onResume() call without requiring further user interaction. See Implement getPurchaseUpdates method for details. 

Validate the receipt by integrating with the Receipt Verification Service (RVS), and call it by providing: 

  • A receiptId: This is the unique identifier of every purchase. Retrieve receiptId from onPurchaseResponse() callbacks as illustrated below:

       @Override
       public void onPurchaseResponse(PurchaseResponse purchaseResponse) {
          switch (purchaseResponse.getRequestStatus()) {
              case SUCCESSFUL:
                  receiptId = purchaseResponse.getReceipt().getReceiptId();
                  PurchasingService.notifyFulfillment(purchaseResponse.getReceipt().getReceiptId(),
                  FulfillmentResult.FULFILLED);
                  break ;
              case FAILED:
                  break ;
          }
       }
    
  • A userId: This is the unique identifier of the customer. Retrieve userId from onUserDataResponse() callbacks as outlined below:

      @Override
      public void onUserDataResponse(UserDataResponse response) {
          final UserDataResponse.RequestStatus status = response.getRequestStatus();
          switch (status) {
              case SUCCESSFUL:
                  currentUserId = response.getUserData().getUserId();
                  currentMarketplace = response.getUserData().getMarketplace();
                  break;
              case FAILED:
              case NOT_SUPPORTED:
                  // Fail gracefully.
                  break;
          }
      }
    

Here is the RVS request syntax:

https://<RVS_server_Url>/version/<Operation_version_number>/verifyReceiptId/developer/<Shared_Secret>/user/<UserId>/receiptId/<ReceiptId>

Request and response examples

The example below illustrates a request that verifies a receipt on the RVS production server: 

https://appstore-sdk.amazon.com/version/1.0/verifyReceiptId/developer/2:smXBjZkWCxDMSBvQ8HBGsUS1PK3jvVc8tuTjLNfPHfYAga6WaDzXJPoWpfemXaHg:iEzHzPjJ-XwRdZ4b4e7Hxw==/user/LRyD0FfW_3zeOlfJyxpVll-Z1rKn6dSf9xD3mUMSFg0=/receiptId/wE1EG1gsEZI9q9UnI5YoZ2OxeoVKPdR5bvPMqyKQq5Y=:1:11

The RVS API returns a response code (HTTP 200), if the request is successful. Here is an example response for a successful request:

{
    "betaProduct": false,
    "cancelDate": 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
}

Receipt verification

Your app may be vulnerable to refund fraud if the server-side receipt verification is not implemented properly. If you do not verify the cancel date, a customer could cancel a purchase and continue to receive services.

With Receipt Verification Service (RVS), you can check the cancelDate field to verify the receipt. For all in-app purchases (consumables, entitlements, or subscriptions), the receipt is valid if the cancelDate field is null.

Here is an example of a canceled receipt:

{
    "betaProduct": false,
    "cancelDate": 1583136000000,
    "parentProductId": null,
    "productId": "com.amazon.iapsamplev2.gold_medal",
    "productType": "CONSUMABLE",
    "purchaseDate": 1583049600000,
    "quantity": 1,
    "receiptId": "wE1EG1gsEZI9q9UnI5YoZ2OxeoVKPdR5bvPMqyKQq5Y=:1:11",
    "renewalDate": null,
    "term": null,
    "termSku": null,
    "testTransaction": true
}

For more information about RVS, see Receipt Verification for IAP Apps.

Additional recommendations

  1. Monitor trends of the canceled receipts by creating a process to call the RVS within 72 hours for each active receipt.
  2. Keep the rate of the polling below 10 Transactions Per Second (TPS) to avoid request throttling.
  3. Continuous polling of RVS for canceled receipts is not recommended because canceled receipts cannot be revived.
  4. If your request for a receiptId gets throttled, then wait for some time before retrying the same receiptId and reduce your calling rate.

Next steps

Implementing the above strategy can help you create a reliable process to track customer purchase trends, and ensure this important source of revenue is secure. Check out our In-App Purchasing Overview for more details on IAP and how to implement it in your projects.


Last updated: Sep 21, 2022