InAppPy
Python In-app purchase validator for Apple AppStore and GooglePlay.
Install / Use
/learn @cx-lukas-salkauskas-x/InAppPyREADME
InAppPy
|ci| |pypi| |downloads|
.. |ci| image:: https://github.com/dotpot/InAppPy/actions/workflows/ci.yml/badge.svg :target: https://github.com/dotpot/InAppPy/actions/workflows/ci.yml .. |pypi| image:: https://badge.fury.io/py/inapppy.svg :target: https://badge.fury.io/py/inapppy .. |downloads| image:: https://img.shields.io/pypi/dm/inapppy.svg :target: https://pypi.python.org/pypi/inapppy
Table of contents
-
Introduction
-
Installation
-
Google Play (
receipt+signature) -
Google Play (verification)
- Setting up Google Service Account Credentials
- Usage Example (with file path)
- Usage Example (with credentials dictionary)
-
Google Play (verification with result)
-
Google Play (consuming products)
-
App Store (
receipt+ using optionalshared-secret) -
App Store Response (
validation_result/raw_response) example -
App Store, asyncio version (available in the inapppy.asyncio package)
-
Development
-
Donate
-
Introduction ===============
In-app purchase validation library for Apple AppStore and GooglePlay (App Store validator have async support!). Works on python3.6+
-
Installation =============== ::
pip install inapppy
-
Google Play (validates
receiptagainst providedsignatureusing RSA) =========================================================================== .. code:: pythonfrom inapppy import GooglePlayValidator, InAppPyValidationError
bundle_id = 'com.yourcompany.yourapp' api_key = 'API key from the developer console' validator = GooglePlayValidator(bundle_id, api_key)
try: # receipt means
androidDatain result of purchase # signature meanssignatureAndroidin result of purchase validation_result = validator.validate('receipt', 'signature') except InAppPyValidationError: # handle validation error pass
An additional example showing how to authenticate using dict credentials instead of loading from a file
.. code:: python
import json
from inapppy import GooglePlayValidator, InAppPyValidationError
bundle_id = 'com.yourcompany.yourapp'
# Avoid hard-coding credential data in your code. This is just an example.
api_credentials = json.loads('{'
' "type": "service_account",'
' "project_id": "xxxxxxx",'
' "private_key_id": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",'
' "private_key": "-----BEGIN PRIVATE KEY-----\nXXXXXXXXXXXXXXXXXXXXXXXXXXXXX==\n-----END PRIVATE KEY-----\n",'
' "client_email": "XXXXXXXXX@XXXXXXXX.XXX",'
' "client_id": "XXXXXXXXXXXXXXXXXX",'
' "auth_uri": "https://accounts.google.com/o/oauth2/auth",'
' "token_uri": "https://oauth2.googleapis.com/token",'
' "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",'
' "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/XXXXXXXXXXXXXXXXX.iam.gserviceaccount.com"'
' }')
validator = GooglePlayValidator(bundle_id, api_credentials)
try:
# receipt means `androidData` in result of purchase
# signature means `signatureAndroid` in result of purchase
validation_result = validator.validate('receipt', 'signature')
except InAppPyValidationError:
# handle validation error
pass
4. Google Play verification
Setting up Google Service Account Credentials
Before using Google Play verification, you need to set up a Google Service Account and obtain the credentials file. This section explains what GOOGLE_SERVICE_ACCOUNT_KEY_FILE is and how to obtain it.
What is GOOGLE_SERVICE_ACCOUNT_KEY_FILE?
GOOGLE_SERVICE_ACCOUNT_KEY_FILE is a JSON file containing a service account's private key and credentials. This file authorizes your application to access the Google Play Developer API to verify in-app purchases and subscriptions.
The credentials can be provided in two ways:
- As a file path (string): Path to the JSON key file downloaded from Google Cloud Console
- As a dictionary (dict): The parsed JSON content of the key file
How to obtain the Service Account Key File:
-
Link Google Cloud Project to Google Play Console
- Go to
Google Play Console <https://play.google.com/console>_ - Select your app
- Navigate to Settings → Developer account → API access
- If you haven't linked a project yet, click Link to create or link a Google Cloud project
- Accept the terms and conditions
- Go to
-
Create a Service Account
-
In the API access page, scroll to Service accounts
-
Click Create new service account or Learn how to create service accounts (this will take you to Google Cloud Console)
-
In Google Cloud Console:
- Go to IAM & Admin → Service Accounts
- Click + CREATE SERVICE ACCOUNT
- Enter a name (e.g., "InAppPy Validator") and description
- Click CREATE AND CONTINUE
- Skip granting roles (not needed for this step)
- Click DONE
-
-
Grant Permissions in Google Play Console
-
Return to Google Play Console → Settings → Developer account → API access
-
Find your newly created service account in the list
-
Click Grant access
-
Under App permissions, select your app
-
Under Account permissions, enable:
- View financial data (for viewing purchase/subscription info)
- Manage orders and subscriptions (if you need to consume products or manage subscriptions)
-
Click Invite user and then Send invitation
-
-
Download the JSON Key File
- Go back to Google Cloud Console → IAM & Admin → Service Accounts
- Click on your service account email
- Go to the KEYS tab
- Click ADD KEY → Create new key
- Select JSON as the key type
- Click CREATE
- The JSON key file will be automatically downloaded
- IMPORTANT: Store this file securely! It contains a private key and cannot be recovered if lost
-
Important Notes
- The JSON key file should contain fields like:
type,project_id,private_key_id,private_key,client_email, etc. - Keep this file secure and never commit it to version control
- In some cases, you may need to create at least one product in your Google Play Console before the API access works properly
- It may take a few minutes for permissions to propagate after granting access
- The JSON key file should contain fields like:
Example JSON key file structure:
.. code:: json
{
"type": "service_account",
"project_id": "your-project-id",
"private_key_id": "a1b2c3d4e5f6...",
"private_key": "-----BEGIN PRIVATE KEY-----\nYourPrivateKeyHere\n-----END PRIVATE KEY-----\n",
"client_email": "your-service-account@your-project.iam.gserviceaccount.com",
"client_id": "123456789",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/..."
}
Usage Example (with file path)
.. code:: python
from inapppy import GooglePlayVerifier, errors
def google_validator(receipt):
"""
Accepts receipt, validates in Google.
"""
purchase_token = receipt['purchaseToken']
product_sku = receipt['productId']
# Pass the path to your service account JSON key file
verifier = GooglePlayVerifier(
GOOGLE_BUNDLE_ID,
'/path/to/your-service-account-key.json', # Path to the JSON key file
)
response = {'valid': False, 'transactions': []}
try:
result = verifier.verify(
purchase_token,
product_sku,
is_subscription=True
)
response['valid'] = True
response['transactions'].append(
(result['orderId'], product_sku)
)
except errors.GoogleError as exc:
logging.error('Purchase validation failed {}'.format(exc))
return response
Usage Example (with credentials dictionary)
.. code:: python
import json
from inapppy import GooglePlayVerifier, errors
def google_validator(receipt):
"""
Accepts receipt, validates in Google using dict credentials.
"""
purchase_token = receipt['purchaseToken']
product_sku = receipt['productId']
# Load credentials from environment variable or secure storage
# NEVER hard-code credentials in your source code!
credentials_json = os.environ.get('GOOGLE_SERVICE_ACCOUNT_JSON')
credentials_dict = json.loads(credentials_json)
# Pass the credentials as a dictionary
verifier = GooglePlayVerifier(
GOOGLE_BUNDLE_ID,
credentials_dict, # Dictionary containing the JSON key data
)
response = {'valid': False, 'transactions': []}
try:
result = verifier.verify(
purchase_token,
product_sku,
is_subscription=True
)
response['valid'] = True
response['transactions'].append(
(result['orderId'], product_sku)
)
except errors.GoogleError as exc:
logging.error('Purchase validation failed {}'.format(exc))
return response
5. Google Play verification (with result)
Related Skills
node-connect
346.8kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
claude-opus-4-5-migration
107.6kMigrate prompts and code from Claude Sonnet 4.0, Sonnet 4.5, or Opus 4.1 to Opus 4.5
frontend-design
107.6kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
model-usage
346.8kUse CodexBar CLI local cost usage to summarize per-model usage for Codex or Claude, including the current (most recent) model or a full model breakdown. Trigger when asked for model-level usage/cost data from codexbar, or when you need a scriptable per-model summary from codexbar cost JSON.
