Developer Console

IAP Best Practice - Track Customer Purchase Trends

As a strategy to track your customers' purchase trends, you can monitor the rate of canceled receipts in your app.

Use the Appstore user ID

The user ID is a unique identifier for every customer that uses IAP. Retrieve your customer's user ID through the PurchasingService.getUserData() method. For details, see Get User Information.

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

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

IAP receipt validation

After a user completes a purchase, process the receipt in your onResume() call without requiring further user interaction. For details, see Implement getPurchaseUpdates method

To validate the receipt, integrate with the Receipt Verification Service for Appstore SDK IAP. The RVS call requires the following parameters:

  • A receipt ID. This is the unique identifier of every purchase. Retrieve the ReceiptId object from onPurchaseResponse() callbacks as shown in the following example.

       @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 user ID. This is the unique identifier of the customer. Retrieve the user ID string from onUserDataResponse() callbacks as shown in the following example.

      @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}/version/{operation-version-number}/verifyReceiptId/developer/{shared-secret}/user/{user-id}/receiptId/{receipt-id}

Request and response examples

The following example shows 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 Service for Appstore SDK IAP.

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: Mar 15, 2024