Quick Links: Download Gideros Studio | Gideros Documentation | Gideros community chat | DONATE
Common In App Billing Interface - Page 4 — Gideros Forum

Common In App Billing Interface

1246

Comments

  • ar2rsawseenar2rsawseen Maintainer
    Hmm, interesting, did not know that.
    Always used the developer account attached to Developer console, not the main account used for business
  • I was able to use test product android.test.purchased and got response back from Google but I am struggling with my real product ID and getting "the item you are attempting to purchase cannot be find" with error message productsError Request Failed
    purchaseError User canceled. (response: -1005:User cancelled)

    Do I need to publish my app as alpha or beta release? can I not test it in my custom built gideros player and running my app from gideros?

    if this is the case and I need to publish it to test it, how do you guys test it then? or you write perfect code from the first try? :)

    Not sure what I am missing here.
  • tkhnomantkhnoman Member
    edited September 2014
    @boriskey : Yes, you need to upload an app with the right permission and bundle to Alpha version and publish it. (no complete asset needed, no asset is also fine)

    After that, you can then test it with your custom android player (that is, removing the asset folder inside asset folder).
    I kind of forgot, but extract to Android might be needed because of the keystore used.
    That is why it is preferable to build that custom player.
    (Also take a note, it might need several hour after you press publish to be able to test the purchase)

    Likes: boriskey

    +1 -1 (+1 / -0 )Share on Facebook
  • boriskeyboriskey Member
    edited September 2014
    @tkhnoman thanks for your response!

    At this point I have my custom built gideros player and my complete app (the one I published to alpha). Custom built gideros player was deployed to my android device signed with my key. The app I posted to alpha is signed with the same key (package name is different though) and I just downloaded it with a test user and was able to purchase my real product - so yay that part worked!

    I guess I still wonder if there is a faster way without publishing my app to google play every time I change code. I was hoping I could use custom gideros player somehow - is that possible?
  • @tkhnoman I think i finally got it - thanks for your explanation! so here is the process that worked for me:

    1) build complete app, sign and publish to alpha release to google play

    2) build app again but this time with all files deleted from assets folder, sign it and export apk to device - this will act a "custom player"

    3) now continue development / testing using Gideros studio, running that custom player on my device

    I can now get some sleep! :)
  • It seems that iab:requestProducts() does not work if you use your editor gmail account.

    I have tested with another mobile and gmail account and it works.
    thanks for mentioning this and this post prompted me to read google's documentation which was not an easy read. But they do mention and explain important requirements like the one about test account, app signing (you have to sign even custom built gideros player) and setting up test users for purchases.

    http://developer.android.com/google/play/billing/billing_testing.html


  • boriskeyboriskey Member
    edited September 2014
    I would like to understand isAvailable() event. In the example shipped with the lib, it says that you need to call this before you make a purchase or restore requests, but in the example in this thread, ar2rsawseen just called iab:purchase() without waiting for EVENT.AVAILABLE.

    The reason I am asking I am not sure how long it takes between calling isAvailable() and getting back EVENT.AVAILABLE - is it pretty much instant? I want to make sure my users do not press purchase button twice and there is no lag.

    I can test it myself of course but I think it will help others to know the different between using isAvailable() and then purchase() instead of simply just calling purchase().

    also does isAvailable() verify that user is connected to internet at the moment? or is it something purchase() and restore() methods will do?
  • @boriskey it is very recommended to call isAvailable and wait for Event.AVAILABLE

    And the waiting time might be different, from my tests can take up to to 10 seconds.

    I usually create methods for scenes called addIabButtons

    and then when iab is available called
    I check if current scene has addIabButtons method and call it to display them on screen
  • Has anyone had this email yet from Google?

    "Beginning January 2015, we will end support for the In-app Billing Version 2 API. After this date, users will no longer be able to make in-app purchases using your app until you upgrade your app to use the Version 3 API.
    The list below contains the applications that we detected which have had a transaction on the v2 API in the last 3 months. This list may contain applications that you have already updated to version 3.

    com.xxxxxx.xxxxxx

    We recommend that you migrate your version 2 implementation to version 3 as soon as possible to avoid any disruption to your app monetization for the above apps. For apps in this list that have already been updated, please verify your implementation.
    "

    Is the latest labs version using version 2 or 3 api?
    Coder, video game industry veteran (since the '80s, ❤'s assembler), arrested - never convicted hacker (in the '90s), dad of five, he/him (if that even matters!).
    https://deluxepixel.com
  • @SS, yep. It is pretty bad news. Wonder why google do that. They will lose part of revenue from unsupported, but still working apps. Same with new Admob...
    May be somebody already has a build of Gideros with embeded v3 In-app? Using one more plugin for EVERY app is annoying.
  • ar2rsawseenar2rsawseen Maintainer
    edited September 2014
    @SinisterSoft Built in Google Billing uses API v2, but IAB plugin uses v3

    @unlying modify Gideros project template, which is used to export, it is located inn [Gideros Install Directory]\Templates\Eclipse\Android Template
    And I think you can do the same for xCode template is [Gideros Install Directory]\Templates\Xcode4\iOS Template\iOS Template (unfortunately I have not tried mangling with IOS template)

    And Gideros should export projects with all your modficiations and plugins you provided preinstalled
    ;)

    Likes: SinisterSoft, jdbc

    +1 -1 (+2 / -0 )Share on Facebook
  • @ar2rsawseen Thanks. :)
    Coder, video game industry veteran (since the '80s, ❤'s assembler), arrested - never convicted hacker (in the '90s), dad of five, he/him (if that even matters!).
    https://deluxepixel.com
  • jdbcjdbc Member
    edited September 2014
    I guess that an common Android payment System out of Google Play SDK but still using gmail accounts will be a success.

    Google Play is becoming a hostil platform for indie developers ... downloads and time for integrating its APIs.
  • @ar2rsawseen published my app to google play and inapp works wonderfully - thanks again for this brilliant addon!

    However on iOS, iab:restore() method does not work like it does on Android - restore method simply does not call onPurchase complete or purchase error events like it does on Android. I can make the initial purchase with iab:purchase() just fine.

    Am I supposed to handle onrestore event on iOS or do something special? I was heavily using your example on page 2 of this thread :) I have only one product (non-consumable) and since restore() calls purchase complete event, I coded my logic there.

    Likes: dominikusdp

    +1 -1 (+1 / -0 )Share on Facebook
  • @ar2rsawseen I got the problem same with @boriskey 's message above, in iOS, iab:restore() doesn't dispatch PURCHASE_COMPLETE event, and it always dispatches RESTORE_COMPLETE event (even though the user hasn't been purchased the item)
    I was heavily using your example on page 2 of this thread :) I have only one product (non-consumable) and since restore() calls purchase complete event, I coded my logic there.
    how you do it @boriskey ? did you code in obj-c code or in your game's lua ? i have tried and we don't have any property in event parameter so I can't check anything (whether the restoring process is successful for real or not).

    really need the help, thanks :D
  • I think I had a fix for it, let me recheck
  • that would be awesome, thanks @ar2rsawseen. Like @dominikusdp said above, I also tried to use onrestore event but it did not work out.

    If you can make it like in android, it would be great. I think Apple can reject apps if they do not see Restore button.
  • hmm unfortunately had no changes to iab plugin, and app I published before was working correctly and approved by Apple.

    So maybe something has changed? Are you testing it on ios8?
  • Hi, thanks for your quick reply @ar2rsawseen :)

    I am testing it on ios 5 and ios 7, same behavior.

    I see itunesconnect changed a lot lately, not sure whether the error is caused by something changed on apple side or not. I haven't used gideros' in-app before.

    With the IAB interface, if user haven't purchased the item and iab:restore is called, it will dispatch RESTORE_COMPLETE or RESTORE_ERROR ? event for RESTORE_COMPLETE don't have any property so i can't check anything there.

    Can I see your what you do in every event handler in your lua code in your working app ? Is it same as the example ? Or I need to handle something else there for iOS ?

    Thanks. :)
  • tested it again today and no luck - initial purchase works fine but restore does not. It would dispatch onrestore event - here is a dump of on restore event variable:

    {__target={__userdata=userdata: 0x3735aac,__events={[userdata: 0x14515c50]=function: 0x372d560,[userdata: 0x145158d0]=function: 0x37162f0,[userdata: 0x14515d60]=function: 0x36f6650}},__type="restoreComplete",__userdata=userdata: 0x36eb02c}

    but then on purchase event is not called like it is called on Android and you cannot use onrestore by itself because it does not give you any indication that purchase has been made successfully.

    ar2rsawseen, do you mind to post your code for iOS on how you do a restore?

    I wait for is available event, then wait till RESTORE button is tapped and then call restore method. Events are added to the scene by that time. On restore would fire up, but on purchase complete (or on purchase error) would never fire up.

    I have xcode 5 and testing it on iPad 3 with iOS 7.1.

    I also found another issue which will be very irritating for users - I init my iab class and this line
    self.iab = IAB.new(self.iaps[1])

    will pop up "Sign to iTunes Store" window even though I have not clicked on Purchase or Restore buttons. Is that by design? How you handle this in your code?
  • boriskeyboriskey Member
    edited September 2014
    looks like I found another issue (unless I messed it up somehow).

    I built a custom player for iOS with ads and iab plugins, so I can test my app by running it from Gideros Studio, which worked wonderfully when I was building Android version.

    Now with iOS, every time I run my app from Gideros Studio and play it on iPad remotely, using custom built player, iab events from previous runs continue to fire up and stack up.

    The only way is to stop the player on device (kill it) and run it again and then run the app from Gideros Studio.

    Looks like events continue to "live" and stack up with every rerun.

    To be precise, I was testing onRestoreComplete event like that:
    function InAppPurchase:onRestoreComplete(e)
     
    	print( table.tostring( e ) )
     
    	for k,v in pairs(e) do print(k,v) end		
    end
    First time I run it from player on device, it prints one line when I hit Restore button in my game. When I hit Play button from Gideros Studio and do the same - now it fires up twice and shows 2 lines. Hit play again - and it fires up 3 times now.

    Does it make any sense?

    I did check standard Gideros events (on mouse down) and that one was working as expected and would not fire up more than once on the following runs.
  • boriskeyboriskey Member
    edited September 2014
    @ar2rsawseen I do not really know objective C but I put a bunch of NSLogs in your iabios.mm methods to see which one are called when I request a restore.

    Basically updatedTransactions is never called but paymentQueueRestoreCompletedTransactionsFinished is called.

    The problem is you fire up onpurchase event in updatedTransactions method which is never called when restore is requested.

    I could try to fix it myself but I have no clue about Objective C so I am hoping you can take a look at this when you have time.

    Also from here
    https://developer.apple.com/library/ios/documentation/StoreKit/Reference/SKPaymentQueue_Class/index.html#//apple_ref/occ/instm/SKPaymentQueue/restoreCompletedTransactions
    After the transactions are delivered, the payment queue calls the observer’s paymentQueueRestoreCompletedTransactionsFinished: method. If an error occurred while restoring transactions, the observer will be notified through its paymentQueue:restoreCompletedTransactionsFailedWithError: method.
    So it does not look like iOS would ever call updatedTransactions method but again I have no experience whatsoever here.

    Also it appears from docs that you need to finishTransaction for restore as well - when restore is requested, Apple created new transaction which also needs to be finished or it will sit in the queue:
    If your app doesn’t use the app receipt, it examines all completed transactions as they’re restored. It uses a similar code path to the original purchase logic to make the product available and then finishes the transaction.
  • This is normal. Same way as you purchase, you add transaction to the payment queue, then when you call restore transactions, it should also add them to the payment queue.
    And it should call update transactions internally

    From Apple docs:

    https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/StoreKitGuide/Chapters/Restoring.html

    Restoring Completed Transactions

    Your app starts the process by calling the restoreCompletedTransactions method of SKPaymentQueue. This sends a request to the App Store to restore all of your app’s completed transactions.

    ...

    The App Store generates a new transaction for each transaction that was previously completed.
  • the problem is in my case it would never call updateTransaction when I do restore. Do you mind to check your app if restore actually works? and maybe post the code how you do that there?

    I am really at the loss and do not know what to do at this point. Like I said initial purchase works fine just not the restore piece.
  • That was a client app but I will check.
    Unfortunately I have not found anything indicating there was a change in this, so maybe the code is faulty.

    I remember @SinisterSoft was pointing out an issue something about restore function and I thought I fixed that but I can't find any records of that conversation where ever that happened.
  • I am researching also - I realize how busy you are lately. Found 2 very good tutorials so I am going to compare recommendations and the code with the code in your plugin. I also have a source code from a working ios app which was created last July in 2013 and written in objective c - the restore button still work there fine. I hired someone to create that app for me because I hated objective c from a first sight (is there such a thing as "hate from a first sight"? ;)

    Problem is they say that the most difficult part is configuration of the products and getting product identifiers back from a market. But my app already does that just fine and I can make a purchase just fine.

    http://troybrant.net/blog/2010/01/in-app-purchases-a-full-walkthrough/

    http://www.cocoanetics.com/2010/02/things-i-learned-implementing-my-first-inapppurchase/

  • yay!!! I found the issue - apparently all transactions need to be finished regardless of the transaction state. Otherwise they will sit in payment queue even when app is killed/rerun. So once i did that, all 3 issues I described above went away! I have tested this from scratch using brand new sandbox account and both the initial purchase and restore work great now.

    http://stackoverflow.com/questions/14740512/multiple-skpaymenttransaction

    Basically I modified updatedTransactions method in iabios.mm to call [self finishTransaction:transaction] for every status code and commented the last if.

    I am going to try and propose changes to the source code on github so you can see if you want to accept it, but here is how method looks like after I modified it:
    - (void)paymentQueue:(SKPaymentQueue*)queue updatedTransactions:(NSArray*)transactions
    {
     
    	for (SKPaymentTransaction* transaction in transactions)
    	{
    		SKPaymentTransactionState state = transaction.transactionState;
     
    		if(state == SKPaymentTransactionStateFailed)
            {
    			[self finishTransaction:transaction];
                giab_onPurchaseError([self.iap UTF8String], [transaction.error.localizedDescription UTF8String]);
            }
    		else if(state == SKPaymentTransactionStateRestored || state == SKPaymentTransactionStatePurchased)
    		{
    			[self finishTransaction:transaction];
    			giab_onPurchaseComplete([self.iap UTF8String], [[self.prodKeys objectForKey:transaction.payment.productIdentifier] UTF8String], [[transaction transactionIdentifier] UTF8String]);
    		}
    /*
            if (state == SKPaymentTransactionStatePurchased)
            {
                NSLog(<a href="http://forum.giderosmobile.com/profile/in%20updatedTransactions%20-%20SKPaymentTransactionStatePurchased" rel="nofollow">@in updatedTransactions - SKPaymentTransactionStatePurchased</a>);
                [self finishTransaction:transaction];
            }
    */		
    	}
    }
  • awesome @boriskey
    I've already merged it on Github

    for some reason I remember something similar, but don't remember why it was not fixed here. But all in all, my mistake, sorry ;)
  • no need to apologize, I am glad I was able to figure this out and learn a bit more about ios. Is it a straightforward process to upgrade admob to the latest version? I could see if I can do that myself if you give me some pointers.

    Dislikes: unlying

    +1 -1 (+0 / -1 )Share on Facebook
  • sure, it usually goes as
    Delete contents of /Plugins/Ads/frameworks/Admob folder in xcode
    Delete contents of /Plugins/Ads/frameworks/Admob folder on file system
    download new Admob SDK,
    copy SDK files to /Plugins/Ads/frameworks/Admob folder
    Add files in xcode
    Try to build
    You might encounter this bug:
    http://blog.giderosmobile.com/post/68378513314/problems-with-xcode-paths-fix
    so fix it

    And then you need to see if there any other errors
    If not, then there were no code changes in sdk and it works as it
    If yes, then need to dive into docs to see what changed and how to reimplement it :)
Sign In or Register to comment.