Google Play Android Developer API 

How to authenticate 

Marc Greenstock
mbaasy

--

Recently I worked on an API that provides support for an Android app that has in-app purchases, and I needed a way to validate these purchases. Google provides an API for purchase validation but there are a few details Google assumes you know already when using it.

Ensure you have the right permissions

Firstly you will want access to the Google Play Console. If you are the owner you can skip this part. Otherwise, make sure you have access to financial information, the owner is the only user who can set this for you. Without this set you will receive a 403 forbidden when making your requests.

Next, log into your Google Developers Console, and create a project. In the API & AUTH > APIs section, switch on Google Play Android Developer API.

Next in the API & AUTH > Consent Screen select an Email Address and enter a Project Name. Unless you are using google OAuth in your app or elsewhere for this project then your users will never see this so put what ever you like, and the rest of the details don’t matter.

Now go to API & AUTH > Credentials and create a new OAuth Client ID. Select Web Application (I know you’re not making a web application but for some reason Google thinks this was a good idea), enter http://localhost in Authorized JavaScript Origins and http://localhost/oauth_callback in Authorized Redirect URI. This end point doesn’t matter too much, it’s only somewhere Google can redirect back to when setting up your credentials.

Now you have this set up you can start pre-authenticating.

Pre-authentication

https://accounts.google.com/o/oauth2/auth?scope=https://www.googleapis.com/auth/androidpublisher&response_type=code&access_type=offline&redirect_uri=http://localhost/oauth_callback&client_id=YOUR_CLIENT_ID

Copy and paste the above URI in your browser replacing YOUR_CLIENT_ID with the Client ID you got in the last step.

You will be taken to an authentication screen asking you if you allow your Project to have access to Google Play Android Developer, say yes. You’ll then be redirected to http://localhost/oauth_callback?code=authorization_code. You will probably get some kind of error, 404 or whatever, but that doesn’t matter, the important part is the authorization_code in the query string. This is necessary to complete the next step.

Here you will swap the authorization_code for a google_refresh_token.

code = "authorization_code"
client_id = "client_id"
client_secret = "client_secret"
redirect_uri = "http://localhost/oauth_callback"
response = HTTParty.post('https://accounts.google.com/o/oauth2/token', {
body: {
grant_type: 'authorization_code',
code: code,
client_id: client_id,
client_secret: client_secret,
redirect_uri: redirect_uri
}
})
JSON.parse(response.body)

The code above is written in Ruby, but it’s a simple HTTP Post request, you can use any language or library or even a REST client like Postman for Chrome. The first 4 lines in the code above will need to be changed to your respective values.

In your response you should get a refresh_token, if you don’t then it is because you have used the authorization_code already and you will need to go to your Google Account Permissions page, revoke access to your project, and repeat the Pre-authentication process.

If you have your refresh_token you’re ready to proceed to the next step.

Getting an access_token

Okay still with me? Good, we’re nearly there.

Now that you have your refresh_token you can now get your access_token and keep it fresh. access_token’s expire after a while so you’ll need to use your refresh_token to get a new one after it expires and I doubt you’ll want to do this manually.

client_id = "client_id"
client_secret = "client_secret"
refresh_token = "refresh_token"
response = HTTParty.post('https://accounts.google.com/o/oauth2/token', {
body: {
grant_type: 'refresh_token',
client_id: client_id,
client_secret: client_secret,
refresh_token: refresh_token
}
})

The code above, while similar to the last snippet will exchange your refresh_token for an access_token and an expires_in integer. You may want to store your access_token in a key value store that can expire, e.g. Redis.

if response.message == ‘OK’ && 
(json = JSON.parse(response.body))
redis.set(‘access_token’, json[‘access_token’])
redis.expireat(‘access_token’, Time.now.to_i + json[‘expires_in’])
access_token = json[‘access_token’]
else
raise "Oh my god there is no access token"
end

The above code is a continuation, taking response, parsing it then storing the access_token in Redis and setting an expiry based on expires_in and the current time. You’ll want to put this in a setter method so that you can set the access token when it doesn’t exist in Redis and a getter method that will retrieve the access token when it does exist.

Now you should have a nice way of refreshing your access_token, you can move on to actually validating purchases.

Validating Purchases

Yeah I lied when I said we were nearly there, but this time I promise.

Google Play has two kinds of in-app purchases; purchases and inapppurchases. The former is subscriptions (I do not know why they just didn’t call them subscriptions) and the latter is single purchases. Anyway, now you have the access_token token all you need to do is your requests to validate with your access_token as a query param, e.g.

https://www.googleapis.com/androidpublisher/v1.1/applications/PACKAGE_NAME/subscriptions/SUBSCRIPTION_ID/purchases/TOKEN?access_token=ACCESS_TOKEN

Of course you will need a PACKAGE_NAME, SUBSCRIPTION_ID and a TOKEN and there is no way to actually get a TOKEN unless you actually pay money for a TOKEN through the app you are developing.

Troubleshooting

If you get a 403 forbidden, it is most probably because your Google Play Console account doesn’t have access to financial information. Have your account owner turn this on for you.

If you get a 401 unauthorized, then it is because you missed a step above, go back and try again.

So this was my first post on Medium, and on this subject, if you notice any errors please let me know. I hope this helps you figuring out how this whole authentication mess works.

--

--