Saltar al contenido

Opciones de copia de página

  1. Instale el paquete

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

    Ventana de terminal
    bunx cap sync
  3. Verificar 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');
    }
  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, // REQUIRED for Android subscriptions, ignored on iOS
    productType: PURCHASE_TYPE.SUBS,
    quantity: 1,
    });
    console.log('Transaction ID', transaction.transactionId);
    await NativePurchases.restorePurchases();
    • Utilice StoreKit Local Testing o Sandbox testers para QA.
    • No se requieren ediciones del manifiesto. Asegúrese de que sus productos estén aprobados.
    • Crear productos y suscripciones en Google Play Console.
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,
}),
});
}
}
OpciónPlataformaDescripción
productIdentifieriOS + AndroidID de producto configurado en App Store Connect / Google Play Console.
productTypeSolo para AndroidPURCHASE_TYPE.INAPP o PURCHASE_TYPE.SUBSPor defecto es INAPPSiempre establecido en SUBS para suscripciones
planIdentifierSuscripciones de AndroidID de plan base desde Google Play Console. Requerido para suscripciones, ignorado en iOS y compras in-app.
billingPlanTypeSuscripciones de iOSPlan de facturación de StoreKit para la compra. Utilice 'monthly' para facturación mensual con un compromiso de 12 meses cuando product.pricingTerms exponga esa opción.
quantityiOSSolo para compras en la aplicación, predeterminado a 1. Android siempre compra un artículo.
appAccountTokeniOS + AndroidUUID/cadena que vincula la compra a su usuario. Requerido que sea UUID en iOS; Android acepta cualquier cadena obfusca hasta 64 caracteres.
isConsumableAndroidEstablecer a true para consumir tokens automáticamente después de conceder la autorización para consumibles. Predeterminado a false.

Usar getPurchases() para una vista cruzada de todas las transacciones que los almacenes informan:

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 escuchador de StoreKit 2. Los compras en la aplicación requieren validación de recibos del servidor.
  • Android: isActive/expirationDate no se rellenan; llame al desarrollador de Google Play API con el purchaseToken para obtener el estado autoritativo. purchaseState deben PURCHASED y isAcknowledged deben true.
  • isBillingSupported() – verificar la disponibilidad en la Tienda de Mac / Google Play.
  • getProduct() / getProducts() – obtener el precio, título localizado, descripción, ofertas de introducción y términos de precios de iOS admitidos.
  • purchaseProduct() – iniciar el flujo de compra de StoreKit 2 o Billing, incluyendo planes de facturación mensuales de compromiso de iOS.
  • restorePurchases() – reproducir compras históricas y sincronizar con el dispositivo actual.
  • getPurchases() – listar todas las transacciones de iOS o compras de Play Billing.
  • manageSubscriptions() – abrir la interfaz de usuario de gestión de suscripciones nativa.
  • addListener('transactionUpdated') – manejar transacciones pendientes de StoreKit 2 cuando se inicia la aplicación (solo iOS).
  1. Mostrar precios de la tienda – Apple requiere mostrar product.title y product.priceString; nunca utilice código duro.
  2. Utilice appAccountToken – genere de manera determinista un UUID (v5) a partir del ID de usuario para vincular compras a cuentas.
  3. Validar en el servidor – envíe receipt (iOS) / purchaseToken (Android) a su back-end para la verificación.
  4. Maneje errores con amabilidad – compruebe las cancelaciones de usuario, las fallas de red y los entornos de facturación no compatibles.
  5. Pruebe exhaustivamente – sigue el guía del entorno de pruebas de iOS y guía del entorno de pruebas de Android.
  6. Restauración y gestión protegida – agrega botones de interfaz de usuario conectados a restorePurchases() y manageSubscriptions().

Después de que el flujo de compra funciona, utilice el Libro de estrategias de ingresos para planificar su primer canal de pago: alcance del producto, SEO, precios, ubicación de la barrera de pago, análisis y retroalimentación de abandono.

Productos no se cargan

  • Asegúrese de que el ID de la cesta / ID de la aplicación coincida con la configuración de la tienda.
  • Confirme que los IDs de los productos están activos y aprobados (Tienda de aplicaciones) o activados (Google Play).
  • Espera varios horas después de crear productos; la propagación de la tienda no es instantánea.

Compra cancelada o atascada

  • Los usuarios pueden cancelar en medio del flujo; envuelva las llamadas en try/catch y superficie mensajes de error amigables.
  • Para Android, asegúrese de que las cuentas de prueba instalen la aplicación desde la Tienda de Play (ruta interna) para que la facturación funcione.
  • Revisar logcat/Xcode para errores de facturación cuando se ejecuta en dispositivo.

Estado de la suscripción incorrecto

  • Utilice para comparar los datos de la tienda con su caché de derechos locales. getPurchases() En Android, siempre consulte el desarrollador de Google Play con __CAPGO_KEEP_0__ para obtener fechas de vencimiento o estado de devolución.
  • On Android, always query the Google Play Developer API with the purchaseToken Editar página
  • Anterior isActive/expirationDate Resumen