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?
@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)
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?
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.
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?
"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.
@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
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
@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.
@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).
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 ?
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:
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?
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 inpairs(e)doprint(k,v)endend
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.
@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.
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 andthen 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
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.
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.
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:
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.
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
Comments
Always used the developer account attached to Developer console, not the main account used for business
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.
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
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?
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!
http://developer.android.com/google/play/billing/billing_testing.html
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?
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
"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?
https://deluxepixel.com
May be somebody already has a build of Gideros with embeded v3 In-app? Using one more plugin for EVERY app is annoying.
@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
https://deluxepixel.com
Google Play is becoming a hostil platform for indie developers ... downloads and time for integrating its APIs.
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
really need the help, thanks
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.
So maybe something has changed? Are you testing it on ios8?
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.
{__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?
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:
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.
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
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:
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.
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.
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.
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/
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:
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
Dislikes: unlying
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