Skip to content

Instantly share code, notes, and snippets.

@derrek
Last active November 14, 2024 20:58
Show Gist options
  • Save derrek/763ef95c71491833ae3c1e4acad6785e to your computer and use it in GitHub Desktop.
Save derrek/763ef95c71491833ae3c1e4acad6785e to your computer and use it in GitHub Desktop.
Google Play/Android Receipt Validation/Verification/Lookup with Ruby

This document outlines setting up google's ruby gem, google-api-client, to verify payloads(receipts) sent to a server from google play in app purchases made via an android app.
This document was written using version 0.9.13.

First you'll need 'owner' access to the google play developer's console that contains the mobile app you wish to verify receipts from.

  • Go to https://play.google.com/apps/publish
  • Click on the mobile app you'd like to set up
  • Click "Settings" on the left click "API access"
  • Below "LINKED PROJECT" link the google play account

Next setup an api account

  • Go to http://console.developers.google.com
  • From the left menu select "Credentials"
  • From the center click "Create credentials"
  • From the drop down select "OAuth client ID"
  • From the "Application Type" list select "Web Application"
  • Note your the "client id" and "client secret"

Now manually "login" with your oauth information (this video outlines the steps below https://www.youtube.com/watch?v=hfWe1gPCnzc)

  • go to https://developers.google.com/oauthplayground/
  • Click the "cog" icon on the righ
  • Check "User your own OAuth credentials"
  • Select "Access Type" of "Offline"
  • Enter the client id and client secret created from the previos step
  • Under scopes on the left select "Google Play Developer API v2" and then
  • click "Authorize APIs'
  • click "Allow'
  • click "Exchange authorization code for tokens'
  • note the "refresh token" and "access token"

Add your secrets.yml something similar to below

google_oauth_defaults: &google_oauth_defaults
  google_oauth_client_id: <%= ENV["GOOGLE_OAUTH_CLIENT_ID"] %>
  google_oauth_client_secret: <%= ENV["GOOGLE_OAUTH_CLIENT_SECRET"] %>
  google_oauth_refresh_token: <%= ENV["GOOGLE_OAUTH_REFRESH_TOKEN"] %>
  google_oauth_access_token: <%= ENV["GOOGLE_OAUTH_ACCESS_TOKEN"] %>

production:
  <<: *google_oauth_defaults

This example assumes rails and uses rails application secrets. You can, of course, swap that out to suit your needs.

require 'google/apis/androidpublisher_v2'

class GooglePlayReceiptVerifier
  attr_accessor :receipt_data
  
  def initialize(receipt_data)
    self.receipt_data = receipt_data
  end
  
  def package_name
    receipt_data&.fetch("packageName", nil)
  end

  def product_id
    receipt_data&.fetch("productId", nil)
  end

  def purchase_token
    receipt_data&.fetch("purchaseToken", nil)
  end
  
  def verify
    secrets = Rails.application.secrets
    
    auth_client = Signet::OAuth2::Client.new(
      scope: [Google::Apis::AndroidpublisherV2::AUTH_ANDROIDPUBLISHER],
      authorization_uri: "https://accounts.google.com/o/oauth2/auth",
      token_credential_uri: "https://accounts.google.com/o/oauth2/token",
      client_id: secrets.google_oauth_client_id,
      client_secret: secrets.google_oauth_client_secret,
      refresh_token: secrets.google_oauth_refresh_token,
      access_token: secrets.google_oauth_access_token
    )

    aps = Google::Apis::AndroidpublisherV2::AndroidPublisherService.new
    aps.authorization = auth_client

    is_verified = false

    aps.get_purchase_product(
        package_name,
        product_id,
        purchase_token,  
    ) do |result, err|
      if result
        # this is a bit simplified - you may opt to do something
        # with the result like store it or return it to the caller
        is_verified = true
      end
      if err
        # you may wish to do something with err like return it to the caller or store it
        # err.to_s
      end
    end
    
    return is_verified
  end
end
@gmcnaughton
Copy link

Thanks so much for the walkthrough and the code!

Out of curiosity, when creating oauth credentials, why use "Web Application" as the application type instead of "Service Account"?

@jeremymarc
Copy link

thanks!

@famictech2000
Copy link

How can you tell if its a PROD purchase vs a TEST purchase?

@ritik1576
Copy link

ritik1576 commented Oct 24, 2024

Error verifying purchase: The current user has insufficient permissions to perform the requested operation.

How to fix this issue , i already gave permission from developer account

@derrek
Copy link
Author

derrek commented Oct 25, 2024

Sorry folks but I don't currently work with any software doing Android Receipt validation so I can't really help you out. If you get around the issues you present feel free to comment here your fix.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment