Saltar al contenido

Primeros pasos

GitHub

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:

Ventana de terminal
npx skills add https://github.com/Cap-go/capgo-skills --skill capacitor-plugins

Luego 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 estos comandos y sigue las instrucciones de cada plataforma:

  1. Instala el paquete

    Ventana de terminal
    bun add @capgo/native-purchases
  2. Sincroniza con proyectos nativos

    Ventana de terminal
    bunx cap sync
  3. Comprobar 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');
    }
  4. Cargar productos directamente desde 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);
    });
  5. Implementar flujos de compra y restauración

    import { NativePurchases, PURCHASE_TYPE } from '@capgo/native-purchases';
    const monthlyPlanId = 'monthly-plan'; // Base Plan ID from Google Play Console
    const transaction = await NativePurchases.purchaseProduct({
    productIdentifier: 'com.example.premium.monthly',
    planIdentifier: monthlyPlanId, // Android base plan id, required unless offerToken is passed; ignored on iOS
    productType: 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 hace falta editar el manifest. Asegúrate de que tus productos estén aprobados.
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, // Android base plan id, required unless offerToken is passed
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,
}),
});
}
}
OpciónPlataformaDescripción
productIdentifieriOS + AndroidSKU/Product ID configurado en App Store Connect / Google Play Console.
productTypeSolo AndroidPURCHASE_TYPE.INAPP o PURCHASE_TYPE.SUBS. Por defecto es INAPP. Siempre se establece en SUBS para suscripciones.
planIdentifierSuscripciones de AndroidBase Plan ID de Google Play Console (Product.identifier en una suscripción, no Product.planIdentifier). Obligatorio para suscripciones en Android a menos que offerToken se proporcione. Se ignora en iOS y en compras in-app.
offerTokenAndroidToken para una suscripción concreta o una oferta de pago único, de la misma getProducts() / getProduct() llamada de compra. Para una suscripción, tiene prioridad sobre planIdentifier. Un token que no coincida con ninguna oferta actual se rechaza.
billingPlanTypeSuscripciones de iOSPlan de facturación de StoreKit para comprar. Usa 'monthly' para facturación mensual con compromiso de 12 meses cuando product.pricingTerms expone esa opción.
quantityiOSSolo para compras in-app, por defecto es 1. Android siempre compra un solo ítem.
appAccountTokeniOS + AndroidUUID/string que vincula la compra con tu usuario. En iOS debe ser un UUID; Android acepta cualquier string ofuscado de hasta 64 caracteres.
isConsumableAndroidEstablecer en true para consumir tokens automáticamente tras otorgar el entitlement de consumibles. Por defecto es false.

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);
}
});
  • 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/expirationDate no se completan; llama a la API de Google Play Developer con el purchaseToken para obtener el estado oficial. purchaseState debe ser PURCHASED y isAcknowledged debe ser true.
  • isBillingSupported() – comprueba la disponibilidad de StoreKit / Google Play.
  • getProduct() / getProducts() – obtén el precio, el título localizado, la descripción, las ofertas de introducción y los términos de precios de iOS admitidos.
  • purchaseProduct() – inicia el flujo de compra del cliente de StoreKit 2 o Billing, incluidos los planes de facturación con compromiso mensual de iOS.
  • restorePurchases() – reprocesa las compras históricas y sincronízalas con el dispositivo actual.
  • getPurchases() – lista todas las transacciones de iOS o las compras de Play Billing.
  • manageSubscriptions() – abre la interfaz de gestión de suscripciones nativas.
  • addListener('transactionUpdated') – gestiona las transacciones pendientes de StoreKit 2 al iniciar la app (solo iOS).
  1. Mostrar precios de la tienda – Apple exige mostrar product.title y product.priceString; nunca los hardcodees.
  2. Usa appAccountToken – genera un UUID (v5) de forma determinista a partir del ID de usuario para vincular compras a cuentas.
  3. Validar en el servidor – envía receipt (iOS) / purchaseToken (Android) a tu backend para su verificación.
  4. Maneja los errores de forma adecuada – verifica cancelaciones de usuario, fallos de red y entornos de facturación no compatibles.
  5. Prueba a fondo – sigue la guía de sandbox de iOS y guía de sandbox de Android.
  6. Ofrece restauración y gestión – añade botones en la UI conectados a restorePurchases() y manageSubscriptions().

Product.subscriptionPeriod ahora es opcional. Android lo omite en ofertas prepago (no recurrentes), que solo tienen precio. Leer product.subscriptionPeriod.unit sin una comprobación es un error de TypeScript. Usa product.subscriptionPeriod?.unit. Los detalles están en Ofertas de suscripción de Android.

Una vez que el flujo de compra funcione, usa el Estrategia de ingresos para planificar tu primer funnel de pago: alcance del producto, ASO, precios, ubicación del paywall, analíticas y feedback de churn.

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/catch y muestra mensajes de error amigables.
  • En Android, asegúrate de que las cuentas de prueba instalen la app desde Play Store (pista interna) para que Billing funcione.
  • Revisa logcat/Xcode para ver errores de facturación al ejecutar en el dispositivo.

Estado de suscripción incorrecto

  • Usa getPurchases() para comparar los datos de la tienda con tu caché local de derechos.
  • En Android, consulta siempre la API de Google Play Developer con purchaseToken para obtener fechas de expiración o el estado de reembolsos.
  • En iOS, verifica isActive/expirationDate y valida los recibos para detectar reembolsos o revocaciones.

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 al usar @capgo/native-purchases, @capgo/capacitor-in-app-review para el detalle de implementación en @capgo/capacitor-in-app-review, Usando @capgo/capacitor-in-app-review para la capacidad nativa en «Usando @capgo/capacitor-in-app-review», @capgo/capacitor-native-market para el detalle de implementación en @capgo/capacitor-native-market, y Usando @capgo/capacitor-native-market para la capacidad nativa en «Usando @capgo/capacitor-native-market.»