I have a React-Native Expo project. I used StoreKit file and synced it with App Store and edited the original scheme to use this StoreKit file and my simulator was working perfectly and offerings were loaded perfectly. I then do
npx expo prebuild --clean
before submitting to Test Flight.
I created build using and submitted to Test Flight.
eas build --platform ios
eas submit --platform ios --latest
I got an error:
There is an issue with your configuration Check underlying error for more details…. <continue>
Below is my code:
import {ActivityIndicator, Alert, Button, FlatList, Platform, View} from "react-native";
import {useEffect, useState} from "react";
import Purchases, {PurchasesOffering, PurchasesPackage} from "react-native-purchases";
import styles from "@/screens/IAP/IAPStyles";
import CustomText from "@/components/CustomText";
import Heading from "@/components/Heading";
function IAPScreen() {
const [currentOfferings, setCurrentOfferings] = useState<PurchasesOffering | null>(null);
const [isPurchasing, setIsPurchasing] = useState<boolean>(false);
const [loading, setLoading] = useState<boolean>(false);
function GetApiKey() {
if (Platform.OS === "ios") {
return process.env.EXPO_PUBLIC_REVENUE_CAT_APP_STORE_KEY || "hardcoded_key";
}
else {
return process.env.EXPO_PUBLIC_REVENUE_CAT_GOOGLE_STORE_KEY || "";
}
}
function RenderPackage({ item } : { item: PurchasesPackage }) {
return(
<View style={styles.productCard}>
<CustomText
customStyles={styles.productTitle}
text={item.product.title}
size={"medium"}
/>
<CustomText
customStyles={styles.productDescription}
text={item.product.description}
size={"small"}
/>
<CustomText
customStyles={styles.productPrice}
text={item.product.priceString}
size={"small"}
/>
<Button
title="Purchase Again"
disabled={isPurchasing}
onPress={() => PurchasePackage(item)}
/>
</View>
);
}
async function PurchasePackage(currentPackage: PurchasesPackage) {
try {
setIsPurchasing(true);
const purchase = await Purchases.purchasePackage(currentPackage);
console.log("Purchase Identifier: ", purchase.productIdentifier)
console.log("Entitled: ", purchase.customerInfo.entitlements);
console.log("Purchase: ", purchase.transaction)
}
catch (error: any) {
if(!error.userCancelled) {
Alert.alert("Error", "Purchase failed: " + error.message);
}
}
finally {
setIsPurchasing(false);
}
}
useEffect(() => {
setLoading(true);
const setup = async () => {
try {
Purchases.configure({
apiKey: GetApiKey(),
});
const offerings = await Purchases.getOfferings();
setCurrentOfferings(offerings.current);
}
catch (error) {
console.log("Error: ", (error as any).underlyingError);
Alert.alert("Error", "Failed to load offerings." + error);
}
}
setup()
.finally(() => setLoading(false));
}, []);
return(
<View style={styles.mainContainer}>
<Heading
text={"Packages & Subscriptions"}
type={"h2"}
customStyles={styles.header}
/>
{
loading ?
<ActivityIndicator size="large" /> :
currentOfferings && currentOfferings.availablePackages.length > 0 ?
(
<FlatList
data={currentOfferings.availablePackages}
renderItem={RenderPackage}
keyExtractor={(item) => item.identifier}
/>
) :
(
<CustomText
customStyles={styles.productDescription}
text={"No available packages."}
size={"small"}
/>
)
}
</View>
);
}
export default IAPScreen;
Additional Information:
1. Created Sandbox Testers.
2. I have another component that uses “react-native-iap” to see whether it can fetch products but it also not able to.