React Native: Compras Integradas en Android

Martin
Ract Native con Expo
4 min readApr 22, 2024

--

Si estas buscando un articulo donde aprender a integrar compras en tu app de react native, has llegado a la publicación correcta. Aprenderás a crear artículos y a recuperar y vender los artículos con react-native-iap. A demás te enseñare a saber cuando se ha reembolsado la compra de un articulo.

¡Empecemos!

Lo primero que deberás hacer es configurar tu proyecto para aceptar compras integradas. Para ello añadiremos el permiso BILLING y en dependencias la librería billingclient.

AndroidManifest.xml

<uses-permission android:name="com.android.vending.BILLING"/>

android/app/build.gradle

implementation "com.android.billingclient:billing:6.2.0"

Ahora debes subir esta versión a goolge play desde tu consola de desarrollador. Te recomiendo que lo hagas en un entorno de test y que la cuenta de correo que vayas a utilizar para descargarte la app y realizar pruebas se encuentre entre tus cuentas de testers.

Una vez tengamos desplegada esta versión vamos a crear los artículos. Nos vamos a la consola de desarrollador de google, seleccionamos la app y bajamos hasta Monetización -> Productos -> Productos de compra en la aplicación. Clicamos en crear producto y rellenamos los campos. El id del producto debe ser único, por lo que te recomiendo que utilices la estrategia de poner el package name de tu aplicación y después algo que identifique tu producto. Por ejemplo: com.example.tuapp.monedas

Introduce un nombre y una descripción. Ten en cuenta que puedes manejar varios idiomas y a la hora de recuperar el artículo lo recibirás en el idioma configurado en el dispositivo. Configura un precio y define si este articulo se podrá comprar varias veces o no. Después dale a guardar.

¡Empecemos con el código!

Lo primero que debemos hacer es instalar la biblioteca react-native-iap

npm install react-native-iap

Luego la importaremos en el código

import { 
getProducts,
purchaseErrorListener,
purchaseUpdatedListener,
initConnection,
requestPurchase,
finishTransaction,
getAvailablePurchases,
withIAPContext } from 'react-native-iap';

Debemos envolver la pantalla donde vayamos a utilizar el react-native-iap con el withIAPContext

export default withIAPContext(HomeScreen)

Con getProducts recuperamos los productos creados para lo cual debemos pasar un array con los ids de los productos. Hay que tener en cuenta que hay que inicializar la conexión con el método initConnection. Tendras que crear una lista para mostrar los productos.

const productIds = [
YOUR_PRODUCT_ID
];
await initConnection()
const products = await getProducts({skus: productIds})

Crea el método para comprar el producto donde llamaremos a requestPurchase

const buyPack = async (productId) => {
const purchase = await requestPurchase({ skus: [productId] });
}

Ahora viene lo más importante, capturar el estado de los requestPurchase. Dentro del useEffect llamamos al purchaseErrorListener por si el pago da algún error y a purchaseUpdatedListener paracontrolar cuando realizan un pago.

const purchaseErrorSubscription = purchaseErrorListener((error) => {
Toast.show({
type: 'error',
position: 'bottom',
text1: error?.message
});
});

Dentro del purchaseUpdatedListener controlaremos el estado en el que se encuentra el pago, el cual puede estar en pendiente (2) o pagado (1). En caso de estar en pagado es muy importante recuperar las compras disponibles con getAvailablePurchases y llamar al finishTransaction. Si no finalizamos la compra llamando al finishTransaction el pago se queda como en pausa y se termina cancelando y reembolsándole el dinero al cliente.

const purchaseUpdatedSubscription = purchaseUpdatedListener(
async (purchase) => {
const state = purchase.purchaseStateAndroid;
switch(state) {
case 1:
const availablepurchase = await getAvailablePurchases();
const finishTransactionResult = await finishTransaction({ purchase: availablepurchase[0], isConsumable: false });

Toast.show({
type: 'success',
position: 'bottom',
text1: i18n.t('paymentsuccesfull')
});

break;
case 2: Toast.show({
type: 'info',
position: 'bottom',
text1: i18n.t('pendingpayment')
});
break;
}
}
);

¡Ya tenemos listo el proceso de compra! ¿Pero que pasa si un cliente por el motivo que sea pide que le reembolsemos el dinero?¿Cómo controlamos ese reembolso en la aplicación para poder quitar el privilegio otorgado con la compra? Pues lo haremos consultando la api androidpublisher

Con fetch haremos un get contra la url ‘https://content-androidpublisher.googleapis.com/androidpublisher/v3/applications/{your_app_package_name}/purchases/voidedpurchases’. Esta llamada nos devolvera un array con los identificadores de las compras anuladas. Por lo que simplemente tendrás que controlar que si el identificador de la compra que otorgo el privilegio coincide con uno de los devueltos por esta llamada, deberás quitar el privilegió.

const voidedPurchase = async (token, productId, acces_token) => {
console.log('cancelled consumido con éxito:');
try {
const response = await fetch(`https://content-androidpublisher.googleapis.com/androidpublisher/v3/applications/com.arekjaar.BeastIptv/purchases/voidedpurchases`, {
method: 'GET',
headers: {
'Authorization': 'Bearer ' + access_token,
'Content-Type': 'application/json'
}
});
if (response.ok) {
const data = await response.json();
for (let cancel of data?.voidedPurchases) {
const idPurchase = await DB.getIdPurchase()
if (idPurchase === cancel?.orderId) {
removePrivilege()
}
}
}

} catch (error) {
}
}

Como veras en la llamada se necesita un access_token para llamar a la api. En el siguiente artículo explico como generar un refresh token para luego generar access token para llamar a cualquier api de google.

Ya sabes que si te ha gustado el artículo me puedes invitar a un café ;-)

https://ko-fi.com/arekjaar

Recuerda seguir la siguiente publicación para más artículos sobre React Native con Expo

--

--

Martin
Ract Native con Expo

Experto en integración de aplicaciones con más de 5 años de experiencia con IBM WMB y IIB y en la creación de flujos para Mule ESB con Anypoint Studio