Apple iTunes In-app purchase verification tool

Overview

itunes-iap v2

Python 2 & 3 compatible! Even with :mod:`asyncio` support!

https://travis-ci.org/youknowone/itunes-iap.svg?branch=master https://coveralls.io/repos/github/youknowone/itunes-iap/badge.svg?branch=master

Quickstart

Create request to create a request to itunes verifying api.

>>> import itunesiap
>>> try:
>>>     response = itunesiap.verify(raw_data)  # base64-encoded data
>>> except itunesiap.exc.InvalidReceipt as e:
>>>     print('invalid receipt')
>>> print response.receipt.last_in_app.product_id  # other values are also available as property!
The common attributes are:
product_id, original_transaction_id and quantity.
See the full document in:

asyncio

>>> import itunesiap
>>> response = await itunesiap.aioverify(raw_data)  # verify -> aioverify

The other parts are the same.

See the full document in:

Installation

PyPI is the recommended way.

$ pip install itunes-iap
To browse versions and tarballs, visit:
https://pypi.python.org/pypi/itunes-iap/

Apple in-review mode

In review mode, your actual users who use older versions want to verify in production server but the reviewers in Apple office want to verify in sandbox server.

Note: The default env is production mode which doesn't allow any sandbox verifications.

You can change the verifying mode by specifying env.

>>> # review mode
>>> itunesiap.verify(raw_data, env=itunesiap.env.review)

Note for v1 users

There was breaking changes between v1 and v2 APIs.

  • Specify version 0.6.6 for latest v1 API when you don't need new APIs.
  • Or use import itunesiap.legacy as itunesiap instead of import itunesiap. (from itunesiap import xxx to from itunesiap.legacy import xxx)

Contributors

See https://github.com/youknowone/itunes-iap/graphs/contributors

Comments
  • Support exclude-old-transactions Request parameter

    Support exclude-old-transactions Request parameter

    This adds support for sending the exclude-old-transactions Request parameter to App Store receipt validation.

    Apple Docs https://developer.apple.com/library/content/releasenotes/General/ValidateAppStoreReceipt/Chapters/ValidateRemotely.html

    opened by brandon-clair 9
  • IndexError: pop index out of range

    IndexError: pop index out of range

    I'm getting the following error when trying to validate in sandbox mode:

    Internal Server Error: /api/validate/
    Traceback (most recent call last):
      File "/Users/hanleyhansen/.virtualenvs/mkl/lib/python2.7/site-packages/django/core/handlers/base.py", line 149, in get_response
        response = self.process_exception_by_middleware(e, request)
      File "/Users/hanleyhansen/.virtualenvs/mkl/lib/python2.7/site-packages/django/core/handlers/base.py", line 147, in get_response
        response = wrapped_callback(request, *callback_args, **callback_kwargs)
      File "/Users/hanleyhansen/.virtualenvs/mkl/lib/python2.7/site-packages/django/views/decorators/csrf.py", line 58, in wrapped_view
        return view_func(*args, **kwargs)
      File "/Users/hanleyhansen/Google Drive/Work/Projects/git/mkl-web/mkl/views/api_views.py", line 99, in validate
        response = itunesiap.verify(receipt_data, IAP_SHARED_SECRET)
      File "/Users/hanleyhansen/.virtualenvs/mkl/lib/python2.7/site-packages/itunesiap/environment.py", line 39, in __exit__
        self._stack.pop(self._ctx_id)
    IndexError: pop index out of range
    

    Any ideas?

    Here is my code:

        try:
            if IAP_SANDBOX:
                with itunesiap.env.sandbox:
                    response = itunesiap.verify(receipt_data, IAP_SHARED_SECRET)
            else:
                with itunesiap.env.default:
                    response = itunesiap.verify(receipt_data, IAP_SHARED_SECRET)
        except itunesiap.exc.InvalidReceipt as e:
            return HttpResponseForbidden({'message': 'not valid', 'error': e}, content_type='application/json')
    
    opened by hanleyhansen 8
  • Why can't get latest_receipt_info

    Why can't get latest_receipt_info

    Following the Official Document: https://developer.apple.com/library/content/releasenotes/General/ValidateAppStoreReceipt/Chapters/ReceiptFields.html#//apple_ref/doc/uid/TP40010573-CH106-SW1

    There should be a latest_receipt_info data in response, but we can't directly get this attribute from the response

    opened by vincentwyshan 7
  • Allow providing an override env in Request.verify

    Allow providing an override env in Request.verify

    Enable specifying an explicit override environment "env" in the Request.verify() and call in order to avoid a pop from the environment stack. This makes cases with thread concurrency deterministic and avoids the Environment.current() stack access.

    Example:

    import itunesiap
    response = itunesiap.verify(receipt, apple_shared_secret, env=itunesiap.env.production)
    
    opened by mmeisinger 7
  • Proposed bugfix for calling response.receipt.in_app resulting in an error

    Proposed bugfix for calling response.receipt.in_app resulting in an error

    This pull request provides a proposed solution for calling response.receipt.in_app in the new receipt format. It also produces a uniform return type for python2 and python3

    opened by dlm 6
  • Installation of 2.5.0 fails on python2

    Installation of 2.5.0 fails on python2

    After the update to 2.5.0 itunes-iap cannot be upgraded anymore on python versions <3.4.2. pip2 install --upgrade itunes-iap tries to install aiohttp, which fails:

    [...]
    Collecting aiohttp (from itunes-iap)
      1 location(s) to search for versions of aiohttp:
      * https://pypi.python.org/simple/aiohttp/
      Getting page https://pypi.python.org/simple/aiohttp/
      Looking up "https://pypi.python.org/simple/aiohttp/" in the cache
      Current age based on date: 311
      Freshness lifetime from max-age: 600
      Freshness lifetime from request max-age: 600
      The response is "fresh", returning cached response
      600 > 311
      Analyzing links from page https://pypi.python.org/simple/aiohttp/
      [...]
      Using version 2.2.3 (newest of versions: 0.1, 0.2, 0.3, 0.4, 0.4.1, 0.4.2, 0.4.3, 0.4.4, 0.5.0, 0.6.0, 0.6.1, 0.6.2, 0.6.3, 0.6.4, 0.6.5,$
      Looking up "https://pypi.python.org/packages/9b/3a/b560a411b97203fb20b5eee084c1e292862b3092029d9d9faaa8714797fa/aiohttp-2.2.3.tar.gz" in $
      Current age based on date: 108202
      Freshness lifetime from max-age: 31557600
      The response is "fresh", returning cached response
      31557600 > 108202
      Using cached aiohttp-2.2.3.tar.gz
      Downloading from URL https://pypi.python.org/packages/9b/3a/b560a411b97203fb20b5eee084c1e292862b3092029d9d9faaa8714797fa/aiohttp-2.2.3.ta$
      Running setup.py (path:/tmp/pip-build-DwBsrd/aiohttp/setup.py) egg_info for package aiohttp
        Running command python setup.py egg_info
        Traceback (most recent call last):
          File "<string>", line 1, in <module>
          File "/tmp/pip-build-DwBsrd/aiohttp/setup.py", line 66, in <module>
            raise RuntimeError("aiohttp requires Python 3.4.2+")
        RuntimeError: aiohttp requires Python 3.4.2+
    Cleaning up...
    Exception information:
    Traceback (most recent call last):
      File "/home/prettyvanilla/.local/share/virtualenvs/bikemap/lib/python2.7/site-packages/pip/basecommand.py", line 215, in main
        status = self.run(options, args)
      File "/home/prettyvanilla/.local/share/virtualenvs/bikemap/lib/python2.7/site-packages/pip/commands/install.py", line 335, in run
        wb.build(autobuilding=True)
      File "/home/prettyvanilla/.local/share/virtualenvs/bikemap/lib/python2.7/site-packages/pip/wheel.py", line 749, in build
        self.requirement_set.prepare_files(self.finder)
      File "/home/prettyvanilla/.local/share/virtualenvs/bikemap/lib/python2.7/site-packages/pip/req/req_set.py", line 380, in prepare_files
        ignore_dependencies=self.ignore_dependencies))
      File "/home/prettyvanilla/.local/share/virtualenvs/bikemap/lib/python2.7/site-packages/pip/req/req_set.py", line 634, in _prepare_file
        abstract_dist.prep_for_dist()
      File "/home/prettyvanilla/.local/share/virtualenvs/bikemap/lib/python2.7/site-packages/pip/req/req_set.py", line 129, in prep_for_dist
        self.req_to_install.run_egg_info()
      File "/home/prettyvanilla/.local/share/virtualenvs/bikemap/lib/python2.7/site-packages/pip/req/req_install.py", line 439, in run_egg_info
        command_desc='python setup.py egg_info')
      File "/home/prettyvanilla/.local/share/virtualenvs/bikemap/lib/python2.7/site-packages/pip/utils/__init__.py", line 707, in call_subproce$
        % (command_desc, proc.returncode, cwd))
    InstallationError: Command "python setup.py egg_info" failed with error code 1 in /tmp/pip-build-DwBsrd/aiohttp/
    

    Most likely the conditional in setup.py isn't working the way you'd expect when using wheels, instead environment markers seem to be the recommended way now: https://wheel.readthedocs.io/en/latest/#defining-conditional-dependencies

    opened by prettyv 5
  • Failback to sandbox only on specific status

    Failback to sandbox only on specific status

    According to iTunes documentation, their production API will return specific status in case when we are sending transaction raw data from their sandbox's environment: https://developer.apple.com/library/ios/technotes/tn2413/_index.html#//apple_ref/doc/uid/DTS40016228-CH1-RECEIPTURL

    Hence, we do not need to send any other failed transactions (those which returned status other than 21007) to sandbox in case when both production and sandbox environments are used.

    Note: while testing on my machine (excluding py2.6, 3.3 and pypi) I got FAIL for py27 in test_receipt, line assert isinstance(in_app0.original_purchase_date_ms, int) - 1432002585000L is not an int (if applicable, I'm using 32bit OS).

    opened by kmitrovic 5
  • On python 3.4 asyncio.coroutines will traceback with AttributeError …

    On python 3.4 asyncio.coroutines will traceback with AttributeError …

    …so use the alternative requests.

    Traceback (most recent call last): File "/home/silver/.local/share/virtualenvs/silver/lib/python3.4/site-packages/my_project/iap.py", line 6, in import itunesiap File "/home/silver/.local/share/virtualenvs/silver/lib/python3.4/site-packages/itunesiap/init.py", line 13, in from .request import Request File "/home/silver/.local/share/virtualenvs/silver/lib/python3.4/site-packages/itunesiap/request.py", line 6, in from itunesiap.verify_aiohttp import AiohttpVerify File "/home/silver/.local/share/virtualenvs/silver/lib/python3.4/site-packages/itunesiap/verify_aiohttp.py", line 3, in import aiohttp File "/home/silver/.local/share/virtualenvs/silver/lib/python3.4/site-packages/aiohttp/init.py", line 6, in from .client import * # noqa File "/home/silver/.local/share/virtualenvs/silver/lib/python3.4/site-packages/aiohttp/client.py", line 15, in from . import connector as connector_mod File "/home/silver/.local/share/virtualenvs/silver/lib/python3.4/site-packages/aiohttp/connector.py", line 13, in from . import hdrs, helpers File "/home/silver/.local/share/virtualenvs/silver/lib/python3.4/site-packages/aiohttp/helpers.py", line 142, in coroutines = asyncio.coroutines AttributeError: 'module' object has no attribute 'coroutines'

    opened by MihaiBalint 4
  • receipt.last_in_app is not the latest purchase

    receipt.last_in_app is not the latest purchase

    I'm not sure if this issue is an Apple problem or my my incorrect interpretation of how the receipt validation process works or a shortcoming of itunes-iap.

    If I send a receipt to get validated and get back a response and then do a response.receipt.last_in_app I get the last purchase in the in_app array contained in the receipt. The problem is that this is not the latest purchase if the receipt hasn't been refreshed on the device. Since I'm handling subscriptions I will be periodically checking the receipt from the server and do not have the ability to refresh the receipt (at least I don't think I can).

    The latest purchase information is however contained in 'latest_receipt_info' of the receipt and Pablo Rivera pointed out how to obtain this in his wiki post https://github.com/youknowone/itunes-iap/wiki/Getting-the-receipt-with-the-latest-expiration-date by doing response._.get('latest_receipt_info') you can get access to this information. However this is just the raw dictionary of the data and then I need to parse it manually which is all nicely done for the in_app part by itunes-iap.

    So my question is, when validating a receipt, is there a way to always get the last purchase history in the in_app part or if not, could itunes-iap be changed in a way to more natively access 'last_receipt_info'? I've already worked around this but I'd like to know if I'm doing something wrong or there is an easier way to do this.

    opened by jeffjvick 4
  • Proposal for encapsulating requests errors and provide user option for verifing ssl certs

    Proposal for encapsulating requests errors and provide user option for verifing ssl certs

    The original goal was to all the user to specify an option for verifying ssl certs. (relevant to issue #16)

    In the process, I ended up encapsulating the requests errors within itunes-iap.

    opened by dlm 4
  • Example doesn't work as InvalidReceipt is not imported in itunesiap/__init__.py

    Example doesn't work as InvalidReceipt is not imported in itunesiap/__init__.py

    As the title pretty much.

    The line in question is incorrect in the current state:

    >>> from itunesiap import Request, InvalidReceipt
    

    Happy to make a pull request but I'm not sure whether you:

    a) want to import that exception in the __init__.py b) change the example to import from the correct location (exceptions.py).

    Let me know, happy to do so.

    opened by djm 4
  • Aioverify error

    Aioverify error

    response = await itunesiap.aioverify(receipt, env=itunesiap.env.review, password="xxx")

                   ^
    SyntaxError: 'await' outside function
    

    How can I solve this error?

    opened by xiaohange 0
  • recruiting maintainer

    recruiting maintainer

    Hello,

    I didn't develop iOS app with in-app purchase for very long time. I maintained this project depends on patches for a few more years, but it seems not very responsible.

    Anyone who interested in this project contact me please.

    Thanks

    opened by youknowone 0
  • Error install with python version 3.5.2

    Error install with python version 3.5.2

    Getting this dependency error, going to do a manual workaround for now but thought I would let you know

    Could not find a version that satisfies the requirement aiohttp>=3.0.1 (from itunes-iap) (from versions: 0.1, 0.2, 0.3, 0.4, 0.4.1, 0.4.2, 0.4.3, 0.4.4, 0.5.0, 0.6.0, 0.6.1, 0.6.2, 0.6.3, 0.6.4, 0.6.5, 0.7.0, 0.7.1, 0.7.2, 0.7.3, 0.8.0, 0.8.1, 0.8.2, 0.8.3, 0.8.4, 0.9.0, 0.9.1, 0.9.2, 0.9.3, 0.10.0, 0.10.1, 0.10.2, 0.11.0, 0.12.0, 0.13.0, 0.13.1, 0.14.0, 0.14.1, 0.14.2, 0.14.3, 0.14.4, 0.15.0, 0.15.1, 0.15.2, 0.15.3, 0.16.0, 0.16.1, 0.16.2, 0.16.3, 0.16.4, 0.16.5, 0.16.6, 0.17.0, 0.17.1, 0.17.2, 0.17.3, 0.17.4, 0.18.0, 0.18.1, 0.18.2, 0.18.3, 0.18.4, 0.19.0, 0.20.0, 0.20.1, 0.20.2, 0.21.0, 0.21.1, 0.21.2, 0.21.4, 0.21.5, 0.21.6, 0.22.0a0, 0.22.0b0, 0.22.0b1, 0.22.0b2, 0.22.0b3, 0.22.0b4, 0.22.0b5, 0.22.0b6, 0.22.0, 0.22.1, 0.22.2, 0.22.3, 0.22.4, 0.22.5, 1.0.0, 1.0.1, 1.0.2, 1.0.3, 1.0.5, 1.1.0, 1.1.1, 1.1.2, 1.1.3, 1.1.4, 1.1.5, 1.1.6, 1.2.0, 1.3.0, 1.3.1, 1.3.2, 1.3.3, 1.3.4, 1.3.5, 2.0.0rc1, 2.0.0, 2.0.1, 2.0.2, 2.0.3, 2.0.4, 2.0.5, 2.0.6, 2.0.6.post1, 2.0.7, 2.1.0, 2.2.0, 2.2.1, 2.2.2, 2.2.3, 2.2.4, 2.2.5, 2.3.0a1, 2.3.0a2, 2.3.0a4, 2.3.0, 2.3.1a1, 2.3.1, 2.3.2b2, 2.3.2b3, 2.3.2, 2.3.3, 2.3.4, 2.3.5, 2.3.6, 2.3.7, 2.3.8, 2.3.9, 2.3.10, 3.0.0b0) No matching distribution found for aiohttp>=3.0.1 (from itunes-iap)

    opened by wdifruscio 1
  • IndexError when exiting context manager

    IndexError when exiting context manager

    I'm experiencing a similar IndexError in one of my api views when using itunesiap.env.sandbox context manager:

    # ...
    if sandbox:
        with itunesiap.env.sandbox:
            try:
                response = itunesiap.verify(raw_data, use_sandbox=True)
                return True, response
            except (ItunesServerNotAvailable, ItunesServerNotReachable):
                no_response = True
            except itunesiap.exc.InvalidReceipt as exc:
                error = exc.description
    

    Sentry actually indicates the error/exception being raised when exiting the contextmanager:

    itunesiap/environment.py in __exit__ at line 42
            self._ctx_id = len(self._stack)
            self.push()
            return self
        def __exit__(self, exc_type, exc_value, tb):
            self._stack.pop(self._ctx_id)  # this line
    

    Any clues on what might be happening?

    opened by maccinza 1
  • IndexError: list index out of range

    IndexError: list index out of range

    Hello. We got this problem with itunes-iap 2.5

    [2017-11-08 15:00:20,934] [ERROR] views.py:3308 - root: list index out of range
    Traceback (most recent call last):
      File "/home/django/atcontrol/releases/1510061996/mayak/api_v3/views.py", line 3243, in purchase_ios
        log.info(res.receipt.last_in_app)
      File "/home/django/atcontrol/releases/1510061996/venv/local/lib/python2.7/site-packages/itunesiap/receipt.py", line 245, in last_in_app	
        self.in_app, key=lambda x: x['original_purchase_date_ms'])[-1]
    IndexError: list index out of range
    

    part of view from our django rest framework api with problem line of code

    @api_view(['POST'])
    def purchase_ios(request):
        log.info('purchase_ios (%s) POST: %s' % (request.user, request.POST))
        try:
            res = itunesiap.verify(request.POST.get("receipt", None), settings.ITUNES_PASSWORD, verify_ssl=False,
                                   use_production=True, use_sandbox=True)
            log.info(res.receipt.last_in_app)
    ...
    

    Any ideas what's wrong?

    opened by aaksarin 7
Releases(2.5.0)
Skyscanner Python SDK

Skyscanner Python SDK Important As of May 1st, 2020, the project is deprecated and no longer maintained. The latest update in v1.1.5 includes changing

Skyscanner 118 Sep 23, 2022
This Bot Can Upload Video from Link Of Pdisk to Pdisk using its API. @PredatorHackerzZ

𝐏𝐝𝐢𝐬𝐤 𝐂𝐨𝐧𝐯𝐞𝐫𝐭𝐞𝐫 𝐁𝐨𝐭 Make short link by using 𝐏𝐝𝐢𝐬𝐤 API key Installation 𝐓𝐡𝐞 𝐄𝐚𝐬𝐲 𝐖𝐚𝐲 𝐑𝐞𝐪𝐮𝐢𝐫𝐞𝐝 𝐕𝐚𝐫𝐢𝐚𝐛𝐥𝐞

ρяє∂αтσя 25 Dec 02, 2022
This is a simple Python bot to identify sentiments in tweets

Twitter-Sentiment 👋 Hi There! 📱 This is a simple Python bot to identify sentiments in tweets 👨‍💻 This project was made for study, and pratice. You

Guilherme Silva 1 Oct 28, 2021
Telegram Auto Filter Bot

Pro Auto Filter Bot V2.o Hey Mo Tech, I'm an Autofilter bot v2.O and you can not Add Me to your Group. I was made for this one group. So don't waste y

14 Oct 20, 2021
🌶️ Give real chat boosting to your discord server.

Chat-Booster Give real chat boosting to your discord server. ✅ Setup: - Add token to scrape messages on server that you whant. - Put the token in

&! Ѵιchy.#0110 36 Nov 04, 2022
Financial portfolio optimisation in python, including classical efficient frontier, Black-Litterman, Hierarchical Risk Parity

PyPortfolioOpt has recently been published in the Journal of Open Source Software 🎉 PyPortfolioOpt is a library that implements portfolio optimizatio

Robert Martin 3.2k Jan 02, 2023
A simple terminal UI for viewing fund P/L analysis through TEFAS

Tefas UI A simple terminal UI for viewing fund P/L analysis through TEFAS. Features (that my own bank's UI lack): Daily and weekly P/L FX comparisons

Batuhan Taskaya 4 Mar 14, 2022
This is new discord nitro generator for discord

Hello! This is new discord nitro generator for discord. If you want use it, To generator i added checker for no seraching generator and checker. This tool maked by .

ItzBolt 1 Jan 16, 2022
Fully undetected auto skillcheck hack for dead by daylight that works decently well

Auto-skillcheck was made by Love ❌ code ✅ ❔ ・How to use Start off by installing python ofc Open cmd in the same directory and type pip install -r requ

Rdimo 10 Aug 13, 2022
A frame to create discord bots (for myself) that uses cogs, JSON, activities, and more.

dpy-frame A frame to create discord bots (for myself) that uses cogs, JSON, activities, and more. NOTE: Documentation is incomplete, so please wait un

Apple Discord 1 Nov 06, 2021
A Discord API Wrapper for Userbots/Selfbots written in Python.

DisCum A simple, easy to use, non-restrictive, synchronous Discord API Wrapper for Selfbots/Userbots written in Python. -using requests and websockets

Liam 450 Dec 27, 2022
Telegram Bot Repo Capable of fetching the following Info via Anilist API inspired from AniFluid and Nepgear

Telegram Bot Repo Capable of fetching the following Info via Anilist API inspired from AniFluid and Nepgear Anime Airing Manga Character Scheduled Top

Rikka-Chan 2 Apr 01, 2022
🐍 The official Python client library for Google's discovery based APIs.

Google API Client This is the Python client library for Google's discovery based APIs. To get started, please see the docs folder. These client librar

Google APIs 6.2k Jan 08, 2023
BingBot - A bot that will automate searches on bing

bingBot A bot that will automate searches on bing. To install this just download

Lukas 2 Jul 28, 2022
A very simple Salesforce.com REST API client for Python

Simple Salesforce Simple Salesforce is a basic Salesforce.com REST API client built for Python 3.5, 3.6, 3.7 and 3.8. The goal is to provide a very lo

simple salesforce 1.4k Dec 29, 2022
Bitcoin tracker hecho con python.

Bitcoin Tracker Precio del Bitcoin en tiempo real. Script simple hecho con python. Rollercoin RollerCoin es un juego en el que puedes ganar bitcoin (y

biyivi 3 Jan 04, 2022
Python Script to download hundreds of images from 'Google Images'. It is a ready-to-run code!

Google Images Download Python Script for 'searching' and 'downloading' hundreds of Google images to the local hard disk! Documentation Documentation H

Hardik Vasa 8.2k Jan 05, 2023
A Python interface to AFL, allowing for easy injection of testcases and other functionality.

Fuzzer This module provides a Python wrapper for interacting with AFL (American Fuzzy Lop: http://lcamtuf.coredump.cx/afl/). It supports starting an A

Shellphish 614 Dec 26, 2022
This project is a basic login system in terminal for Discord

Welcome to Discord Login System(Terminal) 👋 This project is a basic login system in terminal for Discord Author 👤 arukovic Github: @SONIC-CODEZ Show

SONIC-CODEZ 2 Feb 11, 2022
Unofficial Python wrapper for official Hacker News API

haxor Unofficial Python wrapper for official Hacker News API. Installation pip install haxor Usage Import and initialization: from hackernews import H

147 Sep 18, 2022