React-native-iap: Cannot get array of products / subscriptions

Created on 19 Aug 2019  ·  31Comments  ·  Source: dooboolab/react-native-iap

Version of react-native-iap

3.3.9

Version of react-native

0.59.9

Platforms you faced the error (IOS or Android or both?)

iOS and Android

Expected behavior

I expect to be able to get an array of products and subscriptions created in Play console and Appstore.

Actual behavior

Functions RNIap.getProducts and RNIap.getSubscriptions always return empty arrays.

Tested environment (Emulator? Real Device?)

iOS simulator, Android emulator and Android real device

Steps to reproduce the behavior

  1. Add products in Google Play Console and Apple Appstore Connect
  2. I used the code from example folder
  3. I changed products / subscriptions ids

I did wait for more than 24 hours. I also created Internal and Alpha release in Google Play Console, but I still get only empty arrays back.

I guess I am a bit unclear on when exactly should I expect it to start working. For example when my Alpha testing Roll out is still Pending publication in Google Play Console, does that mean that react-native-iap won't work? Do I have to wait until the app is published to try it out?

Also I know that I won't be able to make even test purchases on simulator / emulator, but should getProducts / getSubscriptions work on emulators or do I need real device to test it?

const itemSkus = Platform.select({
    ios: ['product_1'],
    android: ['1', '2']
});

const itemSubs = Platform.select({
    ios: ['subscription_1'],
    android: ['subscription_1', 'subscription_2']
});

let purchaseUpdateSubscription;
let purchaseErrorSubscription;

class App extends Component {
    constructor(props) {
        super(props);

        this.state = {
            productList: [],
            receipt: '',
            availableItemsMessage: ''
        };
    }

    async componentDidMount() {
        SplashScreen.hide();
        try {
            const result = await RNIap.initConnection();
            await RNIap.consumeAllItemsAndroid();
            console.log('result', result);
        } catch (err) {
            console.warn(err.code, err.message);
        }

        purchaseUpdateSubscription = purchaseUpdatedListener(async purchase => {
            console.log('purchaseUpdatedListener', purchase);
            if (purchase.purchaseStateAndroid === 1 && !purchase.isAcknowledgedAndroid) {
                try {
                    const ackResult = await acknowledgePurchaseAndroid(purchase.purchaseToken);
                    console.log('ackResult', ackResult);
                } catch (ackErr) {
                    console.warn('ackErr', ackErr);
                }
            }
            this.setState({ receipt: purchase.transactionReceipt }, () => this.goNext());
        });

        purchaseErrorSubscription = purchaseErrorListener(error => {
            console.log('purchaseErrorListener', error);
            Alert.alert('purchase error', JSON.stringify(error));
        });
    }

    componentWillMount() {
        if (purchaseUpdateSubscription) {
            purchaseUpdateSubscription.remove();
            purchaseUpdateSubscription = null;
        }
        if (purchaseErrorSubscription) {
            purchaseErrorSubscription.remove();
            purchaseErrorSubscription = null;
        }
    }

    goNext = () => {
        Alert.alert('Receipt', this.state.receipt);
    };

    getItems = async () => {
        try {
            const products = await RNIap.getProducts(itemSkus);            
            console.log('Products', products);
            this.setState({ productList: products });
        } catch (err) {
            console.warn(err.code, err.message);
        }
    };

    getSubscriptions = async () => {
        try {
            const products = await RNIap.getSubscriptions(itemSubs);
            console.log('Products', products);
            this.setState({ productList: products });
        } catch (err) {
            console.warn(err.code, err.message);
        }
    };

    getAvailablePurchases = async () => {
        try {
            console.info('Get available purchases (non-consumable or unconsumed consumable)');
            const purchases = await RNIap.getAvailablePurchases();
            console.info('Available purchases :: ', purchases);
            if (purchases && purchases.length > 0) {
                this.setState({
                    availableItemsMessage: `Got ${purchases.length} items.`,
                    receipt: purchases[0].transactionReceipt
                });
            }
        } catch (err) {
            console.warn(err.code, err.message);
            Alert.alert(err.message);
        }
    };

    requestPurchase = async sku => {
        try {
            RNIap.requestPurchase(sku);
        } catch (err) {
            console.warn(err.code, err.message);
        }
    };

    requestSubscription = async sku => {
        try {
            RNIap.requestSubscription(sku);
        } catch (err) {
            Alert.alert(err.message);
        }
    };

    render() {
        const { productList, receipt, availableItemsMessage } = this.state;
        const receipt100 = receipt.substring(0, 100);

        return (
            <View style={styles.container}>
                <View style={styles.header}>
                    <Text style={styles.headerTxt}>react-native-iap V3</Text>
                </View>
                <View style={styles.content}>
                    <ScrollView style={{ alignSelf: 'stretch' }}>
                        <View style={{ height: 50 }} />
                        <NativeButton
                            onPress={this.getAvailablePurchases}
                            activeOpacity={0.5}
                            style={styles.btn}
                            textStyle={styles.txt}
                        >
                            Get available purchases
                        </NativeButton>

                        <Text style={{ margin: 5, fontSize: 15, alignSelf: 'center' }}>
                            {availableItemsMessage}
                        </Text>

                        <Text style={{ margin: 5, fontSize: 9, alignSelf: 'center' }}>
                            {receipt100}
                        </Text>

                        <NativeButton
                            onPress={() => this.getItems()}
                            activeOpacity={0.5}
                            style={styles.btn}
                            textStyle={styles.txt}
                        >
                            Get Products ({productList.length})
                        </NativeButton>
                        {productList.map((product, i) => {
                            return (
                                <View
                                    key={i}
                                    style={{
                                        flexDirection: 'column'
                                    }}
                                >
                                    <Text
                                        style={{
                                            marginTop: 20,
                                            fontSize: 12,
                                            color: 'black',
                                            minHeight: 100,
                                            alignSelf: 'center',
                                            paddingHorizontal: 20
                                        }}
                                    >
                                        {JSON.stringify(product)}
                                    </Text>
                                    <NativeButton
                                        // onPress={() => this.requestPurchase(product.productId)}
                                        onPress={() => this.requestSubscription(product.productId)}
                                        // onPress={() => this.buyItem(product.productId)}
                                        // onPress={() => this.buySubscribeItem(product.productId)}
                                        activeOpacity={0.5}
                                        style={styles.btn}
                                        textStyle={styles.txt}
                                    >
                                        Request purchase for above product
                                    </NativeButton>
                                </View>
                            );
                        })}
                    </ScrollView>
                </View>
            </View>
        );
    }
}
📱 iOS 🙏 help wanted 🚶🏻 stale 🤖 android

Most helpful comment

Of course.After published by google play store , I will confirm here

UPDATE

After my app has published on Google Play Store, purchases came up and worked. It takes 3 days to approve. Thanks to @jvandenaardweg

UPDATE 2

react-native-iap can work on android emulator , if emulator has google play store support.

All 31 comments

You don't need real device to test in ios for getProducts/getSubscription but not in android. For android you'd need to have real device to purchase.

For google, please go over my guide to resolve your issue.
You do not actually have to publish the app to playstore for testing but you need to upload the signed apk.

I also have this issue, I already created a product in apple and I can not seem to access it.

const itemSkus = Platform.select({
  ios: [
    'product1'
  ],
  android: []
});

RNIap.getProducts(itemSkus).then((products) => {
      console.log(products);  //<< returns empty array
}).catch((error) => console.log(error))

Does it takes time for the product to reflect in your experience?

Agreements, Tax and Banking are all active
"react-native-iap": "^3.4.0",
And the in-app is already in "Ready to Submit" status

@nateblog what kind of product did you create? A subscription or something else?

Also, have you added a localization in App Store Connect for your product/subscription? If so, try adding the localization you have active on your device or simulator. I remember I had some troubles with that before. My simulator and device locale are in English, so i've only added "English (U.S.)" localization for my subscriptions.

@jvandenaardweg - thank you for the response, yes I already added the localization since the in-app status will not be set to "Ready to Submit" if I skip the localization. I set the localization to "English (U.S.)" since the device I am using is using English and yes the product is subscription.

UPDATE

I already make sure I enabled the in-app under capabilities and downgraded the package to 2.4.0 but still the same result . . I am unable to get the products, it just return empty array.

Also I linked the package manually since other posts suggested not to use the react-native link but still the same result. I am using both simulator and real device.

Sorry, it is sorted out now, the issue was the bundle Id in my xcode, i am using the wrong bundle id, it all works now

I had a similar, and I just needed to do the linking process of the library manually. (ios)

I'm having the same issue, not loading any products from Itunes Connect, and I'm not sure where to start looking for a problem. The app is using an old version of RN: 0.43.4. I've tried versions 3.3.7, and 2.5.5 of RN-IAP. Should I be using an older version of the library because I'm on an old version of React-Native?

It seems like a difficult issue to troubleshoot as there are no error messages, just no data.

Sorry, it is sorted out now, the issue was the bundle Id in my xcode, i am using the wrong bundle id, it all works now

Hey, @nateblog! I am facing a similar issue: I get empty arrays for products and subscriptions and I have created 2 subscription items within App Store Connect. Could you please elaborate on what was wrong with your bundle id? I don't think that I am submitting the correct item SKUs because I couldn't find any reference as to how they are constructed or what they are - are they [Bundle Identifier].[ProductId of the purchase item] or just [ProductId of the purchase item]?

Also, I would like to add that I have slightly different Bundle Identifiers for my release and debug schemes:

  • Release - 'domain.appName';
  • Debug - 'domain.appName.dev';
    The in-app purchase items that I have created are related to the production (i.e. release) version of the app. Does that mean that I could not access those items from the dev version of the app?

Any advice would be greatly appreciated.

I had a similar, and I just needed to do the linking process of the library manually. (ios)

You saved my day!

I have integrated the react-native-iap and uploaded my signed apk to beta release on play store and also added one subscription plan. I am trying to get the list of subscription by subscription ID in debug mode which is always returning an empty array. Can I actually test the subscription in debug mode?

@ShridharCodewave i'm facing the same issue. please let me know if you can solve the problem :(

react-native-iap: 3.3.2

I am facing same problem on Android Emulator. I uploaded apk to Google Play Store to Beta Channel and added products.

image

First , connection init then I am trying to fetch products but nothing shows on console.warn
No results in here
No Errors in here

@ismetsezer the whole In App billing for Android won't work in the emulator:

You cannot use the emulator to test Google Play Billing; you must install your application on a device to test Google Play Billing.
https://developer.android.com/google/play/billing/billing_testing

You need a real device for that.

In iOS you can fetch subscription data in the simulator. But you cannot buy it, for that you also need a real device.

For the other comments above: Also make sure the versionName and versionCode in android/app/build.gradle is the same or higher as the one uploaded in Google Play Console.

You also need an active reviewed app in a non-production track, because of the new review policy of Android:

Previously you could test an app by uploading an unpublished "draft" version. This functionality is no longer supported. Instead, you must publish your app to the closed or open testing track. For more information, see Draft Apps are No Longer Supported.
https://developer.android.com/google/play/billing/billing_testing

"Publishing" in a closed/open testing track means it needs to go through Google Play's new review process. Which could take a couple of days for new apps, and just a couple of hours for existing apps.

I don't know the exact steps I did, but for me it's working locally with an Android device. So it's probably not a react-native-iap package issue, but more a configuration thing.

If someone can confirm the above, maybe a good thing to update the README about this change. As this is something new since last month.

Thanks @jvandenaardweg when I switched to real device , Yes It works and connection is successfull but as you said and according to link, I have to wait for test app to published on Beta Channel because products array comes empty

Good to hear @ismetsezer . Can you confirm if it starts working for you with a reviewed/published test app? Because then we can update the readme with that new information :-)

Of course.After published by google play store , I will confirm here

UPDATE

After my app has published on Google Play Store, purchases came up and worked. It takes 3 days to approve. Thanks to @jvandenaardweg

UPDATE 2

react-native-iap can work on android emulator , if emulator has google play store support.

@kesepara I had to wait for few hours after adding the new subscription plan on play store for it to appear on the device.

Hi @ismetsezer and @kesepara ,
I would really appreciate your input about your development flow as something is still not clear to me.
I've set up RN IAP for iOS and it is working fine now.
I'm now starting to do the Android part, and I've found here that we have to use signed APK uploaded on Closed track (at least) to be able to test payment features.
But in your comments you're saying that you've been able to test it on Android emulator, is that correct?
Furthermore, if we have to use signed APK on the store, how can we debug?
Your help would be very much appreciated.

Hi @beeremy thanks for your good opinions . You have to test iap on real device or emulator that has google play support to fetch products. IAP has worked after I published app on Google Play Store , this could be change but at least you have to upload or give a draft on the store to test this feature. But it takes 2 - 3 hours to work.

Hi @ismetsezer , thanks for your feedback.

For whoever it can be useful, I've been able to make a debug config running after following this recommendation: https://stackoverflow.com/questions/36113347/is-it-possible-to-debug-locally-google-plays-in-app-billing-in-android-studio

I can confirm as @ismetsezer that subscriptions and products will work in android after app is published in google play console. Trying to get subscriptions / products when app is not yet published will not work for android.

On iOS subscriptions and products are working without having the app published.

Hey there, it looks like there has been no activity on this issue recently. Has the issue been fixed, or does it still require the community's attention? This issue may be closed if no further activity occurs. You may also label this issue as "For Discussion" or "Good first issue" and I will leave it open. Thank you for your contributions.

RN 0.59.1 on Android dev here and I'm using iap version 4.4.1

My build is currently on the Alpha track. Afterwards, I rebuilt as usual on my machine in debug mode, within the Platform.select({}) I specified the subscription ID as it is on the Play Console, and I called getSubscriptions() but I'm receiving an empty array. Is this because it's in Alpha? Any ideas?

@edgaralienfoe did you activate your subscription in Google Play Console?

@acostalima it should be activated. I assumed maybe it takes a few days for it to do so, but still no luck.

@edgaralienfoe I'm asking because I recall there is an option to explicitly activate a subscription on Google Play Console and, if it is not active, then the subscription will not show up in your app. But, if you say so, there might be some other issue then.

@edgaralienfoe Did you find the solution? Maybe your app version needs to be higher than the one in Alpha track

@edgaralienfoe Did you find the solution? Maybe your app version needs to be higher than the one in Alpha track

Alpha track works just fine. I've been testing IAPs for quite some time now with builds deployed to Alpha without issues. The Internal track, on the other hand, does not work.

For everybody who might run into trouble here, what did the trick on iOS for me was linking the project manually as suggested by @Kuhne1 - it worked after cleaning the build folder and installing Pods manually as well, hope it's useful to anybody!

Hey there, it looks like there has been no activity on this issue recently. Has the issue been fixed, or does it still require the community's attention? This issue may be closed if no further activity occurs. You may also label this issue as "For Discussion" or "Good first issue" and I will leave it open. Thank you for your contributions.

Closing this issue after a prolonged period of inactivity. If this issue is still present in the latest release, please feel free to create a new issue with up-to-date information.

Was this page helpful?
0 / 5 - 0 ratings