Problem and solution
I think many people know what Freedom is. For those who do not know - this is an Android application that allows you to make in-game purchases in other applications without spending money.
Description:
Are you tired of the offers in games and programs to buy something (extensions, coins, etc.)? Buy them for free with Freedom!
It is very simple to use: install, launch (the first launch can take some time - up to several minutes), tap on the application - it starts. After that, it will probably pass a license check, and when you purchase from the application, you will be able to pay with a fake card.
Link to the author's article:
habrahabr.ru/post/163547Until a certain time, I ignored this regrettable fact, especially since I agree with the author to some extent that those who use this software would hardly have bought something from me in the game. But the new project we are working on should be multiplayer. And this means that cheaters will get a real advantage over ordinary players, which does not make me particularly happy.
Having smoked Google API manuals in the evening, I decided to build my own validation check of purchases. Since we use Unity3D + Prime31 IAP, we had to process them a bit with a file so that they began to issue a purchase token.
For me, the architecture of this case looks like this:
')

Two web servers are needed to separate the logic of a particular game from checking the validity of the purchase, which is common to all games.
The algorithm is as follows:
- Customer makes a purchase and gets a token
- The client makes a request to the web server of his game, passing the token and the type of purchase
- The web server of the game makes a request to the license server
- License server makes request to Google API
- In case of a successful response, the game's web server charges the game currency and sends the result to the client.
Technical part
I will not write about the web server of the game, as this is beyond the scope of this article.
The license server is written in Django. For those who wish to write a bike on their own - at the end of the article there are pieces of code on python.
GitHub source:
github.com/Agasper/django-google-play-check-paymentInstallation
Create a virtual environment, clone a project and install dependencies
virtualenv . git clone https://github.com/Agasper/django-google-play-check-payment.git project source ./bin/activate pip install -r ./project/req.txt
Create an account and generate keys
- Go to console.developers.google.com/project
- Create a new project, for example, "Payment check"
- Go to
Project -> APIS & AUTH -> APIs
and enable Google Play Android Developer API
- Go to
Project -> APIS & AUTH -> Credentials
, click Create new Client ID
and create a new Service Account
- We remember the e-mail, we generate and download the new P12 key
- Rename it to key.p12 and put it in the
keys
directory in the project root - Go to play.google.com/apps/publish
->
- Click
and enter the e-mail service account that you created in step 4-5. - Give this user rights
Check
All that is written below is launched in test mode, if you want to use Django in combat, that is, separate articles on how to set it up. For example, here:
habrahabr.ru/post/226419 ./manage.py runserver 0.0.0.0:8000
Request example:
http://host:8000/license?package=<package_name>&sku=<product_id>&service=<account>&key=<key>&token=<token>
where:
- package - the name of the package for your application, for example: net.solargames.dungeonexplorer2
- product_id - your in-game purchase ID, for example: net.solargames.dungeonexplorer2.gold
- service - the e-mail address of your service account from point 5 above
- key - the name of the file with the key without the extension, in the example was "key"
- token - purchase token, issued by Google when making a purchase on the device
The answer in the case of a successful purchase:
<?xml version="1.0" encoding="UTF-8"?><result consumptionState="1" purchaseState="0" purchaseTime="1405003881937" status="0" />
and if someone slipped the wrong token
<?xml version="1.0" encoding="UTF-8"?><result message="Invalid Value" status="1" />
different status, if successful, it is zero.
Here the insides of the project are dismantled, for those who are interestedGuts
It requires the Google API Python Client to work, for convenience, I statically added it to the project.
Link:
code.google.com/p/google-api-python-client/source/browseAll the magic is contained in one small function:
from oauth2client.client import SignedJwtAssertionCredentials from apiclient.discovery import build credentials = SignedJwtAssertionCredentials( service, key_content, scope='https://www.googleapis.com/auth/androidpublisher') http = httplib2.Http() http = credentials.authorize(http) service = build("androidpublisher", "v1.1", http=http) result = service.inapppurchases().get(packageName=package, productId=sku, token=token).execute(http=http)
Inside the
result
is a dict with the parameters of the purchase. In case of an error, an Exception will occur with a rather poor description of the problem.