Primeros pasos
Copia un prompt de configuración con los pasos de instalación y la guía completa en markdown para este plugin.
Set up this Capacitor plugin in the project.
Use the package manager already used by the project.
Install these package(s): `@capgo/native-purchases`
Run the required Capacitor sync/update step after installation.
Read this markdown guide for the full setup steps: https://raw.githubusercontent.com/Cap-go/website/refs/heads/main/apps/docs/src/content/docs/docs/plugins/native-purchases/getting-started.mdx
Use that guide for platform-specific steps, native file edits, permissions, config changes, imports, and usage setup.
If that guide references other docs pages, read them too.
Instalación
Sección titulada “Instalación”Puedes usar nuestro setup asistido por IA para instalar el plugin. Añade las skills de Capgo a tu herramienta de IA con el siguiente comando:
npx skills add https://github.com/Cap-go/capgo-skills --skill capacitor-pluginsLuego usa el siguiente prompt:
Use the `capacitor-plugins` skill from `Cap-go/capgo-skills` to install the `@capgo/native-purchases` plugin in my project.Si prefieres la configuración manual, instala el plugin ejecutando los siguientes comandos y sigue las instrucciones específicas para cada plataforma a continuación:
-
Instala el paquete
Ventana de la terminal bun add @capgo/native-purchases -
Sincroniza con proyectos nativos
Ventana de la terminal bunx cap sync -
Consulta el soporte de facturación
import { NativePurchases } from '@capgo/native-purchases';const { isBillingSupported } = await NativePurchases.isBillingSupported();if (!isBillingSupported) {throw new Error('Billing is not available on this device');} -
Carga productos directo de las tiendas
import { NativePurchases, PURCHASE_TYPE } from '@capgo/native-purchases';const { products } = await NativePurchases.getProducts({productIdentifiers: ['com.example.premium.monthly','com.example.premium.yearly','com.example.one_time_unlock'],productType: PURCHASE_TYPE.SUBS, // Use PURCHASE_TYPE.INAPP for one‑time products});products.forEach((product) => {console.log(product.title, product.priceString);}); -
Implementa flujos de compra y restauración
import { NativePurchases, PURCHASE_TYPE } from '@capgo/native-purchases';const monthlyPlanId = 'monthly-plan'; // Base Plan ID from Google Play Consoleconst transaction = await NativePurchases.purchaseProduct({productIdentifier: 'com.example.premium.monthly',planIdentifier: monthlyPlanId, // REQUIRED for Android subscriptions, ignored on iOSproductType: PURCHASE_TYPE.SUBS,quantity: 1,});console.log('Transaction ID', transaction.transactionId);await NativePurchases.restorePurchases();- Crea productos y suscripciones in-app en App Store Connect.
- Usa StoreKit Local Testing o testers de Sandbox para QA.
- No requiere editar el manifest. Asegúrate de que tus productos estén aprobados.
- Crea productos y suscripciones in-app en Google Play Console.
- Sube al menos un build de prueba interna y añade testers de licencia.
- Añade el permiso de billing a
AndroidManifest.xml:
<uses-permission android:name="com.android.vending.BILLING" /> - Crea productos y suscripciones in-app en App Store Connect.
Ejemplo de servicio de compra
Sección titulada “Ejemplo de servicio de compra”import { NativePurchases, PURCHASE_TYPE, Transaction } from '@capgo/native-purchases';import { Capacitor } from '@capacitor/core';
class PurchaseService { private premiumProduct = 'com.example.premium.unlock'; private monthlySubId = 'com.example.premium.monthly'; private monthlyPlanId = 'monthly-plan'; // Base Plan ID (Android only)
async initialize() { const { isBillingSupported } = await NativePurchases.isBillingSupported(); if (!isBillingSupported) throw new Error('Billing unavailable');
const { products } = await NativePurchases.getProducts({ productIdentifiers: [this.premiumProduct, this.monthlySubId], productType: PURCHASE_TYPE.SUBS, });
console.log('Loaded products', products);
if (Capacitor.getPlatform() === 'ios') { NativePurchases.addListener('transactionUpdated', (transaction) => { this.handleTransaction(transaction); }); } }
async buyPremium(appAccountToken?: string) { const transaction = await NativePurchases.purchaseProduct({ productIdentifier: this.premiumProduct, productType: PURCHASE_TYPE.INAPP, appAccountToken, });
await this.processTransaction(transaction); }
async buyMonthly(appAccountToken?: string) { const transaction = await NativePurchases.purchaseProduct({ productIdentifier: this.monthlySubId, planIdentifier: this.monthlyPlanId, // REQUIRED for Android subscriptions productType: PURCHASE_TYPE.SUBS, appAccountToken, });
await this.processTransaction(transaction); }
async restore() { await NativePurchases.restorePurchases(); await this.refreshEntitlements(); }
async openManageSubscriptions() { await NativePurchases.manageSubscriptions(); }
private async processTransaction(transaction: Transaction) { this.unlockContent(transaction.productIdentifier); this.validateOnServer(transaction).catch(console.error); }
private unlockContent(productIdentifier: string) { // persist entitlement locally console.log('Unlocked', productIdentifier); }
private async refreshEntitlements() { const { purchases } = await NativePurchases.getPurchases({ productType: PURCHASE_TYPE.SUBS, }); console.log('Current purchases', purchases); }
private async handleTransaction(transaction: Transaction) { console.log('StoreKit transaction update:', transaction); await this.processTransaction(transaction); }
private async validateOnServer(transaction: Transaction) { await fetch('/api/validate-purchase', { method: 'POST', body: JSON.stringify({ transactionId: transaction.transactionId, receipt: transaction.receipt, purchaseToken: transaction.purchaseToken, }), }); }}Opciones de compra requeridas
Sección titulada “Opciones de compra requeridas”| Opción | Plataforma | Descripción |
|---|---|---|
productIdentifier | iOS + Android | SKU/Product ID configurado en App Store Connect / Google Play Console. |
productType | Solo Android | PURCHASE_TYPE.INAPP o PURCHASE_TYPE.SUBS. Por defecto es INAPP. Siempre se establece en SUBS para suscripciones. |
planIdentifier | Suscripciones de Android | Base Plan ID de Google Play Console. Requerido para suscripciones; se ignora en iOS y en compras in-app. |
billingPlanType | Suscripciones de iOS | Plan de facturación de StoreKit a comprar. Usa 'monthly' para facturación mensual con compromiso de 12 meses cuando product.pricingTerms expone esa opción. |
quantity | iOS | Solo para compras in-app, por defecto es 1. Android siempre compra un solo ítem. |
appAccountToken | iOS + Android | UUID/string que vincula la compra con tu usuario. En iOS debe ser un UUID; Android acepta cualquier string ofuscado de hasta 64 caracteres. |
isConsumable | Android | Establecer en true para auto-consumir tokens tras otorgar el entitlement en consumibles. Por defecto es false. |
Verificación del estado del entitlement
Sección titulada “Verificación del estado del entitlement”Usa getPurchases() para una vista multiplataforma de cada transacción que reportan las tiendas:
import { NativePurchases, PURCHASE_TYPE } from '@capgo/native-purchases';
const { purchases } = await NativePurchases.getPurchases({ productType: PURCHASE_TYPE.SUBS,});
purchases.forEach((purchase) => { if (purchase.isActive && purchase.expirationDate) { console.log('iOS sub active until', purchase.expirationDate); }
const isAndroidIapValid = ['PURCHASED', '1'].includes(purchase.purchaseState ?? '') && purchase.isAcknowledged;
if (isAndroidIapValid) { console.log('Grant in-app entitlement for', purchase.productIdentifier); }});Comportamiento de la plataforma
Sección titulada “Comportamiento de la plataforma”- iOS: Las suscripciones incluyen
isActive,expirationDate,willCancel, y soporte para el listener de StoreKit 2. Las compras in-app requieren validación de recibos en el servidor. - Android:
isActive/expirationDateno se completan; llama a la API de Google Play Developer con elpurchaseTokenpara obtener el estado oficial.purchaseStatedebe serPURCHASEDyisAcknowledgeddebe sertrue.
Referencia rápida de API
Sección titulada “Referencia rápida de API”isBillingSupported()– verificar disponibilidad de StoreKit / Google Play.getProduct()/getProducts()– obtener precio, título localizado, descripción, ofertas de introducción y términos de precios de iOS compatibles.purchaseProduct()– inicia el flujo de compra de StoreKit 2 o el cliente de Billing, incluyendo planes de facturación mensual en iOS.restorePurchases()– reproducir compras históricas y sincronizarlas con el dispositivo actual.getPurchases()– listar todas las transacciones de iOS o compras de Play Billing.manageSubscriptions()– abrir la interfaz nativa de gestión de suscripciones.addListener('transactionUpdated')– gestionar transacciones pendientes de StoreKit 2 al iniciar la app (solo iOS).
Buenas prácticas
Sección titulada “Buenas prácticas”- Mostrar precios de la tienda – Apple exige mostrar
product.titleyproduct.priceString; nunca lo hardcodees. - Usa
appAccountToken– genera un UUID (v5) determinista desde tu user ID para vincular compras a cuentas. - Validar en el servidor – envía
receipt(iOS) /purchaseToken(Android) a tu backend para verificar. - Gestionar errores correctamente – verifica cancelaciones de usuario, fallos de red y entornos de facturación no compatibles.
- Realiza pruebas exhaustivas – sigue la guía de sandbox de iOS y guía de sandbox de Android.
- Ofrece restauración y gestión – añade botones en la UI conectados a
restorePurchases()ymanageSubscriptions().
Siguientes pasos con Revenue
Sección titulada “Siguientes pasos con Revenue”Una vez que el flujo de compra funcione, usa el Playbook de ingresos para planificar tu primer funnel de pago: alcance del producto, ASO, precios, ubicación del paywall, analytics y feedback de churn.
Solución de problemas
Sección titulada “Solución de problemas”Los productos no cargan
- Asegúrate de que el bundle ID / application ID coincida con la configuración de la tienda.
- Confirma que los product IDs estén activos y aprobados (App Store) o activados (Google Play).
- Espera unas horas tras crear los productos; la propagación de la tienda no es instantánea.
Compra cancelada o bloqueada
- Users can cancel mid-flow; wrap calls in
try/catchy muestra mensajes de error amigables. - En Android, asegúrate de que las cuentas de prueba instalen la app desde Play Store (internal track) para que Billing funcione.
- Revisa logcat/Xcode para ver errores de facturación al ejecutar en el dispositivo.
Estado de la suscripción incorrecto
- Usa
getPurchases()para comparar los datos de la tienda con tu caché local de entitlements. - En Android, consulta siempre la API de Google Play Developer con el
purchaseTokenpara obtener fechas de expiración o el estado de los reembolsos. - En iOS, comprueba
isActive/expirationDatey valida los recibos para detectar reembolsos o revocaciones.
Continúa desde Primeros pasos
Sección titulada “Continúa desde Primeros pasos”Si estás usando Primeros pasos para planificar la aprobación y distribución en la tienda, conéctalo con Uso de @capgo/native-purchases para la capacidad nativa en el uso de @capgo/native-purchases, @capgo/capacitor-in-app-review para el detalle de implementación en @capgo/capacitor-in-app-review, Uso de @capgo/capacitor-in-app-review para la capacidad nativa en Uso de @capgo/capacitor-in-app-review, @capgo/capacitor-native-market para el detalle de implementación en @capgo/capacitor-native-market, y Uso de @capgo/capacitor-native-market para la funcionalidad nativa en Uso de @capgo/capacitor-native-market.