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)
Boilerplate template for the discord-py-interactions library

discord-py-interactions_boilerplate Boilerplate template for the discord-py-interactions library Currently, this boilerplate supports discord-py-inter

Ventus 7 Dec 03, 2022
Telegram Music Bot for YouTube/SoundCloud/Mixcloud

Telegram Music Bot Telegram Music Bot for YouTube/SoundCloud/Mixcloud This bot downloads and sends the audio when someone send a YouTube/SoundCloud/Mi

Calls Music 76 Jan 02, 2023
Python wrapper for Gmailnator

Python wrapper for Gmailnator

h0nda 11 Mar 19, 2022
Boto3 code assistance for any API in any IDE, always up to date

botostubs Gives you code assistance for any boto3 API in any IDE. Get started by running pip install botostubs Demo Features PyPI package automaticall

Jeshan Giovanni BABOOA 94 Nov 14, 2022
Change between dark/light mode depending on the ambient light intensity

svart Change between dark/light mode depending on the ambient light intensity Installation Install using pip $ python3 -m pip install --user svart Ins

Siddharth Dushantha 169 Nov 26, 2022
Um painel de consultas completo, com metodos atualizados.

Meu pix para eu comprar um café :D "25ef499b-d184-4aa1-9797-0a294be40d83" Painel-de-Consultas Completo. Feito por JOESTAR-TEAM Painel de consultas Com

Dio brando 10 Nov 19, 2021
Exporta archivos masivamente del TEC Digital.

TEC Digital Files Exporter Script que permite exportar los archivos de cursos del TEC Digital del Instituto Tecnológico de Costa Rica, debido al borra

Joseph Vargas 22 Apr 08, 2021
Unofficial python api for MicroBT Whatsminer ASICs

whatsminer-api Unofficial python api for MicroBT Whatsminer ASICs Code adapted from a python file found in the Whatsminer Telegram group that is credi

Satoshi Anonymoto 16 Dec 23, 2022
A telegram bot to read RSS feeds

Telegram bot to fetch RSS feeds This is a telegram bot that fetches RSS feeds in regular intervals and send it to you. The feed sources can be added o

Santhosh Thottingal 14 Dec 15, 2022
Lib for create and show QRCode to PIX, you can show this code in another applications for payment by final consumer.

Biblioteca para a geração de codigos QR (BRCode como chamados na documentação do BACEN) a fins de facilitar a exibição para pagamentos ao consumidor.

João Camargo 13 Oct 05, 2022
Signs the target email up to over 1000 different mailing lists to get spammed each day.

Email Bomber Say goodbye to that email Features Signs up to over 1k different mailing lists Written in python so the program is lightweight Easy to us

Loxdr 1 Nov 30, 2021
Sadew Jayasekara 23 Oct 21, 2022
An example Music Bot written in Disnake and uses slash commands to operate.

Music Bot An example music bot that is written in Disnake [Maintained discord.py Fork] Disnake Disnake is a maintained and updated fork of discord.py.

6 Jan 08, 2022
Python Client for Instagram API

This project is not actively maintained. Proceed at your own risk! python-instagram A Python 2/3 client for the Instagram REST and Search APIs Install

Facebook Archive 2.9k Dec 30, 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
A Python wrapper around the OpenWeatherMap web API

PyOWM A Python wrapper around OpenWeatherMap web APIs What is it? PyOWM is a client Python wrapper library for OpenWeatherMap (OWM) web APIs. It allow

Claudio Sparpaglione 740 Dec 18, 2022
A new coin listing alert bot using Python, Flask, MongoDB, Telegram API and Binance API

Bzzmans New Coin Listing Detection Bot Architecture About Project Work in progress. This bot basically gets new coin listings from Binance using Binan

Eyüp Barlas 21 May 31, 2022
A chatbot on Telegram using technologies of cloud computing.

Chatbot This project is about a chatbot on Telegram to study the cloud computing. You can refer to the project of chatbot-deploy which is conveinent f

Jeffery 4 Apr 24, 2022
A Fork of Gitlab's Permifrost tool for managing Snowflake Permissions

permifrost-fork This is a fork of the GitLab permifrost project. As the GitLab team is not currently maintaining the project, we've taken on maintenac

Hightouch 7 Oct 13, 2021
A small Python app to create Notion pages from Jira issues

Jira to Notion This little program will capture a Jira issue and create a corresponding Notion subpage. Mac users can fetch the current issue from the

Dr. Kerem Koseoglu 12 Oct 27, 2022