Jump to content

[TOPIC: topicViewTemplate]
[GLOBAL: userSmallPhoto]
Photo

RuntimeException after purchase(but ok for restore) on Androids
Started by efgames.net Dec 23 2018 01:14 PM

7 replies to this topic
[TOPIC CONTROLS]
[/TOPIC CONTROLS]
[modOptionsDropdown]
[/modOptionsDropdown]
[reputationFilter]
[TOPIC: post.html]
#1

efgames.net

[GLOBAL: userInfoPane.html]
efgames.net
  • Contributor

  • 196 posts
  • Corona SDK

Hey guys,

what to do, how to fix it?

I checked license key - it is ok. Restoring works fine.

I have this error on android after successful purchase:

java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=3, result=-1, data=Intent { (has extras) }} to activity {com.elitegamesltd.royalquest/com.ansca.corona.CoronaActivity}: java.lang.IllegalArgumentException: plugin.google.iap.v3.util.Base64DecoderException: single trailing character at offset 640
at android.app.ActivityThread.deliverResults(ActivityThread.java:4221)
at android.app.ActivityThread.handleSendResult(ActivityThread.java:4264)
at android.app.ActivityThread.-wrap20(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1613)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:163)
at android.app.ActivityThread.main(ActivityThread.java:6383)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:904)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:794)
Caused by: java.lang.IllegalArgumentException: plugin.google.iap.v3.util.Base64DecoderException: single trailing character at offset 640
at plugin.google.iap.v3.util.Security.generatePublicKey(Security.java:112)
at plugin.google.iap.v3.util.Security.verifyPurchase(Security.java:89)
at plugin.google.iap.v3.util.IabHelper.handleActivityResult(IabHelper.java:500)
at plugin.google.iap.v3.LuaLoader$5.onHandleActivityResult(LuaLoader.java:327)
at com.ansca.corona.CoronaActivity.onActivityResult(CoronaActivity.java:3406)
at android.app.Activity.dispatchActivityResult(Activity.java:7125)
at android.app.ActivityThread.deliverResults(ActivityThread.java:4217)
... 9 more
Caused by: plugin.google.iap.v3.util.Base64DecoderException: single trailing character at offset 640
at plugin.google.iap.v3.util.Base64.decode(Base64.java:559)
at plugin.google.iap.v3.util.Base64.decode(Base64.java:474)
at plugin.google.iap.v3.util.Base64.decode(Base64.java:420)
at plugin.google.iap.v3.util.Security.generatePublicKey(Security.java:102)
... 15 more

Any ideas what I'm doing wrong?

(same code works fine for my other project).

store = require("plugin.google.iap.v3");

function storeInitHandler(event)
local transaction = event.transaction;
if (transaction.state == "purchased" or transaction.state == "restored") then
local buy_id = transaction.productIdentifier;
buyHandlerCall(buy_id);
end
end
store.init(storeInitHandler);

store.purchase(buy_id);


[TOPIC: post.html]
#2

Rob Miracle

[GLOBAL: userInfoPane.html]
Rob Miracle
  • Moderator

  • 25,154 posts
  • Corona SDK

In Googling the error, it seems that people get that a lot with a bad public key. It's just I don't know where you specify a public key other than your keystore so that doesn't seem to be quite right either. Clearly the error is that a base64 string is a character short, or a character long. 

 

I'll ask engineering but this is the first time this has come up so it sounds like a problem in a setup somewhere.

 

Rob


  • efgames.net likes this

[TOPIC: post.html]
#3

efgames.net

[GLOBAL: userInfoPane.html]
efgames.net
  • Contributor

  • 196 posts
  • Corona SDK

I have found a weird thing: it works without a crash - if items are consumable.

so if I do NOT call store.consumePurchase - it gives this error.

If I call it - it is working fine.

 

Maybe I'm doing something wrong and corona was updated?



[TOPIC: post.html]
#4

Rob Miracle

[GLOBAL: userInfoPane.html]
Rob Miracle
  • Moderator

  • 25,154 posts
  • Corona SDK

Google changed their IAP's a while back. There is no longer a difference between Managed (non-consumable) and Unmanaged (consumable) items. You basically have to call store.consumePurchase() on everything.

 

Rob



[TOPIC: post.html]
#5

efgames.net

[GLOBAL: userInfoPane.html]
efgames.net
  • Contributor

  • 196 posts
  • Corona SDK

Google changed their IAP's a while back. There is no longer a difference between Managed (non-consumable) and Unmanaged (consumable) items. You basically have to call store.consumePurchase() on everything.

 

Rob

No, it is not =) (if the item is not consumable - you should not call consume after buying it).

If an item should be available for purchase again - then you call consume after purchase. Otherways google API will return 'owned'. And currently, it behaving like that. If after the crash - I`ll try to buy again the same item - there will be no error, and the user will get his item without a problem.



[TOPIC: post.html]
#6

Rob Miracle

[GLOBAL: userInfoPane.html]
Rob Miracle
  • Moderator

  • 25,154 posts
  • Corona SDK

Let me re-phrase that. You have to call consumePurchase() if you intend to allow the user to purchase it a second time. There is no difference to Google. They expect you to maintain that:

 

https://developer.android.com/google/play/billing/api

 

There is no distinction in the Google Play Developer console between a consumable vs. non-consumable. They are all considered "Managed products". 

 

If you call store.purchase() on an item that has already been purchased, it should not work until you call store.consumePurchase(). It's up to you to track if it's a one-time purchase or a multi-purchase and call store.consumePurchase() when the item is consumed. Your description above makes it sound like this is what's happening.

 

You're describing calling store.purchase() after calling store.consumePurchase() as working vs. calling store.purcahse() without previously calling store.consumePurchase() crashing. If you hadn't previously successfully called store.purchase() there wouldn't be a reason to call store.consumePurchase() which leads me to believe that you are successfully calling store.purchase() at least once on the items in question which would lead you to the situation you're describing.

 

Rob



[TOPIC: post.html]
#7

efgames.net

[GLOBAL: userInfoPane.html]
efgames.net
  • Contributor

  • 196 posts
  • Corona SDK

No.

Here is my case:

1) I uploaded APK to google store with IAPs.

I tried to buy them - but APK crashed(error in first post).

Simple code - store.purchase() and nothing more.

 

2) Posted here on forum my problem.

 

3) I checked my other games - and they were working fine. This is my first game with a non-consumable IAPs - so I decided to consume them and see if APK would fail. It did not. In order to do that: I refunded my purchases, added store.consumePurchase(), and tested.

 

I dont call store.consumePurchase() before store.purchase().

I have this problem from Sunday - so I had some time to experiment with it - in order to give you more info.

Sorry for my english =)

When I wrote

 

 

No, it is not =)

I meant - what you wrote afterward - store.consumePurchase()  for consumable items, and not calling that method makes them non-consumable.



[TOPIC: post.html]
#8

Trung Kien Tran

[GLOBAL: userInfoPane.html]
Trung Kien Tran
  • Enthusiast

  • 55 posts
  • Corona SDK

Same error with IAP (restore). Please help me!

I think this is a problem from Corona plugin. Previous projects I used similar methods to work well

 

dce1217f58d407f525e7d27b55717d5b.png

Let me re-phrase that. You have to call consumePurchase() if you intend to allow the user to purchase it a second time. There is no difference to Google. They expect you to maintain that:

 

https://developer.android.com/google/play/billing/api

 

There is no distinction in the Google Play Developer console between a consumable vs. non-consumable. They are all considered "Managed products". 

 

If you call store.purchase() on an item that has already been purchased, it should not work until you call store.consumePurchase(). It's up to you to track if it's a one-time purchase or a multi-purchase and call store.consumePurchase() when the item is consumed. Your description above makes it sound like this is what's happening.

 

You're describing calling store.purchase() after calling store.consumePurchase() as working vs. calling store.purcahse() without previously calling store.consumePurchase() crashing. If you hadn't previously successfully called store.purchase() there wouldn't be a reason to call store.consumePurchase() which leads me to believe that you are successfully calling store.purchase() at least once on the items in question which would lead you to the situation you're describing.

 

Rob




[topic_controls]
[/topic_controls]