Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android verify IAP subscription server side with Ruby

I have been googling and searching and this is killing me. I am just trying to setup our RoR server to be able to query the google play purchases API to validate if a subscription has been renewed and I cannot seem to find an actual solution. I have been through all of the google documentation. It appears I need a service account as described here

https://developers.google.com/accounts/docs/OAuth2ServiceAccount

But then I found this python article on how they actually want us to use the web server application flow

http://milancermak.wordpress.com/2012/08/24/server-side-verification-of-google-play-subsc/

I don't really care at this point, I just need to get the server to successfully talk to the Google API to validate/renew subscriptions. I have found 0 articles on how this flow works. Has anyone gotten this working??

like image 855
echappy Avatar asked Mar 19 '23 11:03

echappy


1 Answers

For anyone who stumbled on this, this was the craziest thing I have ever had to deal with but I managed to figure it out and do it right. I want to thank the following articles for helping me slowly but surely get to the bottom of this. I will add the most frustriating part of this is the steps I am going to list below, I am not 100% convinced they are all necessary because the only error I ever got during this was "403 Insufficient Permissions" so all I can really do here is tell you EVERYTHING I did and hope it works for you.

This article got everything working but was using the web access approach and stating that the service account wouldn't work

http://milancermak.wordpress.com/2012/08/24/server-side-verification-of-google-play-subsc/

This was a great implementation on the above article for Ruby

https://gist.github.com/cornflakesuperstar/5632813

This was a great article on how to get the key so that you could store it as an environment variable for Heroku

http://ar.zu.my/how-to-store-private-key-files-in-heroku/

This was a good article on how to setup the service account (note I am not the account owner of our services so I was flying blind on telling him how to do this. This article worked)

https://developers.google.com/console/help/#activatingapis

This was the article on how you need to authorize the auto generated email from above

How can I authorize with OAuth 2.0 for google's predictive API in Ruby?

The official Google Implementation for the API is here

https://developers.google.com/android-publisher/api-ref/purchases/subscriptions/get

After countless late nights since I posted this article I was able to get this working WITH A SERVICE ACCOUNT with the following steps

  1. I had our developer console admin generate me the service account information as described in the above developer article
  2. I had our admin add the email account and allow it permission as described in the above stack overflow article
  3. I followed the article on how to make the key a string that could be stored as a string

After tons of trial and error, miraculously got a "200" out of the API. Here is my code

ISSUER = '45366745684568-afdasfasdfasdfasdfasdf@developer.gserviceaccount.com'  # From service account
APP_NAME = '<appname>'  # This value didn't seem to matter.  I think it is for logging
APP_VERSION = '1.0'     # This value didn't seem to matter.  I think it is for logging

  class SomeClass < ActiveRecord::Base
   def self.google_api_client
    @@google_client ||= Google::APIClient.new(
      application_name:    APP_NAME,
      application_version: APP_VERSION
    ).tap do |client|

      # Load the key downloaded from the Google Developer Console
      if ENV['GOOGLE_API_KEY'].nil?
        puts "Be sure that you have ENV['GOOGLE_API_KEY'] defined in your environment."
        return
      end
      key = OpenSSL::PKey::RSA.new ENV['GOOGLE_API_KEY'], 'notasecret'

      # Initialize the connection
      client.authorization = Signet::OAuth2::Client.new(
        :token_credential_uri => 'https://accounts.google.com/o/oauth2/token',
        :audience => 'https://accounts.google.com/o/oauth2/token',
        :scope => 'https://www.googleapis.com/auth/androidpublisher',
        :issuer => ISSUER,
        :signing_key => key)
      client.authorization.fetch_access_token!
    end
  end

  def self.test_server(package_name, subscription_id, token)
    # Get the client
    client = self.google_api_client

    # Discover the subscriptions API
    publisher = client.discovered_api('androidpublisher', 'v2')

    # Make the API call
    result = client.execute(
      :api_method => publisher.purchases.subscriptions.get,
      :parameters => {'packageName' => package_name, 'subscriptionId' => subscription_id, 'token' => token}
    )
  end
end

Once I did all of the steps above I was still struggling (same 403 error). I realized the thing that was burning me was the 'scope' was not properly set to 'https://www.googleapis.com/auth/androidpublisher'. I hope this really helps someone. This was tearing me apart and now it works perfect.

Thanks all of the mentioned articles for your help.

like image 120
echappy Avatar answered Apr 03 '23 17:04

echappy