hyochan / react-native-iap

In App Purchase module for React Native!
https://react-native-iap.hyo.dev
MIT License
2.86k stars 647 forks source link

Works on Android but iOS return IAP initialization error [Error: E_IAP_NOT_AVAILABLE] #2863

Open PandaDouxYT opened 1 month ago

PandaDouxYT commented 1 month ago

Hello, I'm experiencing a bug today. When I launch my app on Android, I have no problem, the products are displayed correctly and I can buy them. However, on iOS, the products are not displayed and I get the error: ‘IAP initialization error [Error: E_IAP_NOT_AVAILABLE]’. on a real physical device. (i start my app with npx expo start)

Which I've already set up / configured:

xcode iap: image

package.json

{
  "name": "starlegends",
  "version": "2.2.3",
  "scripts": {
...
  },
  "dependencies": {
...
    "react-native-iap": "^12.15.1",
...
  },

app.json

{
  "expo": {
    "name": "StarLegends",
    "slug": "StarLegends",
    "version": "2.2.3",
    "web": {
      "favicon": "./assets/favicon.png"
    },
    "extra": {
      "eas": {
        "projectId": "x"
      }
    },
    "ios": {
      "bundleIdentifier": "com.starlegends"
    },
    "android": {
      "package": "com.starlegends"
    }
  },
  "react-native-google-mobile-ads": {
    "android_app_id": "ca-app-pub-x",
    "ios_app_id": "ca-app-pub-x",
    "skAdNetworkItems": [
      "x.skadnetwork",
      ...
    ]
  }
}

Podfile:

...
platform :ios, podfile_properties['ios.deploymentTarget'] || '13.4'
install! 'cocoapods',
  :deterministic_uuids => false

prepare_react_native_project!

target 'StarLegends' do
  use_expo_modules!

  use_frameworks! :linkage => :static

  config = use_native_modules!

  use_frameworks! :linkage => podfile_properties['ios.useFrameworks'].to_sym if podfile_properties['ios.useFrameworks']
  use_frameworks! :linkage => ENV['USE_FRAMEWORKS'].to_sym if ENV['USE_FRAMEWORKS']

  pod 'RNIap', :path => '../node_modules/react-native-iap'

  use_react_native!(
    :path => config[:reactNativePath],
    :hermes_enabled => podfile_properties['expo.jsEngine'] == nil || podfile_properties['expo.jsEngine'] == 'hermes',
    # An absolute path to your application root.
    :app_path => "#{Pod::Config.instance.installation_root}/..",
    :privacy_file_aggregation_enabled => podfile_properties['apple.privacyManifestAggregationEnabled'] != 'false',
  )
...

my code (for test):

import React, { useEffect, useState } from 'react';
import { View, Text, FlatList, Alert, Pressable, Platform } from 'react-native';
import * as RNIap from 'react-native-iap';

const itemSkus = Platform.select({
    ios: [
        { sku: '160coins', andDangerouslyFinishTransactionAutomaticallyIOS: false },
        { sku: '400coins', andDangerouslyFinishTransactionAutomaticallyIOS: false },
        { sku: '700coins', andDangerouslyFinishTransactionAutomaticallyIOS: false },
        { sku: '1200coins', andDangerouslyFinishTransactionAutomaticallyIOS: false },
        { sku: '1800coins', andDangerouslyFinishTransactionAutomaticallyIOS: false },
        { sku: '3100coins', andDangerouslyFinishTransactionAutomaticallyIOS: false }
    ],
    android: ['160coins', '400coins', '700coins', '1200coins', '1800coins', '3100coins']
});

export default function Test() {
    const [products, setProducts] = useState([]);
    const [loading, setLoading] = useState(true);

    useEffect(() => {
        const initializeIAP = async () => {
            try {
                await RNIap.initConnection();
                await RNIap.flushFailedPurchasesCachedAsPendingAndroid();

                const availableProducts = await RNIap.getProducts({ skus: itemSkus });
                setProducts(availableProducts);
                setLoading(false);

                const purchaseUpdateSubscription = RNIap.purchaseUpdatedListener(
                    async (purchase) => {
                        const receipt = purchase.transactionReceipt;
                        if (receipt) {
                            try {
                                // Send the receipt to the server for verification and unlock the purchase
                                // await yourAPI.deliverOrDownloadFancyInAppPurchase(receipt);

                                // Finalize the transaction
                                await RNIap.finishTransaction({ purchase, isConsumable: true });

                                Alert.alert('Purchase Successful', 'Your purchase was successful!');
                                console.log('purchase', purchase);
                            } catch (error) {
                                // console.warn('Error processing transaction', error);
                                Alert.alert('Error', 'Error processing transaction');
                            }
                        }
                    }
                );

                const purchaseErrorSubscription = RNIap.purchaseErrorListener(
                    (error) => {
                        // console.warn('purchaseErrorListener', error);
                        Alert.alert('Purchase Error', error.message);
                    }
                );

                return () => {
                    if (purchaseUpdateSubscription) {
                        purchaseUpdateSubscription.remove();
                    }
                    if (purchaseErrorSubscription) {
                        purchaseErrorSubscription.remove();
                    }
                    RNIap.endConnection();
                };
            } catch (error) {
                console.error('IAP initialization error', error);
                // console.error('IAP initialization error', JSON.stringify(error, null, 2));

                setLoading(false);
            }
        };

        initializeIAP();
    }, []);

    if (loading) {
        return (
            <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
                <Text>Loading products...</Text>
            </View>
        );
    }

    return (
        <View style={{ flex: 1, padding: 16 }}>
            <Text style={{ fontSize: 24, marginBottom: 16 }}>Available Products</Text>
            <FlatList
                data={products}
                keyExtractor={(item) => item.productId}
                renderItem={({ item }) => (
                    <View style={{ marginBottom: 16 }}>
                        <Text style={{ fontSize: 18 }}>{item.title}</Text>
                        {/* <Text>{item.description}</Text> */}
                        <Text>{item.localizedPrice}</Text>
                        <Pressable
                            onPress={() => {
                                rightSku = Platform.select({
                                    ios: { sku: itemSkus[0], andDangerouslyFinishTransactionAutomaticallyIOS: false },
                                    android: { skus: [itemSkus[0]] }
                                });
                                RNIap.requestPurchase({ skus: ['160coins'] }, false);
                            }}
                            style={{ backgroundColor: 'blue', padding: 10, borderRadius: 5 }}
                        >
                            <Text style={{ color: 'white' }}>Buy</Text>
                        </Pressable>
                    </View>
                )}
            />
        </View>
    );
}

(i have pod install but 0 changes)

On Apple Store Connect image

Info.plist:

image image

? I don't know if there's a link, I don't think so, but google ads work on my app?

Many thanks to you

Virajmakwana commented 4 weeks ago

did you got any Solution for this???