j3k0 / cordova-plugin-purchase

In-App Purchase for Cordova on iOS, Android and Windows
https://purchase.cordova.fovea.cc
1.29k stars 529 forks source link

Initialize function never resolves on Android in case of errors #1507

Closed fabian-meisinger closed 3 months ago

fabian-meisinger commented 5 months ago

Observed behavior

Errors within the store.initialize function on Android never resolve or reject the returned Promise (e.g. when using an emulator without a logged in account). The error also does not get logged when debug logging is active and only is shown when a listener is registered via store.error.

        store.error((error) => {
            console.error('Store error', error);
        });
        try {
            console.log('Initializing store');
            await store.initialize(platforms);
            console.log('Initialized store');
        } catch (err) {
            console.warn('Failed to initialize store', err);
        }
Initializing store
[CdvPurchase] INFO: initialize()
[CdvPurchase.Adapters] INFO: Adding platforms: [{"platform":"android-playstore"}]
[CdvPurchase.Adapters] INFO: 
[CdvPurchase.Adapters] INFO: GooglePlay initializing...
[CdvPurchase.GooglePlay] INFO: Initialize
[CdvPurchase.GooglePlay.Bridge] INFO: setup ok
[CdvPurchase.GooglePlay.Bridge] INFO: listener: {"type":"ready","data":{}}
[CdvPurchase] DEBUG: Calling callback: type=error() name=
Store error {isError: true, code: 6777001, message: 'Init failed - Setup failed. BILLING_UNAVAILABLE: G…le Play In-app Billing API version is less than 3', platform: 'android-playstore', productId: null}code: 6777001isError: truemessage: "Init failed - Setup failed. BILLING_UNAVAILABLE: Google Play In-app Billing API version is less than 3"platform: "android-playstore"productId: null
[CdvPurchase.GooglePlay] INFO: Initialize

Internally the iabError function also calls initialize again, which writes to the log and then immediately exits, because the initializationPromise is still set.

In addition when store.initialize is called again after the first failed attempt (e.g. after a hot reload), it succeeds because the initializedHasBeenCalled flag is already set to true, even though the store is not really initialized.

Expected behavior

The initialize function should reject the promise and pass the error. On subsequent calls it should also return the original Promise in case initialization is still in progress.

I also didn't notice the store.error listener until after I debugged the problem, because I expected all listeners to be available on store.when(), so maybe you could add an alias there for better consistency.

System Info

   Capacitor Doctor   

Latest Dependencies:

  @capacitor/cli: 5.5.1
  @capacitor/core: 5.5.1
  @capacitor/android: 5.5.1
  @capacitor/ios: 5.5.1

Installed Dependencies:

  @capacitor/android: 5.3.0
  @capacitor/ios: 5.3.0
  @capacitor/cli: 5.5.1
  @capacitor/core: 5.3.0

[success] Android looking great! 👌
francoisduchemin commented 5 months ago

I have noticed the exact same problem today. If the user is not logged in into the Google Playstore, the following error is thrown: "Init failed - Setup failed. BILLING_UNAVAILABLE: Google Play In-app Billing API version is less than 3" but the the initialize function never resolves:

await CdvPurchase.store.initialize([platform]);
kuimoani commented 5 months ago

I encountered the same error, but it is now resolved after log-in into the Google Play Store and updating it on the emulator.