B4J Question Androidpublisher API

aaronk

Well-Known Member
Licensed User
Longtime User
Hi,

I have a B4A app with in app purchases in it.

In my B4A app, I am sending a message to my B4J app which will tell it to check Google Play to confirm if the payment was made or not.

I know if my B4J app got this message that the payment must have been made, but I want to also check server side as well. (just in case someone hacks my app and sends a fake payment to my server).

Done some research and found: https://developers.google.com/android-publisher/api-ref/purchases/products/get#http-request

(this seems to be the only thing I have found so far)

Looking at the above page, it looks like this is meant to return if the purchase was successful or not.

2 things I have noticed..

1. It looks like it requires it to open a web browser to authorize the oAuth. When running it as a non-UI it doesn't work since it can't open the browser to authorize it.

Is there a way in running this as a non-UI app ?


2. When I do run it as a non-UI it shows the following in the log..

Waiting for debugger to connect...
Program started.
Getting access token from authorization code...
Token received. Expires: 07/02/2017 16:31:52

{
"error": {
"errors": [
{
"domain": "global",
"reason": "required",
"message": "Login Required",
"locationType": "header",
"location": "Authorization"
}
],
"code": 401,
"message": "Login Required"
}
}
false
Online data not available.

The code I am using is:

B4X:
Sub Process_Globals
    Private fx As JFX
    Private MainForm As Form
    Private ClientId As String = "1910.......apps.googleusercontent.com"
    Private ClientSecret As String = "93Fw....ieS"
   
    Private oauth2 As GoogleOAuth2
    Private lblBirthday As Label
    Private lblEmail As Label
    Private lblName As Label
End Sub

Sub AppStart (Form1 As Form, Args() As String)
    MainForm = Form1
    oauth2.Initialize(Me, "oauth2", ClientId, "https://www.googleapis.com/auth/androidpublisher", ClientSecret, File.DirData("GoogleContacts"))
    MainForm.RootPane.LoadLayout("1") 'Load the layout file.
    MainForm.Show
End Sub

Sub btnGetData_Action
    oauth2.GetAccessToken
    Wait For OAuth2_AccessTokenAvailable (Success As Boolean, Token As String)
    If Success = False Then
        Log("Error accessing account.")
        Return
    End If
    Dim j As HttpJob
    j.Initialize("", Me)
    'full list of features available: person.addresses,person.age_ranges,person.biographies,person.birthdays,person.bragging_rights,person.cover_photos,person.email_addresses,person.events,person.genders,person.im_clients,person.interests,person.locales,person.memberships,person.metadata,person.names,person.nicknames,person.occupations,person.organizations,person.phone_numbers,person.photos,person.relations,person.relationship_interests,person.relationship_statuses,person.residences,person.skills,person.taglines,person.urls
   
   
    Dim packageName As String = "my.app.nam"   
    ' The package name of the application the inapp product was sold in (for example, 'com.some.thing'). (string)
   
    Dim productId As String    = "my.app.name.productid"
    ' The inapp product SKU (for example, 'com.some.thing.inapp1'). (string)

    Dim Token As String    = "fndbkcedmnjbenc.......qToYEvB0jlIcaxCO2GZbDw"
    ' The token provided to the user's device when the inapp product was purchased. (string)

    Log("https://www.googleapis.com/androidpublisher/v2/applications/" & packageName & "/purchases/products/" & productId & "/tokens/" & Token)
    j.Download("https://www.googleapis.com/androidpublisher/v2/applications/" & packageName & "/purchases/products/" & productId & "/tokens/" & Token)
    Wait For (j) JobDone(j As HttpJob)
    Log(j.Success)
    If j.Success Then
       
        ParsePersonData(j.GetString)
    Else
        oauth2.ResetToken
        Log("Online data not available.")
    End If
    j.Release
End Sub


Sub ParsePersonData (data As String)
    Log(data)

End Sub

'Return true to allow the default exceptions handler to handle the uncaught exception.
Sub Application_Error (Error As Exception, StackTrace As String) As Boolean
    Return True
End Sub

(I removed some field while posting on the forum.)

Firstly is this possible in a non-UI app? And any ideas on why the above fails ?

I did create a new OAuth Client id with the type set to Other, and following the tutorial from here: https://www.b4x.com/android/forum/threads/class-b4x-google-oauth2.79426/#content
 

aaronk

Well-Known Member
Licensed User
Longtime User
authorize it once in a UI app and then take the saved token and use it in your server app

Doesn't it expire ?

Based on the log:
Token received. Expires: 07/02/2017 16:31:52

I am guessing I will need to login to the server once a week and update the token ?

Based on my code should this code work since it's saying login is required ?

I can't work out where I have gone wrong ?
 
Upvote 0

DonManfred

Expert
Licensed User
Longtime User
Upvote 0

aaronk

Well-Known Member
Licensed User
Longtime User
as the request ends in an error you get an date in the past.
I think the date is in US format (MMDDYYYY)

I think the token is ok, except it's going to expire, but can't work out why it says Login Required even knowing I am sending the correct details.
 
Upvote 0

aaronk

Well-Known Member
Licensed User
Longtime User
How do I get pass my issue?

Nothing is logged in the IDE log, but when I press btnGetData_Action it then opens the web browser and asks for me to login, which I do. (using my Google Play developer login).

Then it asks me to allow 'view and manage your Google Play development account'. I selected 'allow'.

The browser then redirects me to 127.0.0.1:51067/?code=4/mmZNiC.........

Then it logs the following in the IDE:
{
"error": {
"errors": [
{
"domain": "global",
"reason": "required",
"message": "Login Required",
"locationType": "header",
"location": "Authorization"
}
],
"code": 401,
"message": "Login Required"
}
}
false
Online data not available.

I am guessing something is not right somewhere, but any idea where I have gone wrong ?
 
Upvote 0

aaronk

Well-Known Member
Licensed User
Longtime User
You should start with implementing it in a UI project
I am. (code in the first post) Everything I have done so far has been with the UI.

Once I get it working in a UI app, then I will try and get it working in a non-UI app.
 
Upvote 0
Top