Many people regard their application primarily as a source of revenue. Any sensible developer who gets into mobile application development is looking at least at ROI (return of investment) when selecting their monetization strategy.
In-app purchase is one model that can help you make money, one we have mixed feelings about it. The secret’s out — it’s not easy to make money with apps. Having experimented with monetization on our own mobile products, we know how hard it is to choose the right source of revenue and sustain it.
What is In-App Purchase?
In-app purchasing refers to the buying of goods and services from an application on a mobile device. In-app purchases mean developers can provide their applications for free, but then advertise paid upgrades, feature unlocks, special items, or even ads other apps and services, to users. This allows the developer to profit despite giving the basic app itself away for free.
Types Of In-App Purchases
In-app purchases include:
- Consumable: For example, game currency, health, and hints. Users need to buy these items repeatedly, every time they want to use them — they cannot be used in the future for free. On reinstalling or changing device the user may lose their consumable product.
- Non-consumable: For example, upgrading the app to the pro version or removing ads. Users buy these items once and they can then be used on an ongoing basis, for free. On reinstalling or changing devices these products are retained — if the user loses their non-consumable item, they may be able to download it again for free by restore in-app purchases.
- Non-renewing subscriptions: For example, a sport session pass for one, three, or six months. Users can use these items for a fixed period of time, with an option to purchase again when the period ends.
- Auto-renewable subscriptions: Users can buy these items for a specified period of time, they’ll automatically renew when the period has passed. For example, ongoing services (Netflix, Hulu Plus, etc), or magazine subscriptions.
In-app purchase product creation
For in-app purchases you need products to offer to the user — a subscription, or some coins — which you present to the user in the app.
Think of products as different packages which you show to the user to purchase. So, you should create one or two or more products in iTunes Connect for iOS and Google Play Store Console for Android.
To enable in-app purchase for your app you should have iTunes Connect account for iOS and Google Play Store Console account for Android.
Let’s start implementing in-app Purchase in our application. Here are the steps we have to follow:
- Configure in-app purchase on Google Play Store Console.
- Configure the react-native-iap library in React native.
1. Configure in-app purchase on iTunes Connect (for iOS)
Important: Before you can create your In-App Purchases, you’re required by Apple to request and fill out their Paid Applications contract.
Log in to your App Store Connect account here
https://appstoreconnect.apple.com/
Go to the “Agreements, Tax, and Banking” section. You’ll see the link to request the paid applications contract towards the top of the page.
Request and fill out the paid applications contract.
This is very important. You need the paid applications contract in place before Apple will allow you to charge for in-app purchases. Make sure you fill out all of your Contact, Banking, and Tax information. If any of these are not filled out, the contract with Apple is not completed, so In-App Purchases will not work.
Now that you have your paid applications contract filled in, you need to add the products (the in-app purchases) to your app listing.
Go to the “My Apps” section of your “App Store Connect” account.
Click on your app to step into its listing.
Select “Features” from the menu towards the top.
Make sure that after clicking the “Features” tab you are in the “In-App Purchases” section on the left-hand menu.
Add an in-app purchase product by selecting the (+) button.
Select the “Non-Consumable” type and click “Create.”
Select according to your requirement — it depends on the type of product you want to create.
Enter a reference name and product ID. It’s a good idea to enter a reference name that clearly tells you what in-app section this specific purchase will unlock. Also, make note of the product ID you enter since you will also need to enter the product ID on your app control panel.
Select the price you want to charge for this specific purchase.
Enter the App Store information for this purchase. This is the information that will be visible on the App Store.
Enter the purchase’s review information. The screenshot (requires at least 640 x 920 pixels) and the information you provide will not be shown on the App Store — it is only for Apple’s review purposes.
Click “Save” in the upper-right hand corner.
Now that you have your In-App Purchase created, you need to add the Product ID to your app’s control panel.
In your app control panel, go to the “Commerce” section from the menu on the left.
Copy and paste the product ID from your App Store Connect account which you added to the iOS product ID field
Once you’ve entered your product IDs, click the “Add” button to save.
One final thing that you have to configure in XCode settings, open XCode and select project and go to Capabilities section and enable InApp Purchase button.
2. Configure In-App Purchase on Google Play Store Console
IMPORTANT: Before you can create your In-App Purchases in android, you are required to activate a Merchant account in your Google Developer account.
Log in to your Google Developer account here: https://play.google.com/apps/publish
Click the “Settings” tab from the menu on the left.
Scroll to the bottom of this page and you’ll see a link to activate your Merchant account.
When you’ve activated your Merchant account it will look like this:
Now that you’ve activated your Merchant account, you’re required to obtain your license/billing Key from your Google Developer account.
From the menu on the left, select “All Applications”, then click on the app that you’re going to apply the in-app purchases to:
From the menu on the left select “Services and APIs” found under “Development Tools.”
Copy the license key in the section titled “Your license key for this application.”
Upload your license/billing key to the Commerce section of your app’s control panel.
Now you have your Merchant account activated and your license/billing Key uploaded.
Click on your app listing.
Click the“In-App Products” tab from the menu on the left.
If your app was already live on the Play Store and you’re just now including In-App Purchases, the In-App Products section is found under the Store Presence tab of your app’s listing.
Make sure you have “Managed Products” selected, then click “Create Managed Products.”
Input your Product ID.
Input your title and description, then change the status to active.
Set a price, then click “Save” at the bottom of the page.
Now that you have your in-app purchase created, you need to add the product ID to your app control panel.
In the app control panel, go to the commerce section from the menu on the left.
Copy and paste the Product ID from your Google Developer account which you entered previously into the Google Play Product ID field.
Once you have entered your Product IDs, click the “Add” button to save.
One more thing that you must configure in Android: You have to submit an alpha or beta release with the following permission in Android Manifest.xml:
uses-permission android:name="com.android.vending.BILLING"
3. Configure the react-native-iap library in React native
react-native-iap is a react native module library for in-app purchases for both Android and iOS platforms.
The goal for this library is to get experience between the two platforms for in-app-purchase.
To install react-native-iap you just need to run one of the following commands in the project terminal:
npm i react-native-iap
or
yarn add react-native-iap
From React Native 0.60 and higher, linking is automatic. So you don’t need to run react-native link.
If you’re on a Mac and developing for iOS, you need to install the pods (via Cocoapods) to complete the linking:
npx pod-install ios
Now the setup for in-app purchases is done, we should see the code part in React native.
First, we should import RNIap from react-native-iap, like this:
import RNIap, { Product, ProductPurchase, PurchaseError, acknowledgePurchaseAndroid, purchaseErrorListener, purchaseUpdatedListener, } from 'react-native-iap';
You have to define your products SKU’s for iOS and Android separately:
const itemSkus = Platform.select({ ios: [ 'com.example.productId' ], android: [ 'com.example.productId' ] });
Also have to define your products subscriptions for iOS and Android separately:
const itemSubs = Platform.select({ ios: [ 'test.sub' ], android: [ 'test.sub' ] });
Now you can proceed and fetch your in-app purchase products with itemsSkus and itemsSubs, as shown:
import React, {Component} from 'react'; import { SafeAreaView, StyleSheet, Text, TouchableOpacity, Platform, } from 'react-native'; import RNIap, { Product, ProductPurchase, PurchaseError, acknowledgePurchaseAndroid, purchaseErrorListener, purchaseUpdatedListener, } from 'react-native-iap'; const itemSkus = Platform.select({ ios: ['com.example.productId'], android: ['com.example.productId'], }); const itemSubs = Platform.select({ios: ['test.sub'], android: ['test.sub']}); let purchaseUpdateSubscription; let purchaseErrorSubscription; export default class App extends Component { constructor(props) { super(props); this.state = { productList: [], receipt: '', availableItemsMessage: '', }; } async componentDidMount(): void { try { const result = await RNIap.initConnection(); console.log('connection is => ', result); await RNIap.consumeAllItemsAndroid(); } catch (err) { console.log('error in cdm => ', err); } purchaseUpdateSubscription = purchaseUpdatedListener( async (purchase: ProductPurchase) => { console.log('purchaseUpdatedListener', purchase); if ( purchase.purchaseStateAndroid === 1 && !purchase.isAcknowledgedAndroid ) { try { const ackResult = await acknowledgePurchaseAndroid( purchase.purchaseToken, ); console.log('ackResult', ackResult); } catch (ackErr) { console.warn('ackErr', ackErr); } } this.purchaseConfirmed(); this.setState({receipt: purchase.transactionReceipt}); purchaseErrorSubscription = purchaseErrorListener( (error: PurchaseError) => { console.log('purchaseErrorListener', error); // alert('purchase error', JSON.stringify(error)); }, ); }, ); } componentWillUnmount(): void { if (purchaseUpdateSubscription) { purchaseUpdateSubscription.remove(); purchaseUpdateSubscription = null; } if (purchaseErrorSubscription) { purchaseErrorSubscription.remove(); purchaseErrorSubscription = null; } } getItems = async (): void => { try { console.log('itemSkus[0]', itemSkus[0]); const products: Product[] = await RNIap.getProducts(itemSkus); console.log('Products[0]', products[0]); this.setState({productList: products}); this.requestPurchase(itemSkus[0]); } catch (err) { console.log('getItems || purchase error => ', err); } }; getSubscriptions = async (): void => { try { const products = await RNIap.getSubscriptions(itemSubs); console.log('Products => ', products); this.setState({productList: products}); } catch (err) { console.log('getSubscriptions error => ', err); } }; getAvailablePurchases = async (): void => { try { const purchases = await RNIap.getAvailablePurchases(); console.info('Available purchases => ', purchases); if (purchases && purchases.length > 0) { this.setState({ availableItemsMessage: `Got ${purchases.length} items.`, receipt: purchases[0].transactionReceipt, }); } } catch (err) { console.warn(err.code, err.message); console.log('getAvailablePurchases error => ', err); } }; requestPurchase = async (sku): void => { try { RNIap.requestPurchase(sku); } catch (err) { console.log('requestPurchase error => ', err); } }; requestSubscription = async (sku) => { try { await this.getItems(); await RNIap.requestSubscription(sku); } catch (err) { alert(err.toLocaleString()); } }; purchaseConfirmed = () => { //you can code here for what changes you want to do in db on purchase successfull }; render() { return ( <SafeAreaView style={styles.rootContainer}> <TouchableOpacity onPress={() => { this.getItems(); }} style={styles.buttonStyle}> <Text style={styles.buttonText}>Test IAP</Text> </TouchableOpacity> </SafeAreaView> ); } } const styles = StyleSheet.create({ rootContainer: { flex: 1, justifyContent: 'center', alignItems: 'center', }, buttonStyle: { width: '70%', backgroundColor: '#000', borderRadius: 25, padding: 10, justifyContent: 'center', alignItems: 'center', }, buttonText: { color: '#fff', fontSize: 17, fontWeight: 'bold', }, });
Testing
We check in-app purchase functionality in the app by making a sample purchase of a product by any user.
- For iOS, we create a sandbox tester for that. Go to “User & Roles Section” in iTunes, select the “Sandbox Tester” tab and add a new user as a tester with some basic details. With the credentials of that user you can purchase any product on iOS without paying any real money and test in app purchase functionality in the iOS app.
- For Android, we add a tester account, open play store console, go to the “Settings” section and then the “Account Detail” tab, scroll down to “License Testing” and add the email of the user you want to add as a tester. You can test in-app purchase functionality in the Android app using these tester accounts credentials.
One more thing to add: To check in-app purchase, your Android build must be in release mode — you can’t test in debug build.
That’s it — you can now make your app in-app purchase configured and test it.
Note: in-app purchases cannot be tested on an iOS simulator or Android emulator — please use a real device.
Greetings!!