Restore purchase (DEF-2738) SOLVED

When I call iap.restore I receive all transaction with state == 1 (TRANS_STATE_PURCHASED )
like:

{
  trans_ident = ,
  receipt = {"packageName":"com.bringmecakes","productId":"booster_hint","purchaseTime":1496001477744,"purchaseState":0,"purchaseToken":"...token..."},
  ident = booster_hint,
  state = 1,
  signature = ...signature...,
  date = 2017-05-28T22:57:57+03:00,
}

I tested few times on android and all time the same result. State all time is 1.
But as I understand it should be 3 (iap.TRANS_STATE_RESTORED). Is it bug?

UPD: As we understood restore purchaise and non consumable iap doesn’t work at all. Pls, look at next post in topic.

In contrast to Apple, Google doesn’t distinguish between purchased and restored products.
So it very well can be considered not a bug by the Defold team. There is a remark in the docs “This is only available on store providers supporting restoring purchases.”

I personally think the restored state could have been removed from the SDK and replaced simply by the purchased state to make the behaviour of the stores more consistent. Or have the two stores API separated into different modules.

Hmmm. The same remark has iap.restore method. And this method returns true on android.

And when I reading documentation it looks like:
if iap.restore returns true then restore purchase is supporting and iap.TRANS_STATE_RESTORED should works too.

I do not agree with “2 different modules”. One module is great!
But would be good to have one behavior (I think it is possible to handle in module) or at least some info in docs about supported platforms:

"iOS/Amazon only, on Android it will be TRANS_STATE_PURCHASED " or something like this.

I made a flag for android is_restore and it works.
Unfortunately my adventure with a restore purchase is not finished(

Now I try to restore purchase on ios. But I have no any callback. Iap listener did not invoked at all when I call iap.restore() =(

If I try to buy something one more time i reciving message “this in-app purchase is already bought” and then nothing… iap listener did not invoke in this situation too…

This should obviously work. BUT it’s a feature that isn’t used in King games (we only have consumable products in our games and those cannot be restored) so there might be an issue with the restore functionality. We do a test of the IAP functionality every release of Defold, but now that I think of it our test app doesn’t include functionality to test iap.restore().

The “this in-app purchase is already bought” usually indicates that the purchase hasn’t been finished yet. If you have “Auto Finish Transactions” checked in game.project it will be automatically consumed by the engine. If it isn’t checked it means that you need to manually call iap.finish().

Could you please verify that the product you are trying to restore is a non-consumable product? Could you please also let me know the state of the Auto Finish Transactions checkbox in game.project?

1 Like

It is non-consumable products and checkbox is off.

Ok, and are you in your code explicitly calling iap.finish()? If you for some reason didn’t call iap.finish() (app crashed or you simply forgot to in your code) then you should get a callback every time you set the IAP listener using iap.set_listener() until you finish the transaction.

1 Like

no (
I forgot to uncomment it after experiments with android restore purchase and so on…
But how I can to finish it now if I have no callback? By auto_finish checkbox?

Ok. I am woken up.
I shouldn’t finish non-consumable products because if I finish it I can’t restore them.
And now I did not called finish() method for my products.
On android it works good, and I can to restore all purchaise (I rechecked using finish() method too, and with finish() I can’t to restore purchaises)

But on iOS I have an issue when callback did not invoked.

Hmm. Ok so on iOS nothing happens when you call iap.restore() and you get no callback in iap.set_listener()?

Could you please provide a step by step description of what you do, what happens, expected behavior and how your app and products are configured?

1 Like

What I want to do:
I want to have non consumable products and possibility to restore them without server.

Just first example with android, when all works fine. I just want to understand that I made all right.

Part 1, Let’s try to understand how it works on Android (and how it should work)

Products configuration:
On Android I have no option to set my product as non-consumable.
I just create new product and activate it.

###Steps how it works

Buy
1.

function M.buy(self, id)
  iap.set_listener(iap_listener)
  iap.buy(id)
end
local function iap_listener(self, transaction, error)
 if transaction.state == iap.TRANS_STATE_PURCHASED then
        msg.post(...)
--no finish!!!
 end
end

Reinstall an apk

Restore
1.

function M.restore_purchases()
    iap.set_listener(iap_listener)
    iap.restore()
end

2 Same code as in Buy part

local function iap_listener(self, transaction, error)
if transaction.state == iap.TRANS_STATE_PURCHASED then
        msg.post(...)
--no finish!!!
end
end

###Steps how it didn’t work:

Buy

  1. Same code for a buy
function M.buy(self, id)
  iap.set_listener(iap_listener)
  iap.buy(id)
end
local function iap_listener(self, transaction, error)
 if transaction.state == iap.TRANS_STATE_PURCHASED then
     msg.post(...)
     iap.finish(transaction)
 end
end

Reinstall an apk

Restore
1.

function M.restore_purchases()
    iap.set_listener(iap_listener)
    iap.restore()
end

2 . iap listener did not invoked at all (I have no non consumed items, because i finish them all)


All right there?

Part 2, iOS issue

Products configuration:

I use the same code as for android.
And buying works good.
But restoring…

When I try to restore using the same code:

function M.restore_purchases()
    iap.set_listener(iap_listener)
    iap.restore()
end

iap_listener do not invoked.

When I try to buy item one more time:


If I tap to ok iap_listener do not invoked. And I don’t know that user finish work with ios interface.

When I try to buy item one more time on Android it just invoke iap_listener with needed transaction and TRANS_STATE_PURCHASED state (as it shoud be, as i think)

Ok, hmm, you might have come across a bug. I’ve created a ticket to investigate further: DEF-2738

1 Like

Any estimates when somebody can look into it?
It’s fun, but “restore purchase” was our last task before soft launch. =)))

Approximately, just for understand what we can say to our potential publishers.

You should be able to implement basic IAP features with native extensions if you want to soft launch without waiting.

Yes, but If it’s not a long term, I can spend this time for next tasks, that we should to do regardless of soft launch results.

Not sure. @Sara, @sven, @Andreas_Tadic?

I can take a look later this week.

1 Like

IAP_TRANS_RESTORED is invoked on platforms supporting it, which I think is only iOS (need to check that) so if the iap.restore true on Android and it doesn’t support restoring items, it’s a bug. I would need to investigate the code to give correct answers, but it does seem like a bug.
And to be clear, the IAP_TRANS_RESTORED can only be invoked on platforms supporting restoring items since one need to know what item was restored (which is not possible otherwise).

2 Likes

But Android is supporting restore purchase for non-consumable products (products that you did not consume using consumePurchase). And iap.restore should work on android too.

What do you think about second part of issue this and this.

Ok, I misread and thought you meant it was an error it returing true on iap.restore on Android. Ok, so that’s good.
Regarding the rest, I won’t personally have time to look into this straight away.
It does seem like a bug but before reporting it, it would need to be investigated further.
@saracglaser, @Bjorn_Ritzl maybe you can prioritise this correctly.

1 Like