• Hey! Guest! The 39th GMC Jam will take place between November 26th, 12:00 UTC and November 30th, 12:00 UTC. Why not join in! Click here to find out more!
  • Hello [name]! Thanks for joining the GMC. Before making any posts in the Tech Support forum, can we suggest you read the forum rules? These are simple guidelines that we ask you to follow so that you can get the best help possible for your issue.

Android In App Purchase crash

L

Lerner

Guest
When I try to initialize In App Purchases with the function "iap_activate()", my game crashes ("Game X has stopped"). The IDE also logs lots of Java exceptions (please see below). I swear I have read all the available documentation, and I have searched for the same problem without success.

Here is my code:

Add a product to an existing "products" list (my function "iap_product_add(productId, title, description, price, someCallback)"):

// Store in a map
var productMap = ds_map_create()
ds_map_add(productMap, "id", product)
ds_map_add(productMap, "title", title)
ds_map_add(productMap, "description", description)
ds_map_add(productMap, "price", price)

// Fetch map to the list
ds_list_add(products, productMap)
ds_list_mark_as_map(products, ds_list_size(products) - 1)


Later in the same object, to initialize IAP:

iap_activate(products)

Log (from start of the "BILLING"):
6313 6313 I yoyo : BILLING: Loading services...
6313 6313 I yoyo : BILLING: Attempting to bind to Billing Service
6313 6313 I yoyo : BILLING: Service connected
6313 6313 I yoyo : BILLING: Billing v3 support available
6313 6313 I yoyo : BILLING: Request sku details
6313 6936 I yoyo : BILLING: getSkuDetails() at index 0
6313 6313 I yoyo : BILLING: Request purchase information
6313 6313 E yoyo : BILLING: Base64 decoding failed.
6313 6313 D AndroidRuntime: Shutting down VM
6313 6313 E AndroidRuntime: FATAL EXCEPTION: main
6313 6313 E AndroidRuntime: Process: com.dimitrilerner.tennislovr, PID: 6313
6313 6313 E AndroidRuntime: java.lang.IllegalArgumentException: android.Base64DecoderException: single trailing character at offset 32
6313 6313 E AndroidRuntime: at com.dimitrilerner.tennislovr.RunnerBillingSecurity.generatePublicKey(RunnerBillingSecurity.java:127)
6313 6313 E AndroidRuntime: at com.dimitrilerner.tennislovr.RunnerBillingSecurity.verifyPurchase(RunnerBillingSecurity.java:83)
6313 6313 E AndroidRuntime: at com.dimitrilerner.tennislovr.RunnerBilling$3$1.run(RunnerBilling.java:211)
6313 6313 E AndroidRuntime: at android.os.Handler.handleCallback(Handler.java:739)
6313 6313 E AndroidRuntime: at android.os.Handler.dispatchMessage(Handler.java:95)
6313 6313 E AndroidRuntime: at android.os.Looper.loop(Looper.java:148)
6313 6313 E AndroidRuntime: at android.app.ActivityThread.main(ActivityThread.java:7325)
6313 6313 E AndroidRuntime: at java.lang.reflect.Method.invoke(Native Method)
6313 6313 E AndroidRuntime: at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
6313 6313 E AndroidRuntime: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)
6313 6313 E AndroidRuntime: Caused by: android.Base64DecoderException: single trailing character at offset 32
6313 6313 E AndroidRuntime: at android.Base64.decode(Base64.java:559)
6313 6313 E AndroidRuntime: at android.Base64.decode(Base64.java:474)
6313 6313 E AndroidRuntime: at android.Base64.decode(Base64.java:420)
6313 6313 E AndroidRuntime: at com.dimitrilerner.tennislovr.RunnerBillingSecurity.generatePublicKey(RunnerBillingSecurity.java:114)
6313 6313 E AndroidRuntime: ... 9 more
6313 6355 I yoyo : Retrieving com.dimitrilerner.tennislovr.noads
6313 6355 I yoyo : Restoring com.dimitrilerner.tennislovr.noads to 0
6313 6355 I yoyo : BILLING: Request deferred, store isn't available right now


The GooglePlayServicesExtension is installed. Google Services are enabled, and the INTERNET permission too. No Google Licensing, no other permission. And I don't know if iOS is concerned too.

Also, first time I enabled an IAP, the app worked like a charm and I could test buy an item.

Please help me, what's wrong?

Edit: I didn't test activating Google Licensing. Is it mandatory?
 
Last edited by a moderator:
L

Lerner

Guest
Assuming you have actually specified your licensing key, I suspect this is a knock-on from an issue we've found building the "base" Google Play Services extension the IAP one depends on: https://help.yoyogames.com/hc/en-us/community/posts/115005610967-Google-Play-Services-hangs-on-GMS-2

We'd need you to submit your project to the Helpdesk so we could investigate further.

No, you don't need the licensing extension to do IAP stuff on Google.
Thank you for your reactivity! I have submitted a bug report in the Yoyo Games "Submit a request" form.
 
L

Lerner

Guest
@Dan I don't want to seem too intrusive, but I'm wondering if there is a way to follow the progression of a bug, ala Mantis (I can still access it with an old account). What I fear is that despite I posted the bug in the "Submit a request" and "Report a bug" forms, I don't have any feedback.

This bug is really annoying as I can't publish my games for now, or I will need to remove any IAP and follow a "free&pro apps" strategy.
 

Dan

YoYo Games Staff
YYG Staff
Actually, I've just re-read the first line of your message above. iap_activate() is the wrong function to call on Android anyway - the Google IAPs extension has its own function you need to call instead.

Are you including the IAP extension for Google also and using that?

The crash here might be unrelated to the issue I mention above, and just "simply" that iap_activate() is now unsafe on Android (which I'll now look into - if you could add a link to your project into your Helpdesk ticket, so I could download what you have just now, that would be ideal).

However, even if you are using the Google IAP extension and calling the correct function, you will need the fix I mention and to wait for the new version, I'm afraid.
 

thitz

Member
Actually, I've just re-read the first line of your message above. iap_activate() is the wrong function to call on Android anyway - the Google IAPs extension has its own function you need to call instead.

Are you including the IAP extension for Google also and using that?

The crash here might be unrelated to the issue I mention above, and just "simply" that iap_activate() is now unsafe on Android (which I'll now look into - if you could add a link to your project into your Helpdesk ticket, so I could download what you have just now, that would be ideal).

However, even if you are using the Google IAP extension and calling the correct function, you will need the fix I mention and to wait for the new version, I'm afraid.
Hello, @Dan!
I've got a similar problem using the version of 1.4.1763.
After completing a purchase the game instantly crashes. Suddenly. Not a GMS crash report has been showed. Just "Game has stopped working".
I got a crash report from google play console which says:
Code:
java.lang.IllegalArgumentException: java.security.spec.InvalidKeySpecException: java.lang.RuntimeException: error:0D07209B:asn1 encoding routines:ASN1_get_object:too long
    at com.littlegeegeeinteractive.animal.RunnerBillingSecurity.generatePublicKey(RunnerBillingSecurity.java:123)
    at com.littlegeegeeinteractive.animal.RunnerBillingSecurity.verifyPurchase(RunnerBillingSecurity.java:83)
    at com.littlegeegeeinteractive.animal.RunnerBilling$3$1.run(RunnerBilling.java:218)
    at android.os.Handler.handleCallback(Handler.java:739)
    at android.os.Handler.dispatchMessage(Handler.java:95)
    at android.os.Looper.loop(Looper.java:135)
    at android.app.ActivityThread.main(ActivityThread.java:5753)
    at java.lang.reflect.Method.invoke(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:372)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1405)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1200)
Caused by: java.security.spec.InvalidKeySpecException: java.lang.RuntimeException: error:0D07209B:asn1 encoding routines:ASN1_get_object:too long
    at com.android.org.conscrypt.OpenSSLKey.getPublicKey(OpenSSLKey.java:143)
    at com.android.org.conscrypt.OpenSSLRSAKeyFactory.engineGeneratePublic(OpenSSLRSAKeyFactory.java:47)
    at java.security.KeyFactory.generatePublic(KeyFactory.java:172)
    at com.littlegeegeeinteractive.animal.RunnerBillingSecurity.generatePublicKey(RunnerBillingSecurity.java:116)
    ... 10 more
Caused by: java.lang.RuntimeException: error:0D07209B:asn1 encoding routines:ASN1_get_object:too long
    at com.android.org.conscrypt.NativeCrypto.d2i_PUBKEY(Native Method)
    at com.android.org.conscrypt.OpenSSLKey.getPublicKey(OpenSSLKey.java:141)
    ... 13 more
All of my extensions are up to date. Also my SDK/JDK. The license key from the play store is also the same.
You also said there's a specific function to android instead of iap_activate(). Can you please tell me which function is that?

Can you help me through this please?
Thank you!
 

ZigZag

Member
Actually, I've just re-read the first line of your message above. iap_activate() is the wrong function to call on Android anyway - the Google IAPs extension has its own function you need to call instead.

Are you including the IAP extension for Google also and using that?

The crash here might be unrelated to the issue I mention above, and just "simply" that iap_activate() is now unsafe on Android (which I'll now look into - if you could add a link to your project into your Helpdesk ticket, so I could download what you have just now, that would be ideal).

However, even if you are using the Google IAP extension and calling the correct function, you will need the fix I mention and to wait for the new version, I'm afraid.
Hi Dan

I recently bought GMS2 and got the problem that all my apps crash right away on android as soon as I call the iap_activate() function, you are talking about this not being the correct way of doing this, but what is it then? All official documentation on this are referring to/using iap_activate().

I do not have this issue on GMS 1.4 where everything is working perfectly.

SDK, NDK, extension all are configured and updated correctly, as mentioned the exact same setup is working on GMS 1.4.

Kind regards
 
L

Lerner

Guest
Hi Dan

I recently bought GMS2 and got the problem that all my apps crash right away on android as soon as I call the iap_activate() function, you are talking about this not being the correct way of doing this, but what is it then? All official documentation on this are referring to/using iap_activate().

I do not have this issue on GMS 1.4 where everything is working perfectly.

SDK, NDK, extension all are configured and updated correctly, as mentioned the exact same setup is working on GMS 1.4.

Kind regards
I still have this problem but as Dan said, you should (and I will) wait for the next GameMaker Studio 2 update.
 
S

Syncrom

Guest
Hello, guys !!

I have the same problem. Anybody knows what is the function we must to use instead iap_activate()...

Any example, @Dan?

I am not very good using extensions... I apologize for this.

Ah, I am using GMS 1.4

Thank you.

EDIT ******
=========
I just have downloaded the GooglePlayServicesIAPExtension from the marketplace, and now it seems the iap_activate() works well, because iap_status() = 1 (iap_status_available), so it seems it works well....

But now, the game, not the CODE, but the APK, shows me a message saying that the product is not available...

I am very tired with all this subject... I have spent ONE WEEK with compilations... Today is friday and the app continues without works properly.

Is it so difficult that Yoyo explains the official way to implement inApp's for Android users?

I am thinking about to migrate to Unity 3D.

GMS is very frustrating.

Now, the problem is given by iap_acquire(product, "")
I was tracing the code, and iap_acquire produces an error: The item is not for selling (I translate from Spanish).

But I have the item ACTIVE in the Play Store.

What is happening?
 
Last edited by a moderator:
L

Lerner

Guest
After updating GameMaker Studio to the last IDE (v2.0.6.136) and runtime (v2.0.6.93), always the same problem. This is very exhausting, as I cannot publish my games. :mad:

Code:
05-10 22:27:38.581 21836 21836 I yoyo    : exception while doing license check! invalid license key????java.lang.IllegalArgumentException: com.google.android.vending.licensing.util.Base64DecoderException: single trailing character at offset 32

[...]

05-10 22:27:43.711 21836 21836 I Ads     : Starting ad request.

05-10 22:27:43.751 21836 21836 I yoyo    : BILLING: Service connected

05-10 22:27:43.861 21836 21836 I yoyo    : BILLING: Billing v3 support available

05-10 22:27:43.871 21836 21836 I yoyo    : BILLING: Request sku details

05-10 22:27:43.871 21836 22119 I yoyo    : BILLING: getSkuDetails() at index 0

05-10 22:27:44.071 21836 21836 I yoyo    : onPause

05-10 22:27:44.081 21836 21836 I yoyo    : Pausing the Runner

05-10 22:27:44.081 21836 21836 W yoyo    : AL lib: (EE) dlGetIID: dlsymIID :: SL_IID_VOLUME :: ef205e7c

05-10 22:27:44.131 21836 21836 I yoyo    : onWindowFocusChanged(false|false)

05-10 22:27:44.131 21836 21836 I yoyo    : Setting vis flags to 5894

05-10 22:27:44.131 21836 21836 W yoyo    : AL lib: (EE) dlGetIID: dlsymIID :: SL_IID_VOLUME :: ef205e7c

05-10 22:27:44.141 21836 21836 I yoyo    : BILLING: Request purchase information

05-10 22:27:44.151 21836 21836 E yoyo    : BILLING: Base64 decoding failed.

05-10 22:27:44.161 21836 21836 D AndroidRuntime: Shutting down VM

05-10 22:27:44.191 21836 21836 E AndroidRuntime: FATAL EXCEPTION: main

05-10 22:27:44.191 21836 21836 E AndroidRuntime: Process: com.dimitrilerner.tennislovr, PID: 21836

05-10 22:27:44.191 21836 21836 E AndroidRuntime: java.lang.IllegalArgumentException: java.lang.IllegalArgumentException: bad base-64

05-10 22:27:44.191 21836 21836 E AndroidRuntime:     at com.dimitrilerner.tennislovr.RunnerBillingSecurity.generatePublicKey(RunnerBillingSecurity.java:127)

05-10 22:27:44.191 21836 21836 E AndroidRuntime:     at com.dimitrilerner.tennislovr.RunnerBillingSecurity.verifyPurchase(RunnerBillingSecurity.java:83)

05-10 22:27:44.191 21836 21836 E AndroidRuntime:     at com.dimitrilerner.tennislovr.RunnerBilling$3$1.run(RunnerBilling.java:218)

05-10 22:27:44.191 21836 21836 E AndroidRuntime:     at android.os.Handler.handleCallback(Handler.java:739)

05-10 22:27:44.191 21836 21836 E AndroidRuntime:     at android.os.Handler.dispatchMessage(Handler.java:95)

05-10 22:27:44.191 21836 21836 E AndroidRuntime:     at android.os.Looper.loop(Looper.java:148)

05-10 22:27:44.191 21836 21836 E AndroidRuntime:     at android.app.ActivityThread.main(ActivityThread.java:7325)

05-10 22:27:44.191 21836 21836 E AndroidRuntime:     at java.lang.reflect.Method.invoke(Native Method)

05-10 22:27:44.191 21836 21836 E AndroidRuntime:     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)

05-10 22:27:44.191 21836 21836 E AndroidRuntime:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)

05-10 22:27:44.191 21836 21836 E AndroidRuntime: Caused by: java.lang.IllegalArgumentException: bad base-64

05-10 22:27:44.191 21836 21836 E AndroidRuntime:     at android.util.Base64.decode(Base64.java:161)

05-10 22:27:44.191 21836 21836 E AndroidRuntime:     at android.util.Base64.decode(Base64.java:136)

05-10 22:27:44.191 21836 21836 E AndroidRuntime:     at android.util.Base64.decode(Base64.java:118)

05-10 22:27:44.191 21836 21836 E AndroidRuntime:     at com.dimitrilerner.tennislovr.RunnerBillingSecurity.generatePublicKey(RunnerBillingSecurity.java:114)

05-10 22:27:44.191 21836 21836 E AndroidRuntime:     ... 9 more
I will get in touch again with the helpdesk.

Edit: @Dan, as I submitted my project, I would also like to know if I did a mistake, if this is a bug that is remaining or something else. Thanks.
 

Nettub

Member
I was waiting for the udpate too, and I'm getting the same error :(

Code:
05-11 09:52:25.422 14599 14619 I yoyo    : android.software.leanback = 0
05-11 09:52:25.422 14599 14619 I yoyo    : MANUFACTURER = HUAWEI
05-11 09:52:26.207 14599 14599 I yoyo    : BILLING: Loading services...
05-11 09:52:26.208 14599 14599 I yoyo    : BILLING: Attempting to bind to Billing Service
05-11 09:52:26.233 14599 14599 I yoyo    : BILLING: Service connected
05-11 09:52:26.249 14599 14599 I yoyo    : BILLING: Billing v3 support available
05-11 09:52:26.249 14599 14599 I yoyo    : BILLING: Request sku details
05-11 09:52:26.250 14599 14749 I yoyo    : BILLING: getSkuDetails() at index 0
05-11 09:52:26.295 14599 14599 I yoyo    : BILLING: Request purchase information
05-11 09:52:26.303 14599 14599 E yoyo    : BILLING: Base64 decoding failed.
--------- beginning of crash
05-11 09:52:26.307 14599 14599 E AndroidRuntime: FATAL EXCEPTION: main
05-11 09:52:26.307 14599 14599 E AndroidRuntime: Process: com.XXXXX.XXXXXX, PID: 14599
05-11 09:52:26.307 14599 14599 E AndroidRuntime: java.lang.IllegalArgumentException: java.lang.IllegalArgumentException: bad base-64
05-11 09:52:26.307 14599 14599 E AndroidRuntime:     at com.X.X.RunnerBillingSecurity.generatePublicKey(RunnerBillingSecurity.java:127)
05-11 09:52:26.307 14599 14599 E AndroidRuntime:     at com.X.X.RunnerBillingSecurity.verifyPurchase(RunnerBillingSecurity.java:83)
05-11 09:52:26.307 14599 14599 E AndroidRuntime:     at com.X.X.RunnerBilling$3$1.run(RunnerBilling.java:218)
05-11 09:52:26.307 14599 14599 E AndroidRuntime:     at android.os.Handler.handleCallback(Handler.java:755)
05-11 09:52:26.307 14599 14599 E AndroidRuntime:     at android.os.Handler.dispatchMessage(Handler.java:95)
05-11 09:52:26.307 14599 14599 E AndroidRuntime:     at android.os.Looper.loop(Looper.java:156)
05-11 09:52:26.307 14599 14599 E AndroidRuntime:     at android.app.ActivityThread.main(ActivityThread.java:6523)
05-11 09:52:26.307 14599 14599 E AndroidRuntime:     at java.lang.reflect.Method.invoke(Native Method)
05-11 09:52:26.307 14599 14599 E AndroidRuntime:     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:941)
05-11 09:52:26.307 14599 14599 E AndroidRuntime:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:831)
05-11 09:52:26.307 14599 14599 E AndroidRuntime: Caused by: java.lang.IllegalArgumentException: bad base-64
05-11 09:52:26.307 14599 14599 E AndroidRuntime:     at android.util.Base64.decode(Base64.java:161)
05-11 09:52:26.307 14599 14599 E AndroidRuntime:     at android.util.Base64.decode(Base64.java:136)
05-11 09:52:26.307 14599 14599 E AndroidRuntime:     at android.util.Base64.decode(Base64.java:118)
05-11 09:52:26.307 14599 14599 E AndroidRuntime:     at com.X.X.RunnerBillingSecurity.generatePublicKey(RunnerBillingSecurity.java:114)
05-11 09:52:26.307 14599 14599 E AndroidRuntime:     ... 9 more
 
L

Lerner

Guest
No feedback at this moment. The issue on the helpdesk is still labelled "Open".
 
L

Lerner

Guest
To those like @ZigZag, @Syncrom, @thitz and @Nettub who cannot work with IAP on Android, I have tweaked the RunnerBillingSecurity.java file located in (your project directory)\extensions\GooglePlayServicesIAPExtension\AndroidSource\Java. Replace the content with this will bypass the YoYo Games billing security that makes my games crash:

Code:
package ${YYAndroidPackageName};

import android.util.Base64;


import com.yoyogames.runner.RunnerJNILib;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.text.TextUtils;
import android.util.Log;

import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Signature;
import java.security.SignatureException;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.X509EncodedKeySpec;
import java.util.ArrayList;
import java.util.HashSet;

/**
 * Security-related methods. For a secure implementation, all of this code
 * should be implemented on a server that communicates with the
 * application on the device. For the sake of simplicity and clarity of this
 * example, this code is included here and is executed on the device. If you
 * must verify the purchases on the phone, you should obfuscate this code to
 * make it harder for an attacker to replace the code with stubs that treat all
 * purchases as verified.
 */
public class RunnerBillingSecurity 
{
    private static final String KEY_FACTORY_ALGORITHM = "RSA";
    private static final String SIGNATURE_ALGORITHM = "SHA1withRSA";
    private static final SecureRandom RANDOM = new SecureRandom();
   
    /**
     * This keeps track of the nonces that we generated and sent to the
     * server.  We need to keep track of these until we get back the purchase
     * state and send a confirmation message back to Android Market. If we are
     * killed and lose this list of nonces, it is not fatal. Android Market will
     * send us a new "notify" message and we will re-generate a new nonce.
     * This has to be "static" so that the {@link BillingReceiver} can
     * check if a nonce exists.
     */
    private static HashSet<Long> sKnownNonces = new HashSet<Long>();    

    /** Generates a nonce (a random number used once). */
    public static long generateNonce() 
    {
        long nonce = RANDOM.nextLong();
        sKnownNonces.add(nonce);
        return nonce;
    }

    public static void removeNonce(long nonce) 
    {
        sKnownNonces.remove(nonce);
    }

    public static boolean isNonceKnown(long nonce) 
    {
        return sKnownNonces.contains(nonce);
    }


    public static boolean verifyPurchase(String signedData, String signature) {       
        // YoYo Games implementation crashes the game, so no verification for now
        return true;
    }
       
    /**
     * Runs a private algorithm to generate our public key from 
     *  a previously encoded string
     */
    public static String getBase64EncodedPublicKey() {
   
        return RunnerActivity.BASE64_PUBLIC_KEY;
    }

    /**
     * Verifies that the signature from the server matches the computed
     * signature on the data.  Returns true if the data is correctly signed.
     *
     * @param publicKey public key associated with the developer account
     * @param signedData signed data from server
     * @param signature server signature
     * @return true if the data and signature match
     */
    public static boolean verify(PublicKey publicKey, String signedData, String signature) 
    {
        // YoYo Games implementation crashes the game, so no verification for now
        return true;
    }
}
Now the game does not crash and product details can be restored, but buying a product does not work for now (this time the problem may be on my side)...
 
L

Lerner

Guest
Thx Lerner!, Looks like my IAP is working again :) , don't know how important are this "security" code
The code prevents people to easily tweak with IAP at a basic level (the downside of my patch is that there is no more protection).
 
L

Lerner

Guest
The code prevents people to easily tweak with IAP at a basic level (the downside of my patch is that there is no more protection).
@Nettub Have you tried to buy something in your app? In other words, does iap_acquire() works for you?
 
L

Lerner

Guest
It works thanks to the guide, so a big thank you @Nettub! I realize it was a mix of code errors / experimentation and a crash due to a bug.
 
L

Lerner

Guest
No advancement? I am very disappointed, GMS2 seems very capable but these bugs are very un-pro for a program I paid 450€ more than the free one that does 3D... :mad::mad::mad:

I don't want to quit what I believe to be an excellent program, but the silence is speaking for itself.

Edit: 3 months and no progress, then other bugs. That makes me angry.
 

rwkay

YoYo Games Staff
YYG Staff
As far as I am aware iap is working fine on all platforms, can you please point me at the bugs you are experiencing and I will go and chase QA to work out what has happened and why things are in limbo

Russell
 
L

Lerner

Guest
As far as I am aware iap is working fine on all platforms, can you please point me at the bugs you are experiencing and I will go and chase QA to work out what has happened and why things are in limbo

Russell
As far as I am aware iap is working fine on all platforms, can you please point me at the bugs you are experiencing and I will go and chase QA to work out what has happened and why things are in limbo

Russell
Hello Russell,

Here is my thread on the help desk: https://help.yoyogames.com/hc/en-us...gest=2a37587c3a2ed44dc2a515b274edbb2255a78094. Ignore the first post that brings a misused example, what I (and others apparently) am experiencing is that RunnerBillingSecurity.java works only for me if I bypass the security, else it crashes (see logs and the RunnerBillingSecurity.java present in the attachments of the helpdesk thread).
 

turra

Member
I just came across this, android IAPs seem like a right pain! Modifying RunnerBillingSecurity.java seemed to do the trick, thanks!
 
L

Lerner

Guest
Does anyone have IAP working without modifying RunnerBillingSecurity.java? I am having the same problem as the OP.
You could file a bug report too. This way, it could give more data to YoYo Games to fix this problem.
 

DireMind

Member
Hi Lerner. Thanks for responding. I'm not sure if I have IAP for GMS2 set up properly. In GMS1.4 there was an IAP tab for entering your GooglePlayPublicKey. In GMS2 the only place I can find to enter the public key is in the Google Licensing area. Do I need Google Licensing enabled?
When I run iap_activate() I can retrieve the pricing information for the products I have set up but the app crashes instantly. I get the same "BILLING: Base64 decoding failed” message which makes me wonder if I have the GooglePlayPublicKey entered properly. The first test account purchase I made worked but now every time I run iap_activate() it crashes.

I have the GooglePlayServicesExtension and GooglePlayServicesIAPExtension installed. The ones that say "Download for 1.4" There is no "Download for 2" so I just used 1.4 extensions.

Still stuck on this. I'll submit a bug report when I'm sure I've got it right on my end.
 
L

Lerner

Guest
Hi Lerner. Thanks for responding. I'm not sure if I have IAP for GMS2 set up properly. In GMS1.4 there was an IAP tab for entering your GooglePlayPublicKey. In GMS2 the only place I can find to enter the public key is in the Google Licensing area. Do I need Google Licensing enabled?
When I run iap_activate() I can retrieve the pricing information for the products I have set up but the app crashes instantly. I get the same "BILLING: Base64 decoding failed” message which makes me wonder if I have the GooglePlayPublicKey entered properly. The first test account purchase I made worked but now every time I run iap_activate() it crashes.

I have the GooglePlayServicesExtension and GooglePlayServicesIAPExtension installed. The ones that say "Download for 1.4" There is no "Download for 2" so I just used 1.4 extensions.

Still stuck on this. I'll submit a bug report when I'm sure I've got it right on my end.
IIRC:
  • Google Licensing is not mandatory, neither directly related to IAPs.
  • I confirm I use the GM:S 1.4 extensions.
iap_activate() crashed without the workaround I have created. Use the file I have given above to make it not crash again. It skips some (basic) security verification, hence making the extension work at the expense of (a bit) less hack-proof IAPs.
 

DireMind

Member
After extensive testing I've discovered that IAP in GMS2 works but only WITH the Google Play Licensing Extension installed and your GooglePlayPublicKey entered in the licensing section with enable licensing turned on. Turn it off and your app will crash as soon as your app calls iap_activate().

Basically if you want to use Android IAPs without the workaround you have to use Google Licensing. I don't want to do this as it means a user has to be online to use the app.

I have a feeling that this is not a bug but rather a missing feature. There is no where to enter your GooglePlayPublicKey except in the licensing section. And no way to tell your app to use the PublicKey without activating licensing. by comparison GMS 1.4 has two places to enter the PublicKey. A tab for licensing AND a tab for IAP.
 

chirpy

Member
Hi, I'm not sure what I did right, but I seem to be able to use Android IAP without crashing at iap_activate. 1.4 extension, no modification to RunnerBillingSecurity.java (I'm not 100% sure because I'm using another ad-related extension, but it certainly did not claim to do so), and no Google Licensing extension nor public key setup. The only ID from Google Play Console that I entered to GM:S2 was "Google Services Id" in Game Options - Android - Social.

PC, GM:S2, IDE v2.1.0.207 Runtime v2.1.0.135
 
Last edited:

DireMind

Member
Hi Chirpy, thanks for the detailed information. It's good to see that you have it working. I'm going to take another look at how I have it set up. Thanks again!
 

DireMind

Member
I tried setting up IAP just as Chirpy did. Did not work. I still get the same error. I created a new apk and uploaded it to Google Play and got the "Unfortunately, 'Your App' has stopped." message as soon as I called iap_activate(). Error message looks like this. I have a game ready to publish so this is very frustrating.

: BILLING: Loading services...
: BILLING: Attempting to bind to Billing Service
: BILLING: Service connected
: BILLING: Billing v3 support available
: BILLING: Request sku details
: BILLING: getSkuDetails() at index 0
: BILLING: Request purchase information
: BILLING: Base64 decoding failed.
: Shutting down VM
: FATAL EXCEPTION: main

Unfortunately, 'Your App' has stopped.
 

chirpy

Member
@DireMind
Sorry that it still didn't work for you. Is it on a physical device with YYC build? By the way you don't need to upload to Google Play every time; just make sure you're using the same keystore file it should be ok.

I'm still struggling to retrieve product list info from the store; thought it was because it takes time to enable the products but after a day it still doesn't return anything when I called iap_enumerate_products. If anyone had tips I'd really appreciate that.
 

chirpy

Member
Thanks to @Lerner and @Nettub
I re-read this thread a couple of more times and realized you were able to iap_acquire following the old and only example, and finally spotted the stupid error in my product ds_list creation. Somehow I had not been adding my products to the list, but to some constant integer as the list id ( ds_list_add(0, product); ... wtf ), and therefore was always really using a 0-length list.
 

DireMind

Member
I thought I had it solved by using a new phone and test account but as soon as I completed a test purchase it's gone back to crashing.

@chirpy
Thanks for the help so far. Just a quick question. Have you tried completing a test purchase? Both test accounts I have started crashing after one test purchase.
 
Last edited:

chirpy

Member
@DireMind
Thanks for sharing. I was using my developer account yesterday so didn't get past the popup, and now .. yes it crashed with the same exception as you all mentioned. Immediately after the purchase was completed.

IDE v2.1.0.212 RT v2.1.0.136

java.lang.IllegalArgumentException: java.lang.IllegalArgumentException: bad base-64

By the way, I also had the issue @Syncrom mentioned of "item not available" on a test device I had access to. For me it was caused by having 2 google accounts on the same device, so it's always sending billing requests from the main=owner account and not my test account. Since Google supports no actual switching of paying account, I ended up using an older device of mine to test with the test account as main=owner.

[Edit]
Bypassing signature verification using @Lerner's modified RunnerBillingSecurity worked for me. I also tried replacing return value of getBase64EncodedPublicKey() with my public key hardcoded, and the verification will pass without enabling Google Licensing, no crashes. I have no idea whether this is just as good as @Lerner's workaround, commenting out the body of verifyPurchase so it always return true.

/**
* Runs a private algorithm to generate our public key from
* a previously encoded string
*/
public static String getBase64EncodedPublicKey() {
return "My public key from Google Play Console";
//return RunnerActivity.BASE64_PUBLIC_KEY;
}

Before the modification it seems to be returning "${YYAndroidGoogleLicensingPublicKey}".
 
Last edited:

DireMind

Member
@chirpy
Ah that's to bad that it crashes. It looks like @Lerner or your workaround is the only way to get it to work without using licensing. Thanks for your detailed posts by the way. It's much appreciated. I would like to hear from YoYo on this. This is a serious bug. @Lerner discovered and reported this 5 months ago and it still hasn't been fixed and requires a workaround. I really don't have the patience to wait another 5 months for this to be fixed.
 

chirpy

Member
@DireMind
Thanks for your info as well! Helped me understand what's that verification and exception about.
From the earliest logs it seems that @Lerner had a different issue than ours at the moment;
only since May @Nettub's log showed the same "bad base-64" exception.
And the helpdesk thread they discussed in June disappeared so I had no idea what happened.
I filed another bug report anyway (is it done via https://account.yoyogames.com/report-bug ?).

I can't say it's not disheartening, but I trust YYG only overlooked the use of public key when Google Licensing is not enabled,
as they're busy developing the Mac IDE.

Some more refs about the use of public key string from Google:
https://developer.android.com/google/play/billing/billing_integrate.html#billing-security
"The Base64-encoded RSA public key that is generated by Google Play is in binary encoded, X.509 subjectPublicKeyInfo DER SEQUENCE format."
"It is the same public key that is used with Google Play licensing."

https://developer.android.com/google/play/billing/billing_best_practices.html
"Validate on a device"
"If you cannot run your own server, you can still validate purchase details within your Android app."
"Warning: This form of verification isn't truly secure. Because your purchase verification logic is bundled within your app, this logic becomes compromised if your app is reverse-engineered."

My conclusion:
Enabling Google Licensing seems to be the legit alternative but it's also most limiting to users, if you're not mainly targeting Google Play Store + online ads.
Bypassing the verification doesn't really hurt either since hardcoding without obfuscation seems quite insecure.

I don't know whether we can obfuscate the extension code; I'd love to know how, but having some time wasted in Android IAP I think I'd better move on to other things..
 

DireMind

Member
@chirpy
Yes, I think you can submit a bug report that way. I used the submit bug option from within GMS 2 but I think it's the same thing. YYG just responded to my bug report asking for more info. I pointed them to this thread and and let them know about your bug report as well. Hopefully we can get this resolved. In the meantime at least we have some workaround options to consider.
 
L

Lerner

Guest
Bug continues for me, so I contacted YoYo Games again. I will keep using my fix.
 

Mool

Member
Same here please fix it. I have many acive users who cant play my game after a purchase. I will use GM-S1 now (hope it works)
 

DireMind

Member
Anyone have any updates on this situation? I'm going to install the latest version of Unity and prepare for a possible move to that engine. I really don't want to make the switch as I like Game Maker 2 but forcing apps to use Google Licensing to enable IAP and YYG silence on this situation is becoming a deal breaker. By the way Google themselves recommend using licensing only for paid apps not free apps.
 
L

Lerner

Guest
Anyone have any updates on this situation? I'm going to install the latest version of Unity and prepare for a possible move to that engine. I really don't want to make the switch as I like Game Maker 2 but forcing apps to use Google Licensing to enable IAP and YYG silence on this situation is becoming a deal breaker. By the way Google themselves recommend using licensing only for paid apps not free apps.
That's what I am doing now. Lost 500$.
 
Top