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)
Best Buy Bot used to add products to cart for purchase.

To Install the Best Buy Bot These instructions are for Mac users only. Clone this Repo to your machine. BestBuyBot Open in VScode. Is Python installed

Robert Estrella 1 Dec 11, 2021
A tiktok mass account creator with undetected selenium and email verification, to bot an account

⚠️ STILL UNDER DEVELOPEMENT - v1.1-beta ⚠️ Adding PROXY ROTATION Adding EMAIL VERIFICATION Adding USERNAME COMPILER Tiktok Mass Bot Creator v1.1-beta

xtekky 11 Aug 1, 2022
Monitor robot of Apple Store's products, using DingTalk notification.

概述 本项目应用主要用来监测Apple Store线下直营店货源情况,主要使用Python实现。 首先感谢iPhone-Pickup-Monitor项目带来的灵感,同时有些实现也直接使用了该项目的一些代码。 本项目在iPhone-Pickup-Monitor原有功能的基础上去掉了声音通知,但添加了多

Lennon Chin 159 Dec 9, 2022
Cdk-python-crud-app - CDK Python CRUD App

Welcome to your CDK Python project! You should explore the contents of this proj

Shapon Sheikh 1 Jan 12, 2022
Braje: a python based credit hacker tool. Hack unlimited RAJE LIKER app Credit

#ReCoded Evan Al Mahmud Irfan ✨ ථ BRAJE 1.0 AUTO LIKER, AUTO COMMENT AND AUTO FOLLOWER APP CREDIT HACKER TOOL About Braje: Braje is a python based cre

Evan Al Mahmud Irfan ථ 2 Dec 23, 2021
BaiduPCS API & App 百度网盘客户端

BaiduPCS-Py A BaiduPCS API and An App BaiduPCS-Py 是百度网盘 pcs 的非官方 api 和一个命令行运用程序。

Peter Ding 450 Jan 5, 2023
A website application running in Google app engine, deliver rss news to your kindle. generate mobi using python, multilanguages supported.

Readme of english version refers to Readme_EN.md 简介 这是一个运行在Google App Engine(GAE)上的Kindle个人推送服务应用,生成排版精美的杂志模式mobi/epub格式自动每天推送至您的Kindle或其他邮箱。 此应用目前的主要

null 2.6k Jan 6, 2023
A Python script for rendering glTF files with V-Ray App SDK

V-Ray glTF viewer Overview The V-Ray glTF viewer is a set of Python scripts for the V-Ray App SDK that allow the parsing and rendering of glTF (.gltf

Chaos 24 Dec 5, 2022
Secret messaging app which you can use to communicate with your friends by encrypting / decrypting secret messages or sending secret message through mail.

Secret-Whisper A Secret messaging app which you can use to communicate with your friends by encrypting / decrypting secret messages ?? or sending secr

null 3 Jan 1, 2022
An App to get Ko-Fi payment updates on Telegram.

Deployments. Heroku.com ?? Replit.com ?? Make sure your app runs 24*7 Zeet.co ?? Use this :~ Get Bot token from @botfather ?? Get ID where you want to

Jainam Oswal 16 Nov 12, 2022
A Discord token stealer app written in Python 3.

Discord Token Stealer A Discord token stealer app written in Python 3. This version of the grabber only supports Windows. Features No local caching Tr

cankat 45 Jan 3, 2023
It's a Discord bot to control your PC using your Discord Channel or using Reco: Discord PC Remote Controller App.

Reco PC Server Reco PC Server is a cross platform PC Controller Discord Bot which is a modified and improved version of Chimera for Reco-Discord PC Re

Arvinth Krishna 12 Aug 31, 2022
A Python app to serve Conveyor room requests and run approvals through Slack

✨ CONVEYOR FOR SLACK ✨ This is a friendly little Python app that will allow you to integrate your instance of Conveyor with your Slack workspace. In o

Vivienne 4 Sep 27, 2021
Telegram bot for making Heroku app.json by @AbirHasan2005

Heroku-app.json A Telegram bot for making Heroku app.json by @AbirHasan2005. Demo Bot Host Bot Deploy to Heroku Click Below Button to Deploy to Heroku

Abir Hasan 46 Nov 13, 2022
Written in Python, freezed into stand-alone executable with PyInstaller. This app will make sure you stay in New World without getting kicked for inactivity.

New World - AFK Written in Python, freezed into stand-alone executable with PyInstaller. This app will make sure you stay in New World without getting

Rodney 5 Oct 31, 2021
Django3 web app that renders OpenWeather API data ☁️☁️

nz-weather For a live build, visit - https://brandonru.pythonanywhere.com/ NZ Openweather API data rendered using Django3 and requests ☀️ Local Run In

Brandon Ru 1 Oct 17, 2021
MONAI Deploy App SDK offers a framework and associated tools to design, develop and verify AI-driven applications in the healthcare imaging domain.

MONAI Deploy App SDK offers a framework and associated tools to design, develop and verify AI-driven applications in the healthcare imaging domain.

Project MONAI 49 Dec 23, 2022