React Native In-App Purchases — Part 4

In-app purchases example in React Native

shah parth
Simform Engineering
6 min readMay 30, 2024

--

In part 1, part 2, and part 3, we explored the basics of in-app purchases, including setup processes for both iOS and Android platforms.

In this blog, we will explore real-world examples of integrating an in-app purchase library in React Native. We will cover the initialization process, subscription purchases, and other purchase functionality.

Integrate In-App Purchases in React Native

You can either create a new React Native project or integrate the library into an existing project.

To create a new project, use the following command:

npx react-native@latest init InAppPurchase

Configure In-App Purchases library

// for Yarn
yarn add react-native-iap

//For npm
npm install react-native-iap

After successfully adding the library, update the native side.

iOS Configuration

To update pods, run the following command:


cd ios; pod install; cd -

Android Configuration

Go to android/build.gradle and modify the following lines:

buildscript {
ext {
...
supportLibVersion = "28.0.0"
}
}

Configure the payment provider. To support only the Play Store, update android/app/build.gradle

defaultConfig {
...
missingDimensionStrategy "store", "play"
}

For more details, refer to the react-native-iap documentation.

After adding react-native-iap, you must upload a build for close testing on the Play Store console. Approval will take approximately 8 to 10 hours or one day. For iOS, upload the build to TestFlight.

Initiate In-App Purchases in React Native

Wrap the app with HOC

First, wrap your main file with the withIAPContext Higher-Order Component (HOC):

import React from 'react';
import { withIAPContext } from 'react-native-iap';

const App = () => <View />;

export default withIAPContext(App);

Initialize Connection

Next, call the initializeIAP method to enable the connection:

import React, { useEffect } from 'react';
import { endConnection } from 'react-native-iap'

useEffect(() => {
initializeIAP();

return () => {
endConnection();
};
}, []);

The method initializeIAP to call initConnection is shown below. Once an in-app purchase connects, update another useEffect for the getPurchaseInfo and getSubscriptionInfo functions by changing the setConnection useState to true.

import { Platform } from 'react-native';
import React, { useEffect, useState } from 'react';
import { initConnection, flushFailedPurchasesCachedAsPendingAndroid } from 'react-native-iap';

const isAndroid = Platform.OS === 'android'; // check platform is android or not

const [connection, setConnection] = useState<boolean>(false);// set in-app purchase is connected or not

const initializeIAP = async () => {
try {
await initConnection().then(async (value: boolean) => {
setConnection(value);
isAndroid && (await flushFailedPurchasesCachedAsPendingAndroid());
});
} catch (error) {
console.error('Error initializing IAP: ', error);
}
};

flushFailedPurchasesCachedAsPendingAndroid is used for only Android. Ensure compatibility with platform conditions.

For more info, check flushFailedPurchasesCachedAsPendingAndroid.

Retrieve the Available Subscriptions

To obtain subscription details, pass the subscription ID to the array of SKUs in the getSubscriptions function. Based on that, we can make a purchase request.

Similarly, use getProductsfor in-app purchases.


import { getSubscriptions, Subscription, getProducts, Product } from 'react-native-iap'

const subscriptionIds = ['com.simformllc.iapdemo.years'];// for subscriptions
const productIds= ['com.simformllc.iapdemo.yearsallaccess'];// for in-app purchases

const [subscription, setSubscription] = useState<Subscription[]>([]);
const [products, setProducts] = useState<Product[]>([]);

useEffect(() => {
if (connection) {
getSubscriptionInfo();
getPurchaseInfo();
}
}, [connection]);

// To get Subscription information
const getSubscriptionInfo = async () => {
try {
const subscriptions = await getSubscriptions({
skus: subscriptionIds,
});
setSubscription(subscriptions); // set subscription information
} catch (error) {
console.error('Error fetching products: ', error);
}
};

// To get in-app purchases information
const getPurchaseInfo = async () => {
try {
const productsInfo = await getProducts({ skus: productIds });
setProducts(productsInfo);
} catch (error) {
console.error('Error fetching products: ', error);
}
};

Before making any purchase requests, set the purchaseUpdatedListenerto listen for updates when the app launches.

import { purchaseUpdatedListener, Purchase } from 'react-native-iap';

useEffect(() => {
const subscriptionListener = purchaseUpdatedListener(
(purchase: Purchase) => {
console.log(purchase); // get purchase information
},
);

return () => {
subscriptionListener.remove();
};
}, []);

The purchaseUpdatedListener provides necessary purchase information upon successful completion. Manage your backend API accordingly.

After successfully purchasing a subscription, users will gain access to the platform’s JSON data, as outlined below:

For Android:

{
"autoRenewingAndroid": true,
"dataAndroid": "{\"orderId\":\"GPA.3393-1976-6765-68323\",\"packageName\":\"com.simformLLC.iapdemo\",\"productId\":\"com.simformllc.iapdemo.years\",\"purchaseTime\":1706781727369,\"purchaseState\":0,\"purchaseToken\":\"gdpkmemapmpmmbgjakpccknl...\",\"quantity\":1,\"autoRenewing\":true,\"acknowledged\":false}",
"developerPayloadAndroid": "",
"isAcknowledgedAndroid": false,
"obfuscatedAccountIdAndroid": "",
"obfuscatedProfileIdAndroid": "",
"packageNameAndroid": "com.simformLLC.iapdemo",
"productId": "com.simformllc.iapdemo.years",
"productIds": ["com.simformllc.iapdemo.years"],
"purchaseStateAndroid": 1,
"purchaseToken": "gdpkmemapmpmmbgjakpccknl...",
"transactionDate": 1706781727369,
"transactionId": "GPA.3393-1976-6765-68323",
"transactionReceipt": "{\"orderId\":\"GPA.3393-1976-6765-68323\",\"packageName\":\"com.simformLLC.iapdemo\",\"productId\":\"com.simformllc.iapdemo.years\",\"purchaseTime\":1706781727369,\"purchaseState\":0,\"purchaseToken\":\"gdpkmemapmpmmbgjakpccknl...\",\"quantity\":1,\"autoRenewing\":true,\"acknowledged\":false}"
}

For iOS:

{
"appAccountToken": "",
"originalTransactionDateIOS": 1704875275000,
"originalTransactionIdentifierIOS": 2000000496868441,
"productId": "com.simformllc.iapdemo.years",
"purchaseToken": "",
"quantityIOS": 1,
"transactionDate": 1706782889000,
"transactionId": "2000000514281414",
"transactionReasonIOS": "PURCHASE",
"transactionReceipt": "",
"verificationResultIOS": "eyJhbGciOiJFUzI1NiIsIng1...”
}

Handle the Subscription Purchase Request

When the user presses the subscription button, call requestSubscription and pass the SKU obtained from getSubscriptions.

To purchase a subscription on Android, include offerToken. You can retrieve the offerToken from the SKU using the getSubscriptions function.

On the iOS side, you cannot get an offerToken.

import { requestSubscription, Subscription } from 'react-native-iap';

const onSubscription = async (sku: Subscription) => {
try {
const offerToken = isAndroid
? sku?.subscriptionOfferDetails[0]?.offerToken
: null;

const purchaseData = await requestSubscription({
sku: sku?.productId,
...(offerToken && {
subscriptionOffers: [{ sku: sku?.productId, offerToken }],
}),
});

console.log(purchaseData); // after successfully purchase, we'll get purchase information
} catch (error) {
console.log(error);
}
};

Once a user requests a subscription, a modal will pop up from the respective platform, as shown in the image below:

Subscription for Android and iOS

If you wish to add a loader while requesting a subscription purchase, you can initiate the loader prior to the requestSubscription and terminate it once you receive the purchaseData.

Note: On the Android side, when we request a year’s purchase with a test subscription, you can see the price with duration in the above left-side image, such as 1299.00/30 minutes. So, with the test subscription, you’ll get 30 minutes, but in a real-time scenario, it’ll be a year.

For more information, refer to requestSubscription.

Handle the In-App Purchases Request

When users want to buy an in-app product, use the requestPurchase method.

import { Product, requestPurchase} from 'react-native-iap';

const onPurchase = async (sku: Product) => {
try {
const purchaseData = await requestPurchase({
sku: sku?.productId,
andDangerouslyFinishTransactionAutomaticallyIOS: false,
skus: productIds, // Array of all the IAP
});
console.log(purchaseData); // After successfully purchase, we'll get the purchase information
} catch (error) {
console.log(error);
}
};

For more information, refer to requestPurchase.

Once a user requests to make in-app purchases, they will receive a purchase modal from the respective platform, as shown in the image below:

In-app purchases for Android and iOS

Get Current Available Purchases

After buying any subscription, if you want to check your current subscription, use the getAvailablePurchases function from the library.

import { getAvailablePurchases } from 'react-native-iap';

const getCurrentPurchases = async () => {
try {
const purchases = await getAvailablePurchases();
console.log(purchases);// get current available purchases
} catch (error) {
console.log('Error getting purchases:', error);
}
};

Get Purchases History

If you want to check the previous history of a purchased subscription, use getPurchaseHistory.

import { getPurchaseHistory } from 'react-native-iap';

const getPurchaseHistoryIap = async () => {
try {
const purchaseHistory = await getPurchaseHistory();
console.log(purchaseHistory); //get previous all history
} catch (error) {
console.error('Error fetching purchase history: ', error);
}
};

In the example below, the first image shows different types of subscriptions. Once you Upgrade to a Pro subscription, you will see the next image, which indicates a successful purchase.

Example of Subscription and Success

For the complete source code, check out the GitHub repository. 🚀

Conclusion

By following the above steps, you can integrate the react-native-iap library into React Native for in-app purchases, manage subscriptions, handle purchase requests, and access purchase histories.

For more updates on the latest tools and technologies, follow the Simform Engineering blog.

Follow Us: Twitter | LinkedIn

--

--

shah parth
Simform Engineering

I am react-native developer at Simform Software LLP