Restore purchase (DEF-2738) SOLVED

I try to finish purchase on ios and it works good (restore and repeat of purchase)
And now I have next unsolved questions:

  1. Did I make everything right on android (I shouldn’t finish() purchaise)?
  1. The purchase will not be canceled if i did not use finish() (android has only consume() method and has no method for confirm purchaise)?

  2. What can I do with purchases that user already bouth, but not finished on ios (problem on video)? (I made it by mistake, but it posible after crash or some connection problem)

Yes. Do not call iap.finish() for non-consumable purchases. Google will keep track of this purchase for you. Every time you call iap.set_listener() or iap.restore() you’ll get a callback with any purchase that hasn’t been finished.

As far as I know the purchase will not be canceled by Google. This is supported by the official documentation: https://developer.android.com/google/play/billing/api.html#consume

On iOS (and Android) you should get a callback to the iap.set_listener() function for every product that you haven’t called iap.finish() for. Aren’t you getting a callback? It works in my test app.

1 Like
  1. Done!
  2. Done!
  3. No, I did not receive callback to the iap.set_listener on ios if I did not finish() purchase (on android all good).

Strange. Which iOS version and device are you testing on? Let me double check with my test app.

it is iPad 4 with 10.3.2 ios version

Works in my test app. I’m actually getting multiple callbacks. Once for every time I’ve tried to buy the product (same transaction.trans_ident though).

I receive Purchasing state of transaction and that all

The same code works good on android, and on ios (if purchase was finished) too. But doesn’t work if I did not finish() a purchase.
Now I have 2 sandbox accounts where I cant buy or restore anything.

You mean that you’re getting the purchasing state as a result of the iap.buy() call and then nothing at all for iap.set_listener() (not even when the app is restarted and iap.set_listener is called again)?

It looks like (you can see it on video starting point 3):

  • buy non-consumable product without finish();
  • reinstall app;
  • try to buy this item and receive Purchasing callback;
  • tap buy and ok in ios windows (last is “already bought”);
  • and have no any other messages (in my case it is spin screen without callback), I checked it using DefCon and print in first line of callback (before all conditions).

I can restart an app and repeat all this points and receive the same result.

Google billing API has getPurchaseHistory() method.
https://developer.android.com/google/play/billing/billing_reference.html#getPurchaseHistory

I guess in the engine it’s not used and getPurchases() is used instead.

I’m unable to reproduce this. On an iPhone 5s (iOS 8.3!):

  • Create non-consumable product in iTunes Connect
  • Set auto_finish_transactions to false
  • Install app and run app the first time:
  • Call iap.set_listener()
  • Buy product using iap.buy()
  • Don’t call iap.finish()
  • Uninstall app
  • Install app and run it again:
  • Call iap.set_listener() -> I get a callback as expected!
  • Reinstall any number of times shows the same behavior.

I will try on another phone with a newer iOS version. Which iOS version are you testing on?

Works the same on an iPhone 6(7?) Plus with iOS 10.0.2.

1 Like

Did you call just iap.set_listener() ? Without buing product one more time?

Yes, I’m calling iap.set_listener() in the init function of a gui_script. I do not try to buy the product again. Calling iap.set_listener() should trigger a callback of any purchase that hasn’t been finished in a previous run of the application.

1 Like

From Apple docs:

Finishing a transaction tells StoreKit that you’ve completed everything needed for the purchase. Unfinished transactions remain in the queue until they’re finished, and the transaction queue observer is called every time your app is launched so your app can finish the transactions. Your app needs to finish every transaction, regardless of whether the transaction succeeded or failed.

The restore process does not return a product if it has an unfinished transaction in the payment queue.

If you don’t finish Apple’s transactions, it will mess up things.

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

It works!!! :joy: Thank you!!!

As you can see on my sad example current manual doesn’t help with non-consumable purchase at all.
I think it need to make some changes about it in manual:

  • different way of restore purchaise (TRANS_STATE_PURCHASED only on ios even if iap.restore recive true on android) - is it still right behavior?;
  • no need to finish transaction on android if user want non-consumable item (But still need on ios);
  • if purchase was not finished ios will call callback on start of the app for continue purchase;
  • have no callback on ios if you try to buy non-consumable product one more time (but has this callback on android).

This is confusing when I saw that it works the same way on ios and android with consumable purchases. When I try to use non-consumable and has many difference.

I really happy that it was not an engine bug.
And I hope that my pain will help to some developers in future =)))

3 Likes

And one more question about this theme:
Do you have plans to implement callback when purchase was refunded?

Yes, this is a bit unfortunate, but I believe it’s likely caused by the fact that we do not have any non-consumable items in our King games. I will see what we can do to improve the documentation.

Yes, I believe this is an oversight on our part. I would expect a callback to be invoked in this case. I’ll look into it.

1 Like

@sicher this looks like @AGulev may want to contribute to our IAP manual =] I bet if it is not clear for him, then other Defold users will be unhappy as well.

4 Likes