Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Android - "Billing is unavailable. This may be a problem with your device, or the Play Store may be down." #2573

Open
jsflor opened this issue Oct 6, 2023 · 14 comments

Comments

@jsflor
Copy link

jsflor commented Oct 6, 2023

Please use the Discussion board if you want to get some help. Please use issues to report bugs.

Description

I have got this error Billing is unavailable. This may be a problem with your device, or the Play Store may be down. when using useIAP hook in android app, so getSubscriptions in empty. I have followed all the instructions explained in the documentation, created the subscriptions in play console and my implementation is pretty much the same as in the given example app. Subscriptions in IOS app is working fine. Android app is already publicly available on play store so I tested it on production because I thought it was emulator issue but is not even working on production. Tried on 2 different devices with google account set up.

I expected the connection initiated successfully and subscriptions are not empty
Screenshots

Environment:

  • react-native-iap: 12.10.7
  • react-native: 0.72.3
  • Platforms (iOS, Android, emulator, simulator, device): Android real devices -> SG A54 and Xiaomi Redmi Note 10

To Reproduce
Steps to reproduce the behavior:

  1. Use useIap hook and then initConnection is called
  2. Error 'Billing is unavailable. This may be a problem with your device, or the Play Store may be down.' is throw

[Optional] Additional Context

@Robiullah2244
Copy link

Robiullah2244 commented Oct 6, 2023

I am encountering the same issue. My app is live and has been successfully processing in-app purchases since I checked the app now.

@endyinthesun
Copy link

I have the same issue. Has anyone resolved it?

@jsflor
Copy link
Author

jsflor commented Oct 9, 2023

does anyone have it working on a previous version?

@Sanjaya94
Copy link

does anyone have it working on a previous version?

not in 12.10.5

@nguyenthanhvo06031999
Copy link

Has anyone solved this problem yet?

@Esarhaddon
Copy link

I'm also on react-native version 0.72.3 and I've gotten the latest version of react-native-iap (12.10.8) to work on Android in development, but I'm not using the useIAP hook. Instead I'm manually initializing the connection and setting up the listeners, similar to the first example here: https://react-native-iap.dooboolab.com/docs/guides/purchases. My setup looks something like this (the effect should go in your root component so that it only runs once when your app mounts):

import {
  initConnection,
  purchaseErrorListener,
  purchaseUpdatedListener,
} from "react-native-iap"

// ...

useEffect(() => {
  let purchaseSub
  let errorSub
  initConnection().then(() => {
    purchaseSub = purchaseUpdatedListener((purchase) => {
      // handle purchase
    })
    errorSub = purchaseErrorListener((error) => {
      // handle error
    })
  })
  return () => {
    purchaseSub?.remove()
    errorSub?.remove()
  }
}, [])

However, I'm here because we've started seeing these errors in our logs. In our case it looks like they might be a result of Google's internal testing as we haven't released this version of the app to actual users yet, but it sounds like this might be something we still need to worry about. If you guys try manually setting up the listeners like above do the errors go away?

@Esarhaddon
Copy link

We just verified in BrowserStack with Google Play internal testing that our setup is working.

@renatomserra
Copy link

Also facing this issue in prod with a few users

@Vittor-Javidan
Copy link
Contributor

Vittor-Javidan commented Dec 22, 2023

I'm getting this same issue. "Billing is unavailable. This may be a problem with your device, or the Play Store may be down."

I know my app can connect and disconect, and can recognize the subscription to buy. But when i try to buy, after entering credit card info for example, i receive a message that the payment was refused, and this message erro comes right after.

My app is on open test, if you need to check:
android: https://play.google.com/store/apps/details?id=com.lonewispapps.earthlog
web: https://play.google.com/apps/testing/com.lonewispapps.earthlog

my subscription method on my service class:

  static async buySubscription(o: {
    onError: (errorMessage: string) => void
  }) {
    if (this.userPlan === 'Free') {
      try {
        if (Platform.OS === 'android') {
          const subscription = (await getSubscriptions({ skus: [this.PREMIUM_PLAN_SKU ]}))[0] as SubscriptionAndroid;
          await requestSubscription({
            sku: subscription.productId,
            subscriptionOffers: [{
              sku: subscription.productId,
              offerToken: subscription.subscriptionOfferDetails[0].offerToken,
            }],
          });
        }
      } catch (error) {
        if (error instanceof Error) {
          o.onError(error.message);
        }
      }
    }
  }

My component that calls buySubscription is defined like this:

import React, { memo, useCallback, useEffect, useMemo } from 'react';
import { View } from 'react-native';
import {withIAPContext, useIAP, finishTransaction, Purchase } from 'react-native-iap';

import SubscriptionManager from '@SubscriptionManager';

import { navigate } from '@V1/Globals/NavigationControler';
import ConfigService from '@V1/Services/ConfigService';
import ThemeService from '@V1/Services/ThemeService';

import { Animation } from '@V1/Animation/index';
import { Layout } from '@V1/Layout/index';
import { Button } from '@V1/Button/index';
import { TC } from './__TC__';

export const IAPScreen = withIAPContext(memo(() => {

  const config          = useMemo(() => ConfigService.config, []);
  const theme           = useMemo(() => ThemeService.appThemes[config.appTheme].component, []);

  const {
    currentPurchase,
    currentPurchaseError,
  } = useIAP();

  const buySubscription = useCallback(async () => {
    await SubscriptionManager.buySubscription({
      onError: (errorMessage) => alert(errorMessage),
    });
  }, []);

  const onFinishTransaction = useCallback(async (currentPurchase: Purchase) => {
    await finishTransaction({ purchase: currentPurchase, isConsumable: false });
    navigate('RESTART APP');
  }, []);

  useEffect(() => {
    if (currentPurchaseError?.message) {
      alert(JSON.stringify(currentPurchaseError));
    }
  }, [currentPurchaseError]);

  useEffect(() => {
    if (currentPurchase) {
      onFinishTransaction(currentPurchase);
    }
  }, [currentPurchase]);

  return (
    <Layout.Screen
      screenButtons={
        <TC.ScreenButtons />
      }
    >
      <Animation.SlideFromLeft
        delay={200}
        duration={200}
      >
        <View
          style={{
            padding: 10,
          }}
        >
          <Button.TextWithIcon
            title="Buy subscription"
            iconName="wallet"
            onPress={async () => await buySubscription()}
            theme={{
              font_active: theme.font_active,
              background: theme.background_Button,
              background_active: theme.background_active,
              font: theme.font_Button,
            }}
            style={{
              borderRadius: 10,
            }}
          />
        </View>
      </Animation.SlideFromLeft>
    </Layout.Screen>
  );
}));

I use this hook to connect to the store, which being is used inside the parent component of the component above

export function useAppStoreConnection(o: {
  onFinish: () => void
  onError: (errorMessage: string) => void
}, deps: React.DependencyList) {
  useEffect(() => {

    if (Platform.OS === 'ios') {

      o.onError('Store connection not implemented for IOS');

    } else {

      initConnection().then(() => {
        flushFailedPurchasesCachedAsPendingAndroid().then(() => {
          o.onFinish();
        });
      }).catch(() => {
        o.onError('Could not connect to app store');
      });

      return () => {
        endConnection();
      };
    }
  }, deps);
}

@Hamzii23
Copy link

When you dont have email in your Play Store mean User not login in PlayStore at that time it show error "Billing is unavailable. This may be a problem with your device, or the Play Store may be down."

@Vittor-Javidan
Copy link
Contributor

For me this error was just a hold on my play store account that i needed to solve. Turns out if you have any issue with your account, googles billing will behave like a unreachable service until you fix it, even on test environments.

@kamalkishor1991
Copy link

Many users of this open source app are also facing this issue. I see at least one user facing this issue daily and I don't think that many users will have issue with their play store. Something else is going on here. Users seems to be retrying multiple times after seeing this error.

@Vittor-Javidan
Copy link
Contributor

Vittor-Javidan commented Apr 4, 2024

Well, on my case when I received this error, solving the hold on my account solved the issue. Considering the message comes from google, and not the library (because the lib just pass the error message trough), and considering other issues can bring the same error message, for me looks like google must be the one to blame to not give a good error message to be honest.

Try to use the library in a test app, and give us the feedback of your experience @kamalkishor1991

@kamalkishor1991
Copy link

@Vittor-Javidan thanks for responding. Part of the challenge here is that this error are coming for real users. I am not able to reproduce in any of the device I own.
I will also dig deeper into it by checking out the source code. Can you think of any race condition or prerequisite that might cause this?
If possible can you also point me to relevent code for this one.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

10 participants