Author Topic: [ANDROID] Inapp purchase question - How to consume a product?  (Read 677 times)

Offline adaz

  • Mc. Print
  • *
  • Posts: 48
    • View Profile
Hi,

I know that Managed products are supported by AndroidExtras. I'd like to implement "consuming" a product, e.g. when a user purchased extra lives, then I want to allow him to purchase it again by "consuming" the previous item, and let Google know that this item can be purchased again by that user.
Does anybody know how to do this?
Here is Google's documentation about it: https://developer.android.com/google/play/billing/api.html#managed, but I don't know how to code it in GLBasic.

Thank you!

Adaz

Offline adaz

  • Mc. Print
  • *
  • Posts: 48
    • View Profile
In the meantime I figured out that we somehow have to insert a function into "shop.java" similar to this:

Quote
if(tokens[1].equals("Consume"))
{
return something.consumePurchase(3, something.getProductName(), "inapp:com.adaz.app:"+tokens[3]);
}

Then I could call it by success$=JavaCall$("Shop:Consume:"+sku$)

But I don't know the Java syntax, and what module to include for this to work :(

Offline spacefractal

  • Community Developer
  • Prof. Inline
  • ******
  • Posts: 3419
    • View Profile
    • Space Fractal
not supported in glbasic, hopefully newer do.

And im have to say it:
Im personally so much very so much hate consumable items general. So that why im dont want to support them, and even skips games that does this (include big games, except this is for MP only, while SP is uneffected, example GTA5, im dont play MP anyway).

The inapp purchase api im did last year is only for none consumable items, newer those crappy consumable! This have allways been bad with microtransactions crappy thing. Its have recently just been much worse. So..... No support from me. Please this is from personal view only.

Also Mr Plow arcade Android game did do more better :
You did only have one live as standard in demo version in his Galaga clone, but 3 when you paid for it (permanent).
« Last Edit: 2018-Feb-28 by spacefractal »
Greedy Mouse - Karma Miwa - Spot Race - CatchOut - Android Extras - is on a vacation trip, home before end of few days in jan.

Offline adaz

  • Mc. Print
  • *
  • Posts: 48
    • View Profile
Thank you spacefractal, I see what you mean, and I'll think about it.

Can you just help me in one thing: where and how can I check the token Google sends back when I made a purchase?

Thank you!

Offline spacefractal

  • Community Developer
  • Prof. Inline
  • ******
  • Posts: 3419
    • View Profile
    • Space Fractal
sorry im updated the post, but context is same. This can take quite a hell of time, because its not really that easy to do that and require various setup and can no longer remember anything, since its long time ago (im stopped Android dev and even removed all my apps). Its require a lots of stuff to do and is quite confucion. Mr Plow as well IAN have did that, since he can, he should let you know.

Mr Plow, can you give the example to do that, howove

Howover im do might have changed the api, due issues.

Also, remember you CANNOT test purchases from your OWN account (unlike OUYA). Its here OUYA really shined.

Do you use the Inapp.gbas?

If you does, make sure


here is the latest version im got, before im stopped:
Code: GLBasic [Select]
// --------------------------------- //
// Project: GreedyMouse// Start: Thursday, June 27, 2013
// IDE Version: 11.414


// SETCURRENTDIR("Media") // go to media files

GLOBAL INAPP_ERROR$=""      // When a error in a purchase or when restoring.
GLOBAL INAPP_ISONLINE=0     // is network on?
GLOBAL INAPP_PURCHASE$=""   // when a purchase just have been succed.
GLOBAL INAPP_ACTIVATE$=""   // a user is doing the order progress (chould should "progress" to user, if INAPP_ACTIVATE have any content).
GLOBAL INAPP_STATUS$=""     // wating for a callback for either retore or purchase (this can been used when pause was activated).

// **************************** CONFIGURATIONS START HERE ****************************
GLOBAL INAPP_NR_OF_ITEMS=3; // numbers of inapp items you want to uses (this is due init to Android). Not needed for iOS.

// InAppConfig_SkuNames$ configuration for various Appstores. In the game, you might want to only
// use one SKU, which is why its need to been find and convert the ID to the correct name
// for the shop. Also ID numbers is also required for init ITEMS for Android.
//
// For iOS, you also need configuere the Sku Names in the MKStoreKitConfigs.plist too. That
// can been done using xCode. They should named the same with the SKU you configuried in the
// iTunes Connect and similar interfaces.
//
// This can take some time to setup that one.
//
// SKUS should not confict each other on Android stores, or OpenIAP might fails to fid the correct sku, that even on OUYA.
FUNCTION InAppConfig_Sku2Names$: iID$, store$
        // check name for "The Premium Key"

        IF iID$="0" OR iID$="tip: shopkey" OR iID$="tip_shopkey" OR iID$="shopkey"
                IF store$="com.ouya.shop"      THEN RETURN "greedymouse-premiumkey"
                IF store$="gamestick.tv.shop"  THEN RETURN "greedymouse-gs-premiumkey" // SKU is named URL in GameStick Portal
                IF store$="com.google.play"    THEN RETURN "com.spacefractal.greedymouse.thepremiumkey"
                IF store$="general" OR store$="android" THEN RETURN "shopkey" // the shared name for this sku for Android Stores (should not conflict allready used)
                IF store$="microsoft.windows"  THEN RETURN "windows.thepremiumkey"
                iID$="shopkey"
        ENDIF

        // check name for "Unlock Levels"
        IF iID$="1" OR iID$="tip: shopunlock" OR iID$="tip_shopunlock" OR iID$="shopunlock"
                IF store$="com.ouya.shop"      THEN RETURN "greedymouse-unlockalllevels"
                IF store$="gamestick.tv.shop"  THEN RETURN "greedymouse-gs-unlockalllevels" // SKU is named URL in GameStick Portal
                IF store$="general" OR store$="android" THEN RETURN "shopunlock" // the shared name for this sku for Android Stores (should not conflict allready used)
                IF store$="microsoft.windows"  THEN RETURN "windows.unlocklevels"
                iID$="shopunlock"
        ENDIF

        IF iID$="2" OR iID$="donate" OR iID$="shopdonate" OR iID$="tip_donate"
                IF store$="com.google.play"  THEN RETURN "com.spacefractal.greedymouse.donate"
                IF store$="general" OR store$="android" THEN RETURN "donate" // the shared name for this sku for Android Stores (should not conflict allready used)
                IF store$="microsoft.windows"  THEN RETURN "com.spacefractal.greedymouse.donate"
                iID$="donate"
        ENDIF
        RETURN iID$
ENDFUNCTION


// The Public key from YOUR APPLICATION'S PUBLIC KEY, you get from the Dev Console for that store.
// those Security keys os fpr Android only and is not needed for iOS.
FUNCTION InAppConfig_PublicKeys$: store$
        INAPP_DEVKEY = HashNumber("Dffg-rr234-eeef-e353d-dds3-ffr34-sa234") // just put a totally random sucure key for the hash number (this using for other systems as well).
        IF store$="com.google.play" OR store$=1 THEN RETURN "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAkxMRcymg1LZRuyDpBPx7cIQnY+2a4V1zNAuvmLC+8Q8X7XFDhcOqFQaeRGsJXE6qYUhoTi33VbR+0k9vtHpVI0A0H9Yjr1Jadq5knrrxkOn2a7mmXYDUGIrvy+ucyTBiUKPIXhJadkTsX/xeJUdSXj11LN54S2KXakfUSUQMVhZAMGiM0AcnEO2SFHa5jHTC1DnJkVdUDO3ej9TUhio9ccXE1c++ArMyY7mODY15bFB3+Jl/BApc79wFJVQc9vUiRt+fL4OntoYQ/gsJbzqaCmV/YzAQ4NYK4R6rmPwPdhagP5tRW9MXIseFRBLVbm3FDEWPvdgeqdcy5dpFi426aQIDAQAB"
        IF store$="microsoft.windows" THEN RETURN HashNumber(InAppConfig_PublicKeys$("com.google.play"))
ENDFUNCTION
// **************************** CONFIGURATIONS ENDS HERE ****************************
//
//
//
//
//
// **************************** INAPP SHOP FUNCTIONS START HERE ****************************
?IFDEF IPHONE
//      IMPORT "C" int StoreIsOnline(int) // parents check if the inapp is disabled (0=init once, 1=reinit again).
//      IMPORT "C" int StoreIsFeaturePurchased(const char*, int) // checks if the feature have been purchased
//      IMPORT "C" int StoreRestored() // is store have been complete (1) or failed (-1)?
//      IMPORT "C" void StoreRestore() // Restore any previous purchased items (required on iOS).
//      IMPORT "C" int StoreActivate(const char*) // User have just pressed on the buys button in your app.
//      IMPORT "C" const char* StoreGetPrice(const char*) // Get a Price for the product.
//      IMPORT "C" int StoreActivated() // check the purchasing item....
?ENDIF

GLOBAL INAPP_INIT=0
GLOBAL INAPP_ERROR_TIMER=0  // time before error message vanish.
GLOBAL INAPP_STORE$=""      // the store name going to been used.
GLOBAL INAPP_DEVKEY = 0     // a dev key
GLOBAL INAPP_PURCHASES$=""  // a recent purchase, but waiting for receipt (ANDROID ONLY)
GLOBAL INAPP_RECEPTOK = 0   // Have recept to been checked (ANDROID ONLY)
GLOBAL INAPP_PAUSE = 0
GLOBAL INAPP_SAMSUNGID$     // Group ID for Samsung Apps, is init automatic in the init, based on publickey.
GLOBAL INAPP_INACTIVATESTARTED=0


//
// is the store online?
FUNCTION InAppPurchase_isOnline:
        ?IFDEF WIN32
                InAppConfig_PublicKeys$("nothing")
                RETURN 0
        ?ENDIF

        ?IFDEF IPHONE
                LOCAL ok //=StoreIsOnline(0)
                RETURN ok
        ?ENDIF

        ?IFDEF ANDROID
                LOCAL ok=JavaCall$("Shop:IsOnline")
                RETURN ok;
        ?ENDIF
ENDFUNCTION

// get a price of the current product
FUNCTION InAppPurchase_Price$: iID$
        STATIC IDDD$
        STATIC IDPRICE$
        STATIC counter=0


        iID$=InAppConfig_Sku2Names$(iID$, INAPP_STORE$)

        ?IFDEF WIN32
                RETURN "some price"
        ?ENDIF

        ?IFDEF IPHONE
//              IF IDDD$=iID$ AND IDPRICE$<>"unknown" THEN RETURN IDPRICE$
//              LOCAL price$=StoreGetPrice(iID$)
//              price$=TRIM$(price$)
//              IDDD$=iID$
//              IDPRICE$=price$
//              RETURN price$
        ?ENDIF

        ?IFDEF ANDROID
                IF IDDD$=iID$ AND IDPRICE$<>"unknown" THEN RETURN IDPRICE$
                LOCAL price$=JavaCall$("Shop:GetPrice:"+iID$)
                IF price$="-1" THEN price$="offline"
                IDPRICE$=price$
                RETURN price$
        ?ENDIF
ENDFUNCTION

// is the inapp item available? Etc have you brought the item (1) or not (0)? (consumable is not supported yet)
// for some secure reasons, true and false is easy to been hacked, then its uses some hash to get a bit harder to crach.
//
// to also prevent tapping source for exeample from java, checkout fake products and make sure is returned false, which
// give a constant hash number for that. This could been done in various places in your app.
FUNCTION InAppPurchase_isAvailable: iID$
        LOCAL orig$=iID$
        LOCAL ok%=0

        IF INAPP_DEVKEY=0 THEN InAppConfig_PublicKeys$("")
        IF INAPP_DEVKEY=0 THEN RETURN 0
        orig$=InAppConfig_Sku2Names$(iID$, "android")
        iID$=InAppConfig_Sku2Names$(iID$, INAPP_STORE$)

        ?IFDEF WIN32
                ok=INAPP_DEVKEY //StoreWin(iID$, INAPP_DEVKEY)
        ?ENDIF

        ?IFDEF IPHONE
                //ok=StoreIsFeaturePurchased(iID$, INAPP_DEVKEY)
        ?ENDIF

        ?IFDEF ANDROID
                ok=JavaCall$("Shop:isAvailable:"+iID$+":"+INAPP_DEVKEY)
        ?ENDIF

        ok=HashNumberBig(ok)
        ok=ok-ABS(HashNumberBig(InAppConfig_PublicKeys$("microsoft.windows")))
        ok=ok*HashNumber(-ok)
        ok=ASL(ok, 4)
        ok=ok*HashNumber(orig$)
        ok=ok-HashNumber(INAPP_DEVKEY)
        ok=ABS(ok)
        RETURN ok
ENDFUNCTION

?IFDEF WIN32
        FUNCTION StoreWin: iID$, keys
                IF INAPP_DEVKEY=0 THEN InAppConfig_PublicKeys$("nothing")
                IF INAPP_DEVKEY=0 THEN RETURN 0
                LOCAL ok=0

                IF iID$="jdg445Ffk439Ffkdd3t" THEN RETURN 0
                RETURN keys // allwys return a success.
                RETURN 0 // allways return a fail.
        ENDFUNCTION
?ENDIF

// Start the payment progress (etc you have pressed on a purchase button).
// On windows, the purchase is allways succes. On iOS and Android, a
// GLB_ON_PAUSE/() can been called here, so you might checks INAPP_STATUS$ for
// eventuelly checks if there us a purchase ongoing or not in there.
FUNCTION InAppPurchase_Activate: iID$
        INAPP_INACTIVATESTARTED=1
        IF INAPP_STATUS$<>"" AND INAPP_STATUS$<>"Activate"
                INAPP_ERROR$="store progress ongoing"
                RETURN
        ENDIF

        iID$=InAppConfig_Sku2Names$(iID$, INAPP_STORE$)
        ?IFDEF WIN32
                InAppPurchase_Finished(iID$)
                RETURN TRUE
        ?ENDIF

        ?IFDEF IPHONE
//              LOCAL ok=StoreActivated() // if user have cancelled purchasem but purcahse did got succes, then the purchase should been activated
//              IF ok=1
//                      INAPP_PURCHASE$=iID$
//                      INAPP_STATUS$=""
//                      RETURN
//              ENDIF
//              StoreActivate(iID$)
//              INAPP_STATUS$="Activate"
//              INAPP_ACTIVATE$=iID$
//              RETURN TRUE
        ?ENDIF

        ?IFDEF ANDROID
                IF INAPP_STATUS$=""
                        DEPRINT("InAppPurchase_Activate:"+iID$)
                        JavaCall$("Shop:Activate:"+iID$)
                        INAPP_STATUS$="Activate"
                        INAPP_ACTIVATE$=iID$
                ENDIF
        ?ENDIF
        ENDFUNCTION

// A Purchase have just been activated and then its should been saved here locally.
// Only required for Windows for Fake purchases to save the purchases. Its doing
// automatic on Android as well iOS.
FUNCTION InAppPurchase_Finished: iID$
        INAPP_PURCHASE$=iID$
        IF INAPP_ERROR$="" THEN INAPP_ERROR$="success"
        iID$=InAppConfig_Sku2Names$(iID$, INAPP_STORE$)
        ?IFDEF Win32
                SetStr(InAppHelper_HashID$(iID$), "Purchase", 1)
        ?ENDIF
ENDFUNCTION

// you must do a restore feature for IOS to keep Apple happy to recover all
// perlament purchased items. Dont forget to check the features is Available
// trought InAppPurchase_isAvailable(), which is not automatic done.
//
// a succes would sent a INAPP_PURCHASE$="restored". If user failed to restore
// then a error would been sent to INAPP_ERROR$
//
// This is done automatic on Android and OUYA on startup, but this is required
// for iOS.
FUNCTION InAppPurchase_Restore:
        IF INAPP_STATUS$<>"" THEN RETURN

        ?IFDEF WIN32
                FOR i=0 TO 100
                        LOCAL iID$=InAppConfig_Sku2Names$(i, INAPP_STORE$)
                        IF iID$<>""
                                InAppPurchase_Activate(iID$)
                        ELSE
                                RETURN
                        ENDIF
                NEXT
        ?ENDIF

        ?IFDEF IPHONE
//              StoreRestore()
//              INAPP_STATUS$="Restore"
//              INAPP_ERROR_TIMER=0
        ?ENDIF
ENDFUNCTION

// This is a updater function, which is required to been invoked in loop time.
// This function checkout ongoing purchases using callbacks. that why you need
// this around a SHOWSCREEN.
FUNCTION InAppPurchase_Update:
        LOCAL ok=0
        ?IFDEF ANDROID
                IF INAPP_RECEPTOK=1
                        INAPP_RECEPTOK=2
                        INAPP_ERROR$=""
                ENDIF
        ?ENDIF

        IF INAPP_ERROR$<>""
                INAPP_ERROR_TIMER=INAPP_ERROR_TIMER+UpdateTicks
                IF INAPP_ERROR_TIMER>60
                        INAPP_ERROR_TIMER=0
                        INAPP_ERROR$=""
                ENDIF
        ENDIF

        ?IFDEF WIN32
                IF INAPP_INIT=0
                        INAPP_INIT=1
                        INAPP_STORE$="microsoft.windows"
                        InAppConfig_PublicKeys$("")
                        INAPP_PURCHASE$="restored"
                        INAPP_RECEPTOK=2
                ENDIF
        ?ENDIF

        ?IFDEF IPHONE
//              IF INAPP_INIT=0
//                      INAPP_INIT=1
//                      INAPP_STORE$="apple.appstore.ios"
//                      INAPP_ISONLINE=StoreIsOnline(0)
//                      IF INAPP_ISONLINE<>0
//                              IF INAPP_RECEPTOK<1
//                                      INAPP_PURCHASE$="restored"
//                                      INAPP_RECEPTOK=1
//                              ENDIF
//                      ENDIF
//              ENDIF

//              IF INAPP_STATUS$="Activate"
//                      INAPP_ERROR_TIMER=0
//                      ok=StoreActivated()
//                      IF ok=1
//                              INAPP_PURCHASE$=INAPP_ACTIVATE$
//                              INAPP_STATUS$=""
//                              INAPP_ACTIVATE$=""
//                      ELSEIF ok=-1 OR (InAppPurchase_isOnline()=0)
//                              INAPP_STATUS$=""
//                              INAPP_ACTIVATE$=""
//                              INAPP_ERROR$="cancelled or failed"
//                              INAPP_ERROR_TIMER=0
//                      ENDIF
//              ENDIF

//              IF INAPP_STATUS$="Restore"
//                      ok=StoreRestored()
//                      IF ok=1
//                              INAPP_RECEPTOK=2
//                              INAPP_PURCHASE$="restored"
//                              INAPP_STATUS$=""
//                      ELSEIF ok=-1
//                              INAPP_ERROR$="failed"
//                              INAPP_STATUS$=""
//                              INAPP_ERROR_TIMER=0
//                      ENDIF
//              ENDIF
        ?ENDIF

        ?IFDEF ANDROID
                IF INAPP_INIT=0
                        INAPP_INIT=1
                        InAppHelper_Init()
                ENDIF

                IF INAPP_RECEPTOK<1
                        ok=JavaCall$("Shop:isReceiptDone")
                        IF ok=1
                                INAPP_RECEPTOK=1
                                INAPP_PURCHASE$="restored"
                                IF INAPP_PURCHASES$<>""
                                        INAPP_PURCHASE$=INAPP_PURCHASES$
                                        INAPP_PURCHASES$=""
                                        INAPP_STATUS$=""
                                        INAPP_ACTIVATE$=""
                                        JavaCall$("fullscreen")
                                ENDIF
                        ENDIF
                ENDIF

                IF INAPP_STORE$="No" THEN INAPP_STORE$=JavaCall$("Shop:GetAppStoreName")
                IF INAPP_STATUS$="Activate" AND INAPP_STORE$<>"No"
                        INAPP_ERROR_TIMER=0
                        LOCAL result$=JavaCall$("Shop:Activated")
                        IF LEFT$(result$, 4)="fail" THEN ok=-1
                        IF LEFT$(result$, 4)="succ" THEN ok=1
                        LOCAL isOnline=InAppPurchase_isOnline()
                        IF ok=1
                                JavaCall$("Shop:ActivateReset")
                                INAPP_RECEPTOK=0;
                                INAPP_PURCHASES$=StringField$(result$, 3, ":")
                        ELSEIF ok=-1 //OR isOnline=0
                                JavaCall$("Shop:ActivateReset")
                                INAPP_STATUS$=""
                                INAPP_ACTIVATE$=""
                                INAPP_ERROR$="cancelled or failed"
                                INAPP_ERROR_TIMER=0
                        ENDIF
                ENDIF

        ?ENDIF
ENDFUNCTION
// **************************** INAPP SHOP FUNCTIONS ENDS HERE ****************************

// *** HELPER FUNCTIONS ****
FUNCTION InAppHelper_SetSku: shop$, i
        LOCAL sku$=InAppConfig_Sku2Names$(i, shop$)
        LOCAL sgeneral$=InAppConfig_Sku2Names$(i, "general")
        IF sku$<>"" AND sku$<>sgeneral$ AND sku$<>"0"
                JavaCall$("Shop:SetSku:"+sgeneral$+":"+shop$+":"+sku$)
        ENDIF
ENDFUNCTION

FUNCTION InAppHelper_Init:
        ?IFDEF ANDROID
                // items for the store.

                FOR i=0 TO INAPP_NR_OF_ITEMS-1
                        JavaCall$("Shop:SetSku:android:"+InAppConfig_Sku2Names$(i, "general")+":"+InAppConfig_Sku2Names$(i, "general"))
                        InAppHelper_SetSku("com.google.play", i)
                        InAppHelper_SetSku("com.ouya.shop", i)
                        InAppHelper_SetSku("com.amazon.apps", i)
                        InAppHelper_SetSku("com.samsung.apps", i)
                        InAppHelper_SetSku("com.yandex.store", i)
                        InAppHelper_SetSku("com.nokia.nstore", i)
                        InAppHelper_SetSku("Appland", i)
                        InAppHelper_SetSku("SlideME", i)
                        InAppHelper_SetSku("cm.aptoide.pt", i)
                NEXT
                JavaCall$("Shop:Init")
                INAPP_STORE$=JavaCall$("Shop:GetAppStoreName")
        ?ENDIF
ENDFUNCTION

// hash an item to save locally when a purchase have been succed.
FUNCTION InAppHelper_HashID$: iID$
        LOCAL DID$=PLATFORMINFO$("ID")+iID$
        DID$=ENCRYPT$(DID$, LEFT$(DID$, 5))
        DID$=HashNumber(DID$)+""+HashNumber(PLATFORMINFO$("ID"))+""+HashNumber(iID$)+""+472882049
        RETURN DID$
ENDFUNCTION
 

Make sure to call InAppPurchase_Update() top in your code, and call InAppPurchase_Update() in your SHOWSCREEN() for all places. This is due purchases is async and can might take a while its take effect. Sometimes when you check the purchase have been brought, but take a sec or two after a launch. But im do mean im did some code, so its can wait until update finished.

PS. Extractly here OUYA was MUCH more easier than Google Play. Im liked that way OUYA worked for inapp really.
Greedy Mouse - Karma Miwa - Spot Race - CatchOut - Android Extras - is on a vacation trip, home before end of few days in jan.

Offline adaz

  • Mc. Print
  • *
  • Posts: 48
    • View Profile
Thanks, but everything already works, I can purchase my products, but I don't know how to check the token that Google sends back.
Thanks!

Offline spacefractal

  • Community Developer
  • Prof. Inline
  • ******
  • Posts: 3419
    • View Profile
    • Space Fractal
use InAppPurchase_isAvailable() and use the internal SKU for it, if you also use this API.

the internal SKU is the reason, because they might named different in different shops.

Also you should not checks InAppPurchase_isAvailable() in the startup, then you would been too early. You should check them in runtime in your menu, because they are not Available in the start, but might take some time after a launch of a app.

on iOS make sure to restore, and im not even sure its works at all, since its so long time since then. 2 or 3 years ago. so its might got removed again? Im dont know.
Greedy Mouse - Karma Miwa - Spot Race - CatchOut - Android Extras - is on a vacation trip, home before end of few days in jan.

Offline MrPlow

  • Prof. Inline
  • *****
  • Posts: 1267
    • View Profile
Hi Adaz,

I will try to help you to get your validation working.
In order to work with a purchased product you need to know what is a 'valid' bought response (long number) from Google.


1. To do this you need to test your app on a device and account that allows you to purchase.

2. Make sure to store response with something like this...

newlife = InAppPurchase_isAvailable("< your sku >")

3. In your test version make sure to output or PRINT the successful bought value in 'givelives' to screen or .txt file.

4. Buy your item on the test device and note the value.

5. Use the success value to validate and auth your purchase check, any other value is wrong (not bought).

6. Remove the test printing code and create your production version.

To keep it more stable I store the value in an ini file so the user does not lose the purchase (Google Play sync issues)

If I was amending this now I would also use ENCRYPT$ and DECRYPT$ functions to make it more secure.

Hope this helps!

I have use Inapp for following:

a) Disable Ads
b) Purchase full version (extra lifes)
c) Buying a New Type of Ship item


Code: GLBasic [Select]

        IF newlife<>1889290111  THEN    checkpur() //Does a double check of saved ini of purchase code


FUNCTION checkpur:

        LOCAL test$
        test$ = PLATFORMINFO$("DOCUMENTS") + "/shp87823231.ini" // or use APPINFO
                LOCAL hsc% = 0
        LOCAL ok
        LOCAL sc% = 5684412

        IF DOESFILEEXIST(test$)=FALSE AND newlife% = 1889290111


                ok=OPENFILE(1,test$,FALSE)
                        IF ok=TRUE

                                WRITELONG 1,sc%
                                CLOSEFILE 1
                        ENDIF

        RETURN
        ENDIF


        IF DOESFILEEXIST(test$)=FALSE THEN RETURN

                ok= OPENFILE(1, test$, TRUE)

                IF ok=TRUE
                        READLONG 1,hsc%

                        CLOSEFILE 1
                        IF hsc% > 0 THEN RETURN hsc%
                ENDIF
        IF hsc%=5684412 THEN newlife% = 1889290111
ENDFUNCTION
 
« Last Edit: 2018-Mar-01 by MrPlow »
Comp:
Speccy-48k, Speccy-128k, Amigas, PCs

Offline spacefractal

  • Community Developer
  • Prof. Inline
  • ******
  • Posts: 3419
    • View Profile
    • Space Fractal
also creating ini is not that secure, its can easy to been cracked (you can also crypt it by using the hardware info eventuelly) as well date of creation. So the file got removed when the date is, so the game is needs to been rechecked again.

Google Play should also works offline as well, and you cannot sync the items start of the code. That might first been done while you are in the menu. So its best allways checked around a SHOWSCREEN on your loop code. then items would eventuelt change to brought.

In Greedy Mouse im remember im created a function to pause it, until the items was ready to been checked.

Please Note ads does property not work in newest AE, but inapp purchase should do. Im dont want to use the time to move it to Android Studio.
Greedy Mouse - Karma Miwa - Spot Race - CatchOut - Android Extras - is on a vacation trip, home before end of few days in jan.

Offline adaz

  • Mc. Print
  • *
  • Posts: 48
    • View Profile
Thank you guys, I think I understand you wrote.
2 more questions: how can I check which products are available to purchase, and which products I already own?

Offline MrPlow

  • Prof. Inline
  • *****
  • Posts: 1267
    • View Profile
The same way for each...

If you get

product1 = InAppPurchase_isAvailable("product1sku")
product2 = InAppPurchase_isAvailable("product2sku")

values and check against what you know each valid value is then you can show option to buy or have them greyed out.

Comp:
Speccy-48k, Speccy-128k, Amigas, PCs

Offline spacefractal

  • Community Developer
  • Prof. Inline
  • ******
  • Posts: 3419
    • View Profile
    • Space Fractal
I'm do not return it's as a 0 or 1, but a hashed value by the sku.

You can get which kind value it's have for a purchased value.

The value is different per sku.
Greedy Mouse - Karma Miwa - Spot Race - CatchOut - Android Extras - is on a vacation trip, home before end of few days in jan.

Offline adaz

  • Mc. Print
  • *
  • Posts: 48
    • View Profile
InAppPurchase_isAvailable returns always the same code either if I the item is already purchased, or it's a never-purchased new product. I even tried to comment out the hashing-mechanism in InAppPurchase_isAvailable, to return the result of "JavaCall$("Shop:isAvailable:"+iID$+":"+INAPP_DEVKEY)" directly, but that value is always 0. Why?

Moreover, InAppPurchase_Price$ always returns "unknown". When I press purchase, the Google window appears, and shows the correct price, but GLBasic doesn't... Why?

Thanks!

Offline spacefractal

  • Community Developer
  • Prof. Inline
  • ******
  • Posts: 3419
    • View Profile
    • Space Fractal
its can been a android manifest issue.

Do you have <uses-permission android:name="com.android.vending.BILLING" />? and added the google service into too? Otherwise its will remove the shop# code if its dont exists and nothing will works.

Also you can log what its saw in the logcat.
« Last Edit: 2018-Mar-02 by spacefractal »
Greedy Mouse - Karma Miwa - Spot Race - CatchOut - Android Extras - is on a vacation trip, home before end of few days in jan.

Offline MrPlow

  • Prof. Inline
  • *****
  • Posts: 1267
    • View Profile
You also need to be testing on an account different to your dev account.

I still work from AE 2.9 for my inapp billing and admob and have added play services version 7 (manually).

But latest inapp changes were tested to be working by SF in his Greedy Mouse I'm sure.


Comp:
Speccy-48k, Speccy-128k, Amigas, PCs