Adding In-App Subscriptions Using React Native on Android or iOS with react-native-iap

Tiempo de lectura: 2 minutos

Today we’re going to learn how to add subscriptions to our application developed with React Native for Android or iOS.

House with ice - pexels

To make purchases in the app, we need to install the following library in our project:

npm install react-native-iap

Please install the current version:

"react-native-iap": "12.16.3",

Subscription purchase references for Android:

https://developer.android.com/google/play/billing/rtdn-reference?hl=en

Subscription Purchase References for iOS:

https://developer.apple.com/documentation/appstoreservernotifications

And now let’s implement the following code that will allow us to make the purchase:

import React, { useEffect, useState } from 'react';import { EmitterSubscription, Linking, Platform, SafeAreaView, ScrollView, StyleSheet, Text, View, Button, TouchableOpacity,     useTranslation } from 'react-native';import { useAuthContext } from '@/context/AuthContext';import { AxiosResponse } from 'axios';import * as RNIap from 'react-native-iap';import { ComprasObj } from '@/objects/ComprasIAP';import { useServices } from '@/context/ServiceContext';const test = false;const productosSolicitados = Platform.select({  ios: ['suscripcion.mes.1'],  android: ['suscripcion.mes.1'],});const ComprarSuscripcionScreen: React.FC = () => {  const { t } = useTranslation();  const { userData } = useAuthContext();  const { comprasInAppQueries } = useServices();  const [productos, setProductos] = useState([]);  useEffect(() => {    let retornoCompraError: EmitterSubscription | null = null;    let retornoCompraUpdate: EmitterSubscription | null = null;    RNIap.initConnection()      .then(async () => {        console.log('Conectado IAP');        try {          const products = await RNIap.getSubscriptions({ skus: productosSolicitados! });          products.sort((a, b) => {            const aPrice = (a as any)?.subscriptionOfferDetails?.[0]?.pricingPhases?.pricingPhaseList?.[0]?.priceAmountMicros ?? 0;            const bPrice = (b as any)?.subscriptionOfferDetails?.[0]?.pricingPhases?.pricingPhaseList?.[0]?.priceAmountMicros ?? 0;            return aPrice - bPrice;          });          setProductos(products);        } catch (error) {          console.log('Error buscando suscripciones: ' + error);        }        retornoCompraError = RNIap.purchaseErrorListener((error) => {          console.log('Error compra: ' + JSON.stringify(error));        });        retornoCompraUpdate = RNIap.purchaseUpdatedListener(async (purchase) => {          try {            if (Platform.OS === 'android' && !purchase.isAcknowledgedAndroid && purchase.isAcknowledged) {              Linking.openURL(`https://play.google.com/store/apps/details?id=${purchase.appId}`);            }          } catch (error) {            console.log('Error compra: ', error);          }        });      });    return (                                                  {productos.map((pkg) => {                const price = (pkg as any)?.subscriptionOfferDetails?.[0]?.pricingPhases?.pricingPhaseList?.[0]?.formattedPrice ?? '';                return (                   comprar(pkg)}>                    {`${t(pkg.productId)} ${price}`}                                  );              })}                                        );  }, [comprasInAppQueries]);  const comprar = (pkg) => {    // implementar compra  };  return (      );};const styles = StyleSheet.create({  contenedorGeneral: {    flex: 1,    width: '100%',    height: '100%',    backgroundColor: '#fff',  },  contenedorPremium: {    padding: 20,    alignItems: 'center',  },  card: {    backgroundColor: '#f2f2f2',    borderRadius: 10,    padding: 20,    width: '100%',    marginBottom: 20,  },  premiumTitulo: {    fontSize: 20,    fontWeight: 'bold',    textAlign: 'center',    marginBottom: 10,  },  premiumSubtitulo: {    fontSize: 16,    fontWeight: '400',    marginBottom: 10,    textAlign: 'justify',  },  premiumTexto: {    fontSize: 15,    marginBottom: 5,  },  contenedorBotones: {    width: '100%',    alignItems: 'center',  },  boton: {    backgroundColor: '#007bff',    paddingVertical: 12,    paddingHorizontal: 20,    borderRadius: 8,    marginVertical: 6,    width: '100%',    alignItems: 'center',  },  botonTexto: {    color: '#fff',    fontSize: 16,    fontWeight: '600',  },});

NOTA: uso las i18n para devolver el valor en texto de los elementos de compra.

Con esto tendremos las compras implementadas.

Esto ya lo tienes implementado con purchaseUpdatedListener.

For example:

Your backend does not automatically know when this happens if it only trusts the client.

Leave a Comment