I am using google wallet for my payment gateway, after purchasing the product google giving me a below response that
{
"orderId":"12999763169054705758.1371079406387615",
"packageName":"com.example.app",
"productId":"exampleSku",
"purchaseTime":1345678900000,
"purchaseState":0,
"developerPayload":"bGoa+V7g/yqDXvKRqq+JTFn4uQZbPiQJo4pf9RzJ",
"purchaseToken":"rojeslcdyyiapnqcynkjyyjh"
}
I am trying to make use of Receipt Validation that google play newly introduced.In Google Developer console I made certificate key by Service Account in the Permission. But I am confused how to make use of Receipt Validation after purchasing a Product from the Google Play-store.
So can anyone please help me how to do the Receipt validation of InApp Purchase.
Google provides receipt validation through the Google Play Developer API, within the API are two endpoints you will be most interested in: Purchases.products: get and Purchases.subscriptions: get.
Purchases.products: get can be used to verify a non-auto-renewing product purchase, where Purchases.subscriptions: get is for verifying and re-verifying auto-renewing product subscriptions.
To use either endpoint you must know the packageName, productId, purchaseToken all of these can be found in the payload you received on purchase. You also need an access_token which you can get by creating a Google API service account.
To get started with a service account first go to the Google play Developer console API access settings page and click the Create new project button:
You should now see a new Linked Project and a few new sections, in the the Service Account section, click the Create service account button.
You will be presented with an info box with instructions to create your service account. Click the link to Google Developers Console and a new tab will spawn.
Now click Create new Client ID, select Service account from the options and click Create Client ID.
A JSON file will download, this is your JSON Web Token you will use to exchange for an access_token so keep it safe.
Next, switch tabs back to the Google play Developer console and click Done in the info box. You should see your new service account in the list. Click on Grant access next to the service account email.
Next under the Choose a role for this user, select Finance and click Add user.
You have now set up your service account and it has all the necessary access to perform receipt validations. Next up is exchanging your JWT for an access_token.
The access_token expires after one hour of exchange you so need some server code to handle this and Google have provided several libraries in many languages to handle this (list not exhaustive):
Ruby: https://github.com/google/google-api-ruby-client
Node.js: https://github.com/google/google-api-nodejs-client
Java: https://github.com/google/google-api-java-client
Python: https://github.com/google/google-api-python-client
C#: https://github.com/googleapis/google-api-dotnet-client
I won't go into detail because there is plenty of documentation on how to use these libraries, but I will mention you want to use the https://www.googleapis.com/auth/androidpublisher as the OAuth2 scope, the client_email from the JWT as the issuer and the public key you can get from the private_key and the passphrase notasecret will be used for the signing_key.
Once you have the access_token you're good to go (at least for the next hour at which point you will want to request a new one following the same process in the above paragraph).
To check the status of a consumable (non-auto-renewing) purchase make a http get request to: https://www.googleapis.com/androidpublisher/v2/applications/com.example.app/purchases/products/exampleSku/tokens/rojeslcdyyiapnqcynkjyyjh?access_token=your_access_token
If you get a 200 http response code, everything went as planed and your purchase was valid. A 404 will mean your token is invalid so the purchase was most likely a fraud attempt. A 401 will mean your access token is invalid and a 403 will mean your service account has insufficient access, check that you have enabled Finance for the access account in the Google Play Developer console.
The response from a 200 will look similar to this:
{
"kind": "androidpublisher#productPurchase",
"purchaseTimeMillis": long,
"purchaseState": integer,
"consumptionState": integer,
"developerPayload": string
}
For an explanation of each property see https://developers.google.com/android-publisher/api-ref/purchases/products.
Subscriptions are similar however the endpoint looks like this:
https://www.googleapis.com/androidpublisher/v2/applications/packageName/purchases/subscriptions/subscriptionId/tokens/token?access_token=you_access_token
And the response should contain these properties:
{
"kind": "androidpublisher#subscriptionPurchase",
"startTimeMillis": long,
"expiryTimeMillis": long,
"autoRenewing": boolean
}
See https://developers.google.com/android-publisher/api-ref/purchases/subscriptions for the property descriptions and note that startTimeMillis and expiryTimeMillis will be subject to change depending on the duration of the subscription.
Happy validating!
Marc's answer is excellent. I will only add that the Google Play Developer API Client Library for Java makes it much simpler when connecting from your server to the Google Play servers.
The library automatically handles refreshing the auth token and also provides a typesafe API so you don't have to muck around with URLs.
Here's how you setup the Publisher singleton:
httpTransport = GoogleNetHttpTransport.newTrustedTransport();
jsonFactory = JacksonFactory.getDefaultInstance();
credential = GoogleCredential.fromStream(getClass().getResourceAsStream("/path/to/your/key.json")).createScoped(Collections.singleton(AndroidPublisherScopes.ANDROIDPUBLISHER));
publisher = new AndroidPublisher.Builder(httpTransport, jsonFactory, credential).setApplicationName(APP_NAME).build();
The following code queries a product purchase:
ProductPurchase product = publisher.purchases().products().get(PACKAGE_NAME, sku, token).execute();
Integer purchaseState = product.getPurchaseState();
product.getPurchaseTimeMillis();
product.getConsumptionState();
product.getDeveloperPayload();
You can similarly query for subscriptions:
SubscriptionPurchase sub = publisher.purchases().subscriptions().get(PACKAGE_NAME, sku, token).execute();
sub.getAutoRenewing();
sub.getCancelReason();
...
I faced a similar issue, the problem is in the settings we do in google developer project.
Refer to create-play-service-credentials for settings. Use the same primary account with which you created your in-app products.
Make sure you remove the previous one.
Link to a Google Developer Project
Your Play Developer account needs to be linked to a Google Developer Project.
1a. Open the Settings > Developer account menus and select API access
1b. Select Link to connect your Play account to a Google Developer Project
1c. Agree to the terms and conditions
2. Create Service Account
Next we need to create a service account. This is done from the Google API Console.
2a. Select Create Service Account
2b. Create Service account key credentials
2c. Enter details for service account - There is an "optional" step for granting role access. Make sure you grant access to the current user role.
2d. Download your JSON credential:
3. Grant Access
3a. In Play Console, select Grant Access on the newly created service account
3b. Grant the following permissions:
After this wait for 48 hours to allow Google to propagate all access rights for APIs.
#marc-greenstock provided a great answer, however, there is a very important thing about receipt validation using Google Play Android Developer API.
If you have any problems with using this API and you added your in-app product BEFORE granting permission or linking to your service account, you need to open "In-app products" and perform some update. You can for example edit description of your product and save. You should instantly get permission.
I spent a few hours thinking what did I do wrong...
This answer is excellent. One more issue we ran into while following the direction was that the service account didn't show up in the Google Play Console. We ended up finding this solution to help: Service account doesn't show up in Google Console after creation
Basically, go to IAM on Google API Console and add the new service account, then it will show up on Google Play Console.
screenshot
Related
I'm trying to implement leaderboards in my Android game using Google Play Games Services.
I think I understand how to submit a score and access a leaderboard from a client which is signed in to Play Games, however I would also like to be able to access the leaderboard from my server. This way, I can show the leaderboard to users which are not yet signed in to Play Games or even show it on Discord with my bot.
But I can't figure out how to do that.
Whenever I try to find information on the Internet about server-side access to Play Games, I only find how to get a one-time usage token from a client to then call Play Games from the server on behalf of the user (as I understand it).
But that's not what I want to do! I need to be able to access the leaderboard from my server as an admin (or as myself or as a service account or anything like that), not on behalf of a user. And I want to be able to do that at any time, not only when a client sends an access token...
Is this possible?
Thank you in advance for any help on this matter!
I created a new credential for a web server and then, using my Oauth consent screen, I managed to give myself a refresh token for my own Google account.
This way I can get access tokens whenever I want from my server and access the Play Games REST API with these access tokens on behalf of my account.
Here is how I did it step by step :
In Play Console, create a new credential for a web server (if you don't already have one). In the associated Google Cloud Oauth client ID settings, add an "Authorized redirect URI". I don't think the URL matters but I would advice choosing one that you own... (and maybe it even works with one that doesn't exist but I'm not sure)
Open this URL in a browser : https://accounts.google.com/o/oauth2/v2/auth?redirect_uri=<THE_URL_YOU_CHOSE_ABOVE>&prompt=consent&response_type=code&client_id=<YOUR_CLIENT_ID>&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fgames+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fdrive.appdata+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fgames&access_type=offline
After accepting the prompt that should be displayed, you will be redirected to the URL you chose and you should see a parameter 'code=...' (at the top of your screen where you see the URL). This is the authorization code you need!
Exchange that code for a refresh token (Step 5 in the documentation).
Whenever needed, get a new access token using the refresh token ("Refreshing an access token" section in the documentation).
The access token can be used in the authorization header of your requests to the Play Games REST API :)
The whole procedure is explained here : https://developers.google.com/identity/protocols/oauth2/web-server
I am having trouble calling the Google Play Developer API.
I have followed all steps listed on https://developers.google.com/android-publisher/authorization . This includes
Create Project and enabled Google Play Android Developer API (with my Google Play Console Account)
Link the project through Settings > Developer Account > API Access
Grant access to service account with finance permissions to the app through the Google Play Console.
Create OAuth 2.0 Client Id, Client Secret, and Redirect URI credentials.
Generate the Refresh Token and the Access Token by sending POST request.
Then, to call the purchases.subscriptions.get API, I used the following CURL command:
(https://developers.google.com/android-publisher/api-ref/rest/v3/purchases.subscriptions/get)
curl -X GET "https://androidpublisher.googleapis.com/androidpublisher/v3/applications/{packageName}/purchases/subscriptions/{subscriptionId}/tokens/{token}" -H "Authorization: Bearer {access_token}" -H "Accept: application/json" --compressed
However, I am receiving the following error:
"error": {
"code": 401,
"message": "The current user has insufficient permissions to perform the requested operation.",
"errors": [
{
"domain": "androidpublisher",
"message": "The current user has insufficient permissions to perform the requested operation.",
"reason": "permissionDenied"
}
]
}
}
I have read and implemented changes recommended in other posts such as
added in-app product/subscription before granting permission or linking to service account
opened "in-app products/subscription" and performed some updates
Verified all Users and Permissions through Google Play Console
eg. service account is admin user
waited over 48 hours to allow Google to propagate all access rights for APIs.
I have also tried calling the API through
https://developers.google.com/android-publisher/api-ref/rest/v3/purchases.subscriptions/get#authorization-scopes
but still no luck (get an error).
If anyone has any suggestions, that would be very much appreciated. Thanks.
I faced a similar issue, the problem is in the settings we do in google developer project.
Refer to create-play-service-credentials for settings. Use the same primary account with which you created your in-app products.
Make sure you remove the previous one.
Link to a Google Developer Project
Your Play Developer account needs to be linked to a Google Developer Project.
1a. Open the Settings > Developer account menus and select API access
1b. Select Link to connect your Play account to a Google Developer Project
1c. Agree to the terms and conditions
2. Create Service Account
Next we need to create a service account. This is done from the Google API Console.
2a. Select Create Service Account
2b. Create Service account key credentials
2c. Enter details for service account
2d. Download your JSON credential:
3. Grant Access
3a. In Play Console, select Grant Access on the newly created service account
3b. Grant the following permissions:
3c.Click Invite User at the bottom and send the invite
You will be redirected to Users and Permissions where you should see your newly created service account as Active.
I encountered the same issue. In my case, I was not using a key file (json one) for the granted service account on Google Play while verifying purchases on the back-end. I replaced the wrong key file with the one of granted service account on Google Play and it's working fine now.
I am trying to understand how does the google play billing library authenticate.
All the tutorials start with BillingClient but how does billing client know which account to connect how do I pass authentication credentials to it and more importantly where do I get those credentials.
I checked google play billing documentation before asking here and multiple other docs but everyone assumes the developer has the information magically without need to explain.
When I try to use the client without any credentials I just keep getting disconnection errors.
Google Play Billing library authenticates with your Google Play Application Id which is already defined in google-services.json or string variables on your android project. When you check on Google Play Console you will see there is no extra credentials and so you can retrieve in app purchase sku list by their own keys you defined of each product or subscription.
According to this topic: Can I use Purchase Status API to validate if app was bought via Play Store the Google Play Developer API provides a Purchase Token which can be fetched any time. So I imagine to send this purchase token to my backend server to ensure this user has already paid for my app, like it is written here: https://developer.android.com/google/play/developer-api.html#practices
Since the first comment on the posted anwer (see above first link) is, that there is no way to check if the playstore confirms the purchase I am confused.
I dont want to use InApp Purchases. I want my users to be able to buy an app and receive a piece of information for validating this google user has purchased it - in order to store set a flag in my own backend: "UserA: has_paid = true"
How can I achieve this?
I'm creating an Android application that implements subscriptions to digital content on my backend server. What I wish to do is obtain the name and email associated with the Play account that made the purchase, namely the same information I can get if I go to my Merchant account and view an order.
Using the TrivialDrive in-app billing example, I'm able to access the INAPP_PURCHASE_DATA and send that information to my backend server as the "Checking Subscription Documentation" recommends: http://developer.android.com/google/play/billing/v2/billing_subscriptions.html
The documentation lists a typical implementation workflow and says:
When the user successfully purchases a new subscription, your app
notifies a backend server, which stores the purchase token, user name,
and other information in a secure location.
Although I can store the purchase token, and other INAPP_PURCHASE_DATA how do I obtain the user name or email for that matter. From what I can piece togehter I suspect the account details like user name, email, subscripion expiration date must be requested from my back end server. It seems using the purchase token on my backend server is the key to accessing order information, but at this point I haven't found any clear way to go about doing this.
Any suggestions would be appreciated.
Regards
There is an example on the Android Developer site here: Google Play In-app Billing
Testing In-app Billing
Administering In-app Billing
After that Adding items one at a time to a product list
like this
In-app Billing Reference
Then review this Agreement
Helpful links refund policy, In-app Billing, Implementing In-app Billing
Pls tell if you still facing the some problem :)
Thanks