Implementing IAP on managed app with EAS

Hello !
I am a React and Expo newbee and working on my first project. I am currently implementing In App Purchase and I dont want to eject for now.
So I figured (thanks to this thread) that EAS build was the way to go as it handles the native config required to make In App Purchase work.

However I am struggling with it. At the start, i firstly configured the apple store connect account with the requirement found in this doc, then installed the package expo-in-app-purchases and react-native-unimodules (I assume the configuration of it is done with EAS building).
With this I can build, and i’m uploading my app to TestFlight with eas submit.

As for now my implementation of IAP is only seeing the respondeCode from getProductAsync, but it only gives me an error Maximum call stack size exceeded.
I can not have access to the console because I need to build the app to make it work so I displayed the error direcly on the app screen.
Here’s how I tried this :

import React, { useEffect, useState } from 'react'
import { Dimensions, StyleSheet, Text, View } from 'react-native'
import * as InAppPurchases from 'expo-in-app-purchases';
import { TouchableWithoutFeedback } from 'react-native-gesture-handler';
import { connect } from 'formik';

const windowWidth = Dimensions.get('window').width;
const windowHeight = Dimensions.get('window').height;

const testIAP = () => {
    const [connectOutput, setConnectOutput] = useState('');
    const [getProductOutput, setGetProductOutput] = useState('');
    const [result, setResult] = useState({})
    const [clicked, setClicked] = useState(0)
    const [enterSwitch, setEnterSwitch] = useState(false);
    const [errorMessage, setErrorMessage] = useState('')

    // useEffect(() => {
    //     (async () => {
    //         const test = await InAppPurchases.connectAsync();
    //         console.log(test);
    //     })
    //     return (async () => {
    //         await InAppPurchases.disconnectAsync();
    //     })
    // }, [])

    useEffect(() => {
        connectAsync()
        return () => {
            disconnectAsync()
        }
    }, [])

    const connectAsync = (async () => {
        const test = await InAppPurchases.connectAsync();
        setConnectOutput(test);
    })

    const disconnectAsync = (async () => {
        const test = await InAppPurchases.disconnectAsync();
    })

    const getProductsAsync = (async () => {
        getProductsAsync(['1', '1578239803']).then((responseCode) => {
            setClicked(clicked + 1)
            try { 
                switch (responseCode) {
                    case InAppPurchases.IAPResponseCode.OK:
                        setEnterSwitch(true);
                        setGetProductOutput('OK');
                        setResult(responseCode);
                        break;
                
                    case InAppPurchases.IAPResponseCode.ERROR:
                        setEnterSwitch(true);
                        setGetProductOutput('ERROR');
                        setResult(responseCode);
                        break;
        
                    default:
                        setEnterSwitch(true);
                        setGetProductOutput('default');
                        setResult(responseCode);
                        
                        break;
                }
            } catch (e) {
                setErrorMessage(e.message);
            }
        }).catch((error) => {
            setErrorMessage(error.message);
        })
    })

    return (
        <View style={{ width: windowWidth, height: windowHeight, alignItems: 'center', justifyContent: 'center' }}>
            <Text>Test IAP</Text>
            {/* <TouchableWithoutFeedback onPress={() => {connectAsync()}}>
                <Text>Connect</Text>
            </TouchableWithoutFeedback>
            <Text>{connectOutput}</Text> */}
            <TouchableWithoutFeedback onPress={() => { 
                getProductsAsync() }}>
                <Text>getProducts</Text>
            </TouchableWithoutFeedback>
            <Text>{clicked}</Text>
            <Text>{getProductOutput}</Text>
            <Text>Enter switch :</Text>
            <Text>{enterSwitch ? 'TRUE' : 'FALSE'}</Text>
            <Text>{errorMessage}</Text>
        </View>
    )
}

If someone who succeded to use IAP in managed workflow could point me in the right direction, it would help me greatly !

Nevermind, I managed to fix and understand this by using a custom dev client which helped me to test my code without having to build each time.
I also want to say that the Expo team did a great job with EAS, its very usefull!

1 Like

I think this should get easier soon (but I could be misunderstanding :sweat_smile:)

1 Like