In-App Purchases in React Native using StoreKit2 & Google Billing

COMMENTS ()
Tweet

Apple’s StoreKit2 framework, announced at WWDC 2021, simplifies the development and testing of react native in app purchases on iOS.

One of StoreKit2’s key features is its integration with Xcode. We can now see the status of react native in app purchases directly in Xcode, making debugging issues more accessible and ensuring that everything works as expected.

To test our app’s behavior under different conditions, we can also simulate various purchase scenarios, such as successful purchases, canceled purchases, and refunds.

We will also learn how to develop a full-fledged react native IAP implementation for custom business logic, such as mapping user IDs to Apple/Google subscriptions or enabling parent-child subscription logic where a privileged user can purchase a subscription for other users. 

To satisfy these custom product specifications, we must implement App Store Server Notifications and Google Pub/Sub along with our backend server to handle in-app lifecycle events.

1. Architecture

Our proposed architecture handles only the initial transaction on the Mobile side. We will validate the first purchase via Apple on iOS and Google on Android, then send a request to our server to store our premium users’ information and unique transaction IDs.

Our server will receive and process all further lifecycle events, such as subscription renewal, cancellation, expiry, and grace periods, based on their transaction ID.

We will update our own record by matching the unique transaction ID found in each App Store Server Notification or Google Pub/Sub event with our user subscription records.

Finally, we must relay any IAP-related updates back to the front end. For this, we can pick from one of multiple approaches, depending on the requirements:

  1. Server Side Events
  2. Silent Push Notifications using a service like OneSignal or FCM
  3. Long Polling our server on frontend
  4. Handling a specific error response from subscription-only endpoints and updating the user’s subscription locally only once needed.

NOTE: This is a React Native-only tutorial. Our architecture also requires a server implementation for handling IAP lifecycle events using App Store Server Notifications and Google Pub/Sub Events.

If your app has login and user authentication or any custom business logic, then it is necessary to implement a backend along with your front end to handle the management of Apple/Google accounts and link them to your usernames in the app.

2. Setting up StoreKit2 for iOS

To set in-app purchases using StoreKit2, you need to follow these steps:

  1. Set up your app in App Store Connect and add your In-App Purchase products. You should also add Subscription Groups and Subscriptions based on your use case. You should provide all the necessary details, such as the product name, description, and price. NOTE: It’s a good idea to have matching SKUs (product IDs) for both iOS & Android
  2. Open your project in Xcode and create your StoreKit configuration file:
  • Choose File > New > File.
  • Enter *storekit* in the Filter search field in the sheet that appears.
  • Select StoreKit Configuration File, then click Next.
  • In the dialog, enter a name for the file. Select the checkbox to sync your config file with App Store Connect, specify your team and app in the drop-down menus that appear, and click Next. For a local configuration, leave the checkbox unselected, then click Next.
  • Select a location, and click Create.
  • Save the file to your project.
  1. Open the newly created StoreKit file in Xcode, and you should see all your products and subscriptions. If you don’t see your In-App products or want to sync with the latest App Store Connect changes, press the Sync icon.
     
  2. Add your Sandbox & Production environments endpoint to receive App Store Server Notifications.
  3. For testing on the Sandbox environment (outside of Xcode), add Sandbox testers from App Store Connect.

3. Setting up Google Billing for Android

To setup in-app purchases using Google Billing, you need to follow these steps:

  1. Assuming you have Play Console set up for your app, go to Play Console -> your app/project -> products -> subscriptions and click on “Create Subscription.” You should provide all the necessary details, such as the product name, description, and price.

NOTE: It’s a good idea to have matching SKUs (product IDs) for both iOS & Android.

  1. Now, we will utilize Google Cloud Pub/Sub, which essentially manages notifications whenever a new subscriber or an existing subscriber changes their subscription status. Search for pub/sub in GCP (or locate it within the section on the left) and create a project.
  2. Click on “Create Topic” and provide a unique topic name. A topic contains the subscriptions.
  3. Next, go to subscriptions and click “Create Subscription”. Select the topic you created in the previous step and provide a unique subscription ID. Keep the delivery type to push and add an endpoint URL, which pub/sub will utilize to send out notifications whenever a subscription-related activity occurs.

NOTE: Creating subscriptions here doesn’t mean we are creating in-app subscriptions. It just means that we are subscribing to a topic and will receive messages(in-app events) published by Google on that topic.

  1. We want to set up a Google Cloud Pub/Sub service account. Our app must authenticate itself with Google Cloud services and obtain access to pub/sub functionalities. Within the cloud console, go to the IAM and Admin section and click on service accounts in the panel on the left.
  2. Click the Create Service Account button, add a name and description, and click Create and Continue. In the next step, assign the role as Pub/Sub Admin and continue until done by leaving everything as default.
  3. Click to open the service account we just created, navigate to the KEYS section, and click the Create new key option. Choose JSON format and download the key. This downloaded key is essential for authentication on our server.
  4. Go back to the topics section, click on the hamburger menu (three dots) next to the topic you created, and select view permissions. Add the service account [email protected] and grant it the Pub/Sub Publisher role. Hit save.
  5. Now, search for Monetization Setup in the Google Play console. Scroll down to find the topic name. Enter the topic name as projects/{project_id}/topics/{topic_id} where the project_id is the currently selected project, and the topic_id is the topic you created earlier. If clicking Send Test Notification sends a notification to your registered endpoint without an error, the setup was completed OK.
  6. Now, it’s time to add license testers, which allow testing in-app subscriptions within the sandbox environment. Search for License Testing (or locate it in the side menu) and add Google accounts for testers testing subscriptions from within the app.

4. Using react native iap

The react native iap package allows us to incorporate react native in app purchases into our iOS and Android apps and handle store transactions within them.

Regrettably, the documentation provided is quite limited, and bugs plague the implementation of StoreKit2. This guide seeks to consolidate our experiences with implementing react-native-app and present them digestibly, sparing you from going through all the meticulous research independently.

To implement in-app purchases in your React Native in app purchases  app using react-native-app, you need to follow these steps:

  1. Install the react native iap package.
    yarn add react native iap

cd ios

pod install

  1. Follow iOS & Android specific setup for RN using the latest react-native-iap documentation.
    3. Import the react native iap package in your root App file. Wrap the App component with the withIAPContext() wrapper:
    import {

  withIAPContext,

  initConnection,

  endConnection,

  setup,

  useIAP,

} from ‘react-native-iap’;

 

// … root App Component

export default withIAPContext(App);

  1. Inside the root App component’s useEffect, initialize our react native iap config:

    // … inside root App component

useEffect(() => {

    // … other init

 

    // IAP init

    setup({ storekitMode: ‘STOREKIT2_MODE’ });

    initConnection();

 

    return () => {

      // … other deinit

 

      /// IAP cleanup

      void endConnection();

    };

  }, []);

This will initialize the connection with Play Store Console & App Store Connect using StoreKit2 and set up the necessary configuration for your in-app purchases.

  1. Fetch the available products using the getProducts/get subscriptions method. This method takes an array of Product IDs or SKUs as an argument and returns an array of Product/Subscription objects with the details of the products. You can use this information to display the available products in your app.

    import { useIAP } from ‘react native iap’;

 

// … in component

const { getProducts, getSubscriptions } = useIAP();

 

const PRODUCT_IDS = [‘com.yourapp.product1’, ‘com.yourapp.product2’];

const APP_SKUS = [

  ‘product1’,

  ‘product2’,

];

 

// can get objects using either product IDs or SKU names

const products = await getProducts(PRODUCT_IDS);

const subscriptions = await getSubscriptions({ skus: APP_SKUS });

  1. To initiate a react native in app purchases, use the requestPurchase method. This method takes the Product ID / SKU as an argument and initiates the purchase process. If the purchase is successful, the onPurchase event will be triggered. Here’s an example of how to do this:

    RNIap.requestPurchase({sku: ‘product1’});

 This will initiate the react native in app purchases process and trigger the onPurchase event if the purchase is successful.

  1. Finally, to finish the transaction, use the finishTransaction method. This method takes the transaction ID as an argument and finishes the transaction. Here’s an example of how to do this:

    // only call finishTransaction once you have fulfilled what the user has purchased, including enabling all premium features

RNIap.finishTransaction(transactionId);

This will finish the transaction and the purchase process.

NOTE: After calling this function, you tell Apple/Google that you have fulfilled the transaction. In most use cases, you will want to contact your backend server and confirm the user has been granted the premium features before calling finishTransaction.

  1. To handle all purchases, we must implement some important lifecycle methods that should be in our root-level component:
    const { currentPurchase, currentPurchaseError } = useIAP();

useEffect(() => {

    // … listen to currentPurchase to check if the purchase went through

    if (purchase) {

      try {

        const receipt = purchase.transaction receipt;

        if (receipt) {

          // validate the receipt from the backend

        const validationResponse = iapService.validate(receipt)

          if (validationResponse) {

            // update local user state with newly purchased subscription

            // note: It is important to check user recvd from backend because

            // any signed in apple ID can send receipts to this listener,

            // so we may receive updates for another user

            if (validationResponse.id === user.id) {

              dispatch(updateUser(validationResponse));

            }

            // after confirming transaction & updating our app to show

            // user’s new subscription status, we can finishTransaction

// note: isConsumable = true for one-time purchases,

// false for subscriptions

            await finishTransaction({ purchase, isConsumable: false });

          }

        }

      } catch (error) {

        console.log(‘[IAP] error parsing purchase object: ‘, error);

      }

    }

  }, [currentPurchase]);

 

useEffect(() => {

    // … listen to currentPurchaseError, to check if any error happened

    if (currentPurchaseError) {

      const errorCodes = [

        ‘E_USER_CANCELLED’,

        ‘E_ITEM_UNAVAILABLE’,

        ‘UNKNOWN_ERROR’,

      ];

      // handle accordingly. you might want to ignore the 3 error codes

      // listed above

    }

  }, [currentPurchaseError]);

  1. That’s it! You have successfully implemented React Native in app purchases using the react native iap package. Before publishing your app to the App Store, remember to test your implementation thoroughly.

Conclusion

Thanks to StoreKit2 and Google Billing, Implementing React Native in app purchases has never been easier. By following the guidelines outlined in this guide, developers can enhance their apps with premium features and monetize their offerings effectively.

So why wait? Explore React Native in app purchases and take your React Native apps to new heights of success!

CALL

USA408 365 4638

VISIT

1301 Shoreway Road, Suite 160,

Belmont, CA 94002

Contact us

Whether you are a large enterprise looking to augment your teams with experts resources or an SME looking to scale your business or a startup looking to build something.
We are your digital growth partner.

Tel: +1 408 365 4638
Support: +1 (408) 512 1812