9.2 C
New York
Friday, March 21, 2025

ios – Unable to Fetch Subscriptions Information from App Retailer Join as Sandbox Consumer on Actual Gadget (React Native IAP)


I’m engaged on an iOS app utilizing React Native IAP to fetch subscription information from App Retailer Join.

After I run the app on an actual system utilizing Xcode and a sandbox account, the getOfferings() operate doesn’t return any subscription information. Nevertheless, once I use a StoreKit Configuration file, the subscriptions are fetched efficiently.

Setup Particulars:
Library: react-native-iap (newest model)
Operate Used: getOfferings()
Testing Surroundings: Actual iOS system with a Sandbox account
Paid Agreements: Signed
Subscription Standing: “Able to Submit”

What I’ve Tried:
✅ Verified that the sandbox account is accurately logged into the App Retailer.
✅ Restarted the system and reinstalled the app.
✅ Ensured that in-app purchases are enabled in App Retailer Join.
✅ Checked if the subscriptions are correctly arrange beneath “In-App Purchases” in App Retailer Join.
✅ Confirmed that react-native-iap is accurately configured within the app.

Supply code for fetching subscriptions

import { useEffect, useRef, useState } from "react";
import * as Iap from "react-native-iap";
import { useIAP, validateReceiptIos, getReceiptIOS } from "react-native-iap";
import { SECTIONS, SUBSCRIPTION_DATA_MAPPER } from "@/constants/constants";
import { useSnackBar } from "@/contexts/SnackBarContext";
import { GetActiveSubscriptionPlan } from "@/companies/apiServices";
import { getCurrentSubscriptionPlan } from "@/utils/helper";

const iosPaymentService = () => {
  const [subscriptions, setSubscriptions] = useState();
  const [iapLoading, setIapLoading] = useState(false);
  const [activeSection, setActiveSection] = useState();
  const [loading, setLoading] = useState(true);
  const [subscriptionLoading, setSubscriptionLoading] = useState(false);
  const [showLoadingModal, setShowLoadingModal] = useState(false);
  const [currentPlan, setCurrentPlan] = useState({
    currentPlan: "free",
    choice: -1,
    platform: "",
    worth: 0,
    index: -1,
  });
  const [showAlert, setShowAlert] = useState(false);
  const [sections, setSections] = useState();
  const { showSnackBar } = useSnackBar();
  const [paymentLoading, setPaymentLoading] = useState(false);
  const map = SUBSCRIPTION_DATA_MAPPER();
  const [selectedIndex, setSelectedIndex] = useState(1);

  const {
    linked,
    subscriptions: subs,
    getSubscriptions,
    currentPurchase,
    finishTransaction,
    purchaseHistory,
    getPurchaseHistory,
    requestSubscription
  } = useIAP();

  const getSections = (availableSubscriptions: Iap.Subscription[]) => {
    const groupedSubscriptions = availableSubscriptions.cut back((acc, sub) => {
      const baseProductId = sub.productId.change(/_(month-to-month|quarterly)$/, '');
      if (!acc[baseProductId]) {
        acc[baseProductId] = {
          subscription: sub,
          information: {
            title: sub.title,
            index: Object.keys(acc).size + 1,
            content material: {
              perks: [sub.description],
              costs: {
                forex: {
                  month-to-month: '',
                  quarterly: '',
                },
                cash: {
                  month-to-month: 0,
                  quarterly: 0,
                }
              }
            }
          }
        };
      }
      if (sub.subscriptionPeriodNumberIOS === '1') {
        acc[baseProductId].information.content material.costs.forex.month-to-month = sub.localizedPrice;
      } else if (sub.subscriptionPeriodNumberIOS === '3') {
        acc[baseProductId].information.content material.costs.forex.quarterly = sub.localizedPrice;
      }
      return acc;
    }, {});

    const listing = Object.values(groupedSubscriptions);
    listing.unshift({
      subscription: null,
      information: SECTIONS[0].information,
    });
    // console.log("Listing II:", listing);
    setSections(listing.kind((a, b) => a.information.index - b.information.index));
  };

  const initIAP = async () => {
    if (iapLoading) {
      return;
    }
    setIapLoading(true);
    strive {
      await Iap.initConnection();
      const skus = [
        "com.chatreal.subscription.premium_pro_quarterly",
        "com.chatreal.subscription.premium_pro_monthly",
        "com.chatreal.subscription.premium_quarterly",
        "com.chatreal.subscription.premium_monthly"
      ];
      console.log("isConnneted", linked);
      const availableSubscriptions = await Iap.getSubscriptions({ skus });
      console.log("Out there subscriptions:", JSON.stringify(availableSubscriptions, null, 3));
      setSubscriptions(availableSubscriptions);
      getSections(availableSubscriptions);
    } catch (err) {
      console.warn("Error fetching subscriptions:", err);
      console.log("Error particulars:", JSON.stringify(err, null, 2));
      showSnackBar(`Did not load subscriptions: $`);
    } lastly {
      setIapLoading(false);
    }
  };

  const purchaseSubscription = async (sku: string) => {
    console.log("SKU in IOS: ", sku);
    setPaymentLoading(true);
    strive {
      if (!sku) {
        showSnackBar("Subscription Unavailable for the time being");
        return;
      }

      const request: Iap.RequestSubscriptionIOS = {
        sku,
        andDangerouslyFinishTransactionAutomaticallyIOS: false, // Advisable to maintain false for validation
        appAccountToken: undefined, // Elective: Add person account token if wanted
        amount: 1
      };

      console.log("Request:", request);

      const buy = await Iap.requestSubscription(request);

      console.log("PURCHASE::", buy);
      console.log("PURCHASE STRN::", JSON.stringify(buy, null, 2));

      if (buy) {
        // Validate the receipt (if required)
        const receipt = buy.transactionReceipt;
        // const temp = decodeTransactionReceipt(receipt);
        // console.log("Temp:", temp);
        if (receipt) {
          setShowLoadingModal(false); // Shut the loading modal
          setSubscriptionLoading(false); // Mark subscription as full
        } else {
          console.warn("Receipt validation failed");
          showSnackBar("Subscription validation failed");
        }
      } else {
        console.warn("No Buy discovered");
        showSnackBar("No Buy discovered for the subscription");
      }

    } catch (err) {
      console.warn("Error buying subscription:", err);
      showSnackBar("Buy failed");
    } lastly {
      console.log("Lastly block");
      setPaymentLoading(false);
    }
  };

  const decodeTransactionReceipt = (receipt: string) => {
    strive {
      const decoded = atob(receipt); // Decode Base64 string
      console.log("Decoded Receipt:", decoded);
      return decoded;
    } catch (error) {
      console.error("Error decoding receipt:", error);
      return null;
    }
  };

  const getCurrentSubscription = async () => {
    strive {
      setLoading(true);
      const response = await GetActiveSubscriptionPlan();
      if (!response) return;

      const currentPlan = getCurrentSubscriptionPlan(response?.subscription);
      setCurrentPlan(currentPlan ? { ...currentPlan, platform: response?.platform } : undefined);
    } catch (e) {
      showSnackBar("Error fetching present subscription", 2000);
    } lastly {
      setLoading(false);
    }
  };

  const initPaymentService = async () => {
    await initIAP();
    getCurrentSubscription();
  };

  return {
    initPaymentService,
    paymentLoading,
    subscriptions,
    showAlert,
    subscriptionLoading,
    setSubscriptionLoading,
    setShowAlert,
    sections,
    activeSection,
    showLoadingModal,
    setShowLoadingModal,
    setActiveSection,
    currentPlan,
    loading,
    setLoading,
    setCurrentPlan,
    selectedIndex,
    setSelectedIndex,
    purchaseSubscription,
  };
};

export default iosPaymentService;

That is what I get when working it utilizing xcode and sandbox testing on actual system:
'Out there subscriptions:', '[]'

That is what I get when working it utilizing xcode and storekit config file on simulator and even actual system:

Out there subscriptions: [
   {
      "introductoryPrice": "",
      "title": "Premium",
      "introductoryPriceSubscriptionPeriodIOS": "",
      "introductoryPriceAsAmountIOS": "",
      "productId": "com.chatreal.subscription.premium_monthly",
      "subscriptionPeriodUnitIOS": "MONTH",
      "introductoryPricePaymentModeIOS": "",
      "currency": "USD",
      "price": "4.99",
      "countryCode": "USA",
      "subscriptionPeriodNumberIOS": "1",
      "type": "subs",
      "localizedPrice": "$4.99",
      "introductoryPriceNumberOfPeriodsIOS": "",
      "discounts": [],
      "description": "Chatreal AI Premium Subscription",
      "platform": "ios"
   },
   {
      "description": "Chatreal AI Premium Professional Subscription",
      "subscriptionPeriodNumberIOS": "1",
      "countryCode": "USA",
      "introductoryPriceNumberOfPeriodsIOS": "",
      "reductions": [],
      "subscriptionPeriodUnitIOS": "MONTH",
      "productId": "com.chatreal.subscription.premium_pro_monthly",
      "title": "Premium Professional",
      "introductoryPriceSubscriptionPeriodIOS": "",
      "introductoryPrice": "",
      "localizedPrice": "$9.99",
      "sort": "subs",
      "forex": "USD",
      "introductoryPricePaymentModeIOS": "",
      "worth": "9.99",
      "introductoryPriceAsAmountIOS": "",
      "platform": "ios"
   },
   {
      "introductoryPriceAsAmountIOS": "",
      "subscriptionPeriodUnitIOS": "MONTH",
      "productId": "com.chatreal.subscription.premium_pro_quarterly",
      "reductions": [],
      "introductoryPriceNumberOfPeriodsIOS": "",
      "description": "Chatreal AI Premium Professional Subscription",
      "introductoryPrice": "",
      "localizedPrice": "$24.99",
      "sort": "subs",
      "worth": "24.99",
      "introductoryPricePaymentModeIOS": "",
      "forex": "USD",
      "subscriptionPeriodNumberIOS": "3",
      "countryCode": "USA",
      "introductoryPriceSubscriptionPeriodIOS": "",
      "title": "Premium Professional",
      "platform": "ios"
   },
   {
      "introductoryPriceNumberOfPeriodsIOS": "",
      "reductions": [],
      "introductoryPriceSubscriptionPeriodIOS": "",
      "title": "Premium",
      "introductoryPrice": "",
      "countryCode": "USA",
      "subscriptionPeriodNumberIOS": "3",
      "introductoryPricePaymentModeIOS": "",
      "worth": "12.99",
      "forex": "USD",
      "description": "Chatreal AI Premium Subscription",
      "productId": "com.chatreal.subscription.premium_quarterly",
      "subscriptionPeriodUnitIOS": "MONTH",
      "introductoryPriceAsAmountIOS": "",
      "sort": "subs",
      "localizedPrice": "$12.99",
      "platform": "ios"
   }
]

Related Articles

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Latest Articles