Skip to main content

In-App Purchase Validation

The spectrum of monetization models and tools is extremely varied, from ad-supported, microtransactions, freemium, one-off purchases, and everything in between. A key tool in many of these solutions is the In-App Purchase(IAP). IAPs enable single purchases for unlocks, in-game consumables, subscriptions for premium access, and more.

There are a number of readily available attacks against the most common in-app purchase implementations. These are usually focused around:

  • Feeding the client fake purchase responses which indicate success
  • Replaying a valid purchase response multiple times
  • Sharing a purchase response with another client, so multiple players can receive the reward from a single purchase

For in-app purchases a trusted source of truth is required. LayerG checks and tracks purchases and purchase history, solving a significant set of possible vulnerabilities and pain points:

IssueDescription
Fake PurchasesLayerG directly connects to Apple, Google and Huawei services to check the validity of all incoming purchase receipts. This verification is completely outside the client’s code, and cannot be intercepted and tampered with. Every purchase receipt is verified, every time, and invalid ones are rejected.
Replay AttacksAll transactions are logged, preventing multiple submissions of the same purchase token or receipt
Receipt SharingSuccessful transactions are bound to the account that submits them. Different users cannot submit the same transaction, even a valid one, in an attempt to receive the associated reward.
Product MismatchesEach validated purchase receipt exposes data (e.g. product ID) that can be used to tie a purchase to a product, preventing attacks that attempt to use a valid (cheap) purchase to unlock a different (expensive) reward.
Single Source of TruthWhile LayerG maintains an internal record of all transactions, the remote payment provider is always used for validation.

In-App Purchase Validation is available for Apple, Google, and Huawei purchases, regardless of platform. Both single product and subscription purchases are supported.

Apple and Google purchases made via Unity IAP are also supported.

Interpreting validation results

A validation result contains a list of validated purchases.

Because Apple may contain multiple purchases in a single receipt, each validated purchase in the resulting list will contain only the purchases which have been validated and a boolean value to indicate if it has been seen before or not. If a purchase has already been validated by LayerG previously then the “seen before” value will be true, allowing the developer to discriminate new purchases and protect against replay attacks.

For Google and Huawei, each validation corresponds to a single purchase, which is included in the validation response list and also has a “seen before” value as above.

Each validated purchase also includes the payload of the provider validation response, should the developer need it for any reason.

Should the purchase/receipt be invalid, the validation fail for any reason, or the provider be unreachable, an error will be returned.

Apple

LayerG supports validating purchases made for products and subscriptions in iOS.

Apple purchase receipts are sent to Apple for validation. As suggested by Apple, both Production and Sandbox servers are used to validate receipts.

Setup

To validate receipts against the App Store, LayerG requires your app’s shared secret.

  1. From App Store Connect navigate to the General > App Information page and the App-Specific Shared Secret section:

Apple App Store Connect

Apple App Store Connect

  1. Select Manage and in the dialog that appears, select Generate:

Generate Apple App Store Connect Shared Secret

Generate Apple App Store Connect Shared Secret

  1. Make a record of your shared secret for use in your LayerG configuration:

New Apple App Store Connect Shared Secret

New Apple App Store Connect Shared Secret

  1. Set the value of LayerG’s iap.apple.shared_password configuration flag to the value of the shared secret created above.

Validate purchase

LayerG only supports validating iOS 7+ receipts.

Apple receipts can contain multiple purchases, LayerG will validate all of them and store them as individual purchase records.

Refer to the function reference page for the provided runtime purchase validation functions.

Validate subscription

Refer to the function reference page for the provided runtime subscription validation functions.

IAP notifications

The Apple App Store supports Server Notifications to monitor IAP state updates, such as purchase refunds or subscription auto-renewals. LayerG supports receiving these notifications via a callback URL that can be activated and set up in App Store Connect to act upon a subset of these state updates.

To activate the callback URL the notifications_endpoint_id configuration needs to be set, and takes on the following path: /v2/console/apple/subscriptions/<notifications_endpoint_id>.

Once the URL is set up in both LayerG and App Store Connect, any Apple subscription that was previously validated using the LayerG API will automatically have its state updated via the real-time notifications so that, for example, auto-renewing subscriptions expiry time are automatically kept in sync with the App Store.

IAP refunds

The Apple App Store can send Server Notifications relating to refunded purchases and subscriptions.

After setting up the callback URL described in the IAP Apple Notifications section, it is possible to register hooks with custom code to handle a refund for either a purchase or subscription.

The hook will only be fired for purchases/subscriptions that were previously validated via the respective LayerG Apple IAP validation APIs.

Google

LayerG supports validating purchases made for products and subscriptions on Android.

Setup

To validate receipts against the Play Store, LayerG requires the client_email and private_key of the relevant Google Service Account for your project.

  1. Setup a Service Account in the Google API Console:

Create Service Account

Create Service Account

  1. Once a service account is created, you’ll need to create a key:

    Create Key

    Create Key

  2. Download the key as a JSON file:

Create JSON Key

Create JSON Key

Enable API

Enable API

  1. If you don’t already have a service account, create one as detailed in the official Google documentation.
  • Be sure to grant your service account the following permissions: View financial data, orders, and cancellation survey responses and Manage orders and subscriptions.
  1. Finally you will need to ensure you grant LayerG access to the purchase validation APIs. From the Google Play Developer Console and navigate to Settings > API Access:

Create API Access

Create API Access

  1. The service account you created in the previous steps should be listed above. Grant access to the service account to access the API, making sure you give the service account access to Visibility, View Financial Data, and Manage Orders. These permissions are required for LayerG to validate receipts against Google Play.

Grant Access

Grant Access

  1. Navigate to Users & Permissions to check that the service account is setup correctly:

List users with access

List users with access

Validate purchase

The Google receipt expected is the string returned by Purchase.getOriginalJson(). See the official Google Developer docs for more details.

Refer to the function reference page for the provided runtime purchase validation functions.

Validate subscription

Refer to the function reference page for the provided runtime subscription validation functions.

IAP notifications

Google supports setting up real-time developer notifications to monitor subscription state changes (e.g. when a subscription auto-renews).

The LayerG callback URL can be activated by setting the notifications_endpoint_id configuration, and takes on the following path: /v2/console/google/subscriptions/<notifications_endpoint_id>.

Once the URL is set up both in LayerG and the Google Developer Console, any Google subscription that was previously validated using the LayerG API will automatically have its state updated via the real-time notifications so that, for example, auto-renewing subscriptions expiry time are automatically kept in sync with Google.

IAP refunds

Google provides an API to list refunded purchases. LayerG can be configured to poll this API periodically on configurable intervals.

To enable the periodic check of refunded purchases/subscriptions the following configurations have to be set:

To allow acting on a refunded purchase/subscription, hooks are provided to register custom functions that will be invoked for each, but only for those that have been previously validated using the respective LayerG Google IAP validation APIs.

Facebook Instant Games

LayerG supports validating purchases made for products on Facebook Instant Games.

Validate purchase

Huawei

LayerG validates Huawei purchases against their IAP validation service. As suggested by Huawei, the validity of the purchase data is also checked against the provided signature before contacting the Huawei service. If the data is invalid for any reason, the purchase is rejected before validation with Huawei’s validation service.

Validate purchase

Refer to the function reference page for the provided runtime purchase validation functions.

Unity IAP

Unity IAP has support for integrating with most popular app stores, including Apple and Google.

Unity IAP purchase receipts contain the following information:

KeyValue
StoreThe name of the store in use, such as GooglePlay or AppleAppStore.
TransactionIDThis transaction’s unique identifier, provided by the store.
PayloadFor Apple, a Base64 encoded App Receipt. For Google, JSON encoded purchase data and a signature.

For Apple, a Base64 encoded App Receipt. For Google, JSON encoded purchase data and a signature.

The LayerG IAP Validation APIs expect only the content of the “Payload” key to be provided for validation in the respective store endpoints.

Validate purchase

Subscriptions

In addition to validation of purchases and subscriptions, you can also get subscriptions by specific product ID or list all subscriptions for a given user.

Get subscription

Refer to the function reference page for the provided runtime subscription validation functions.

List user subscriptions

Refer to the function reference page for the provided runtime subscription validation functions.