Consumable In App Purchases on Android

Dan Friedman dan at clearvisiontech.com
Wed Aug 9 15:27:51 EDT 2023


Panos and others…

First, thank you for your assistance and advise with this.   Panos’ suggestions were spot on!    Restoring the purchases, then calling mobileStoreConsumePurchase worked for consumption.   And, adding a “complete” case to purchaseStateUpdate and handeling the mobilePurchaseGet() as well as the mobileStoreConsumePurchase worked beautifully.   A couple of follow up questions…

1 - Does the “complete” case get returned with the Apple Store as well?
2 – Is there a way to get the purchase token from mobilePurchaseGet() on Android?   The “transactionIdentifier” returns the order number, not the purchase token.  The purchase token is needed to verify the purchase server side.

Lastly, it would be terrific if the lesson on the LC website was updated to these options/methods.   It might save the next guy some grief.

-Dan


From: use-livecode <use-livecode-bounces at lists.runrev.com> on behalf of panagiotis m via use-livecode <use-livecode at lists.runrev.com>
Date: Wednesday, August 9, 2023 at 7:51 AM
To: How to use LiveCode <use-livecode at lists.runrev.com>
Cc: panagiotis m <merakosp at gmail.com>
Subject: Re: Consumable In App Purchases on Android
Hello all,

Also, it might be worth trying this as well - add a new button with this
code:

on mouseUp
   mobileStoreEnablePurchaseUpdates
   mobileStoreRestorePurchases
end mouseUp

Then press the button, and *then* call mobileStoreConsumePurchase pProductID .
Hopefully now it should be properly consumed, and you should be able to buy
it (and consume it) again.

Cheers,
Panos
--

On Wed, 9 Aug 2023 at 11:37, panagiotis m <merakosp at gmail.com> wrote:

> Hello Dan,
>
> The call to mobileStoreConfirmPurchase pProductID  causes the
> purchaseStateUpdate message to be sent again with status=complete.
>
> So I would not suggest putting the call to mobileStoreConsumePurchase
> pProductID just after mobileStoreConfirmPurchase.
>
> You could either put it in a separate button and see if it works,
> otherwise add a [case "complete"] in the purchaseStateUpdate msg and there
> consume the product and disable purchase updates, i.e.:
>
> on purchaseStateUpdate pPurchaseID, pProductID, pState
>    switch pState
>       case "paymentReceived"
>          answer "Payment received!"
>          offerPurchasedProduct pProductID
>          mobileStoreConfirmPurchase pProductID
>          break
>       case "error"
>          answer "Error occured during purchase handling:" & return &
> return & mobileStorePurchaseError(pPurchaseID)
>          mobileStoreDisablePurchaseUpdates
>          break
>       case "invalidSKU"
>          answer "Invalid SKU."
>          mobileStoreDisablePurchaseUpdates
>          break
>       case "alreadyEntitled"
>          answer "Already Owned."
>          mobileStoreDisablePurchaseUpdates
>          break
>       case "restored"
>          put "Restored: " & pProductID & cr after field "restored"
>          offerPurchasedProduct pProductID
>          mobileStoreConfirmPurchase pProductID
>          break
>       case "cancelled"
>          answer "Purchase Cancelled:" && pProductID
>          mobileStoreDisablePurchaseUpdates
>          break
>       case "complete"
>          answer "Purchase Complete:" && pProductID
>          mobileStoreConsumePurchase pProductID  // <-- ADD THIS HERE
>          mobileStoreDisablePurchaseUpdates
>          break
>    end switch
> end purchaseStateUpdate
>
> Hope this helps.
>
> Kind regards,
> Panos
> --
>
>
>
> On Tue, 8 Aug 2023 at 22:52, Dan Friedman via use-livecode <
> use-livecode at lists.runrev.com> wrote:
>
>> Andrew,
>>
>> Thank you for the input.   The code snippet you said you are using has
>> mobileStoreConsumePurchase IMMEDIATELY following mobileStoreMakePurchase.
>> Is that what you are doing?   The LC example show that
>> mobileStoreMakePurchase should be handled in the purchaseStateUpdate
>> message after the purchase is paymentReceived”
>>
>> If that’s true, then I feel like I’m doing exactly what you are
>> suggesting.   The purchase is fine, but the consumption if not working for
>> me.   Here’s what I’m doing:
>>
>> on startInAppPurchase numCredits
>>   //setup purchase id
>>   if numCredits = 1 then
>>     put 1001 into productID
>>     put "$0.99" into productAmount
>>   else if numCredits = 2 then
>>     put 1002 into productID
>>     put "$1.99" into productAmount
>>   else if numCredits = 3 then
>>     put 1003 into productID
>>     put "$2.99" into productAmount
>>   else if numCredits = 11 then
>>     put 1011 into productID
>>     put "$9.99" into productAmount
>>   end if
>>
>>   //confirm with user
>>   if numCredits = 1 then
>>     put "Are you sure you want to purchase 1 credit for" && productAmount
>> & "?" into pString
>>   else
>>     put "Are you sure you want to purchase" && numCredits && "credits
>> for" && productAmount & "?" into pString
>>   end if
>>   if myAnswer(pString,"Cancel|Buy Now","Purchase
>> Confirmation","|appBlue") = "Cancel" then //my custom answer dialog
>>     exit startInAppPurchase
>>   end if
>>
>>   //initiate the purchase
>>   mobileStoreEnablePurchaseUpdates
>>   mobileStoreSetProductType productID,"inapp"
>>   mobileStoreMakePurchase productID,"1","testPayload - Android Only"
>> end startInAppPurchase
>>
>> on purchaseStateUpdate pPurchaseID,pProductID,pState
>>   global user
>>
>>   switch pState
>>     case "paymentReceived"
>>       put mobilePurchaseGet(pPurchaseID,"receipt") into rawReciptData
>>
>>       //tell our server is was sucessful and log users credits to database
>>       if isIPhone() then
>>         if db_validateAppleReceipt(rawReciptData) then
>>           add (pProductID-1000) to user["credits"]
>>         end if
>>       else
>>         //will add Android database call when ready
>>       end if
>>
>>       mobileStoreConfirmPurchase pProductID //Inform the store that the
>> purchase identifier productID was successfully delivered
>>       if isAndroid() then
>>         mobileStoreConsumePurchase pProductID. //  <--- DOES NOT SEEM TO
>> CONSUME THE PRODUCT !!
>>       end if
>>
>>       mobileStoreDisablePurchaseUpdates
>>       loadMeUp //refresh our display
>>       break
>>     case "error"
>>       answer "Error occured during purchase handling:" & return & return
>> & mobileStorePurchaseError(pPurchaseID)
>>       mobileStoreDisablePurchaseUpdates
>>       break
>>     case "invalidSKU"
>>       answer "Invalid SKU."
>>       mobileStoreDisablePurchaseUpdates
>>       break
>>     case "alreadyEntitled"
>>       answer "Already Owned."
>>       mobileStoreDisablePurchaseUpdates
>>       break
>>     case "restored"
>>       answer "restored"
>>      offerPurchasedProduct pProductID
>>       mobileStoreConfirmPurchase pProductID
>>       mobileStoreDisablePurchaseUpdates
>>
>>       loadMeUp //refresh our display
>>       break
>>     case "canceled"
>>     case "cancelled"
>>       answer "Purchase Cancelled:" && pProductID
>>       mobileStoreDisablePurchaseUpdates
>>       break
>>   end switch
>> end purchaseStateUpdate
>>
>>
>>
>> Do you see anything wonky in my code?
>>
>> --Dan
>>
>> From: use-livecode <use-livecode-bounces at lists.runrev.com> on behalf of
>> Andrew at MidWest Coast Media via use-livecode <
>> use-livecode at lists.runrev.com>
>> Date: Tuesday, August 8, 2023 at 10:57 AM
>> To: use-livecode at lists.runrev.com <use-livecode at lists.runrev.com>
>> Cc: Andrew at MidWest Coast Media <andrew at midwestcoastmedia.com>
>> Subject: Re: Consumable In App Purchases on Android
>> If I’m consuming instantly, this is the code working in my Android/iOS
>> project with comment lines explaining the values being passed in the
>> Android build (note that the product ID values are more specific for
>> Android than iOS):
>>
>>         if tPlatform = "android" then
>>                  put "com.midwestcoastmedia.dj3pm." into tProductIDbase
>>          else if tPlatform = "iPhone" then
>>                  put EMPTY into tProductIDbase
>>         end if
>>         put tProductIDbase & pWhichProduct into tProductID
>>
>>       mobileStoreEnablePurchaseUpdates
>>       ## mobileStoreSetProductType "com.midwestcoastmedia.dj3pm.tip01",
>> "inapp"
>>       mobileStoreSetProductType tProductID, "inapp"
>>       ## mobileStoreMakePurchase "com.midwestcoastmedia.dj3pm.tip01",
>> "1", "Thanks for the buck!"
>>       mobileStoreMakePurchase tProductID, "1", tMessage
>>       ## mobileStoreConsumePurchase "com.midwestcoastmedia.dj3pm.tip01"
>>       mobileStoreConsumePurchase tProductID
>>       put the result into tCatch
>>
>> BUT you’ll also need to implement the on purchaseStateUpdate handler to
>> completely execute the purchase cycle. The lesson is sometimes hard to
>> follow when Android changes their branding/naming but
>> https://lessons.livecode.com/m/4069/l/184481-how-do-i-implement-in-app-purchases-in-livecode-google-play-store
>> <
>> https://lessons.livecode.com/m/4069/l/184481-how-do-i-implement-in-app-purchases-in-livecode-google-play-store><https://lessons.livecode.com/m/4069/l/184481-how-do-i-implement-in-app-purchases-in-livecode-google-play-store%3e>
>> has a good example of this.
>>
>> —Andrew Bell
>> _______________________________________________
>> use-livecode mailing list
>> use-livecode at lists.runrev.com
>> Please visit this url to subscribe, unsubscribe and manage your
>> subscription preferences:
>> http://lists.runrev.com/mailman/listinfo/use-livecode
>>
>
_______________________________________________
use-livecode mailing list
use-livecode at lists.runrev.com
Please visit this url to subscribe, unsubscribe and manage your subscription preferences:
http://lists.runrev.com/mailman/listinfo/use-livecode


More information about the use-livecode mailing list