Saltare al contenuto

Inizia a utilizzare

  1. Installa il pacchetto

    Finestra del terminale
    bun add @capgo/native-purchases
  2. Sincronizza con i progetti nativi

    Finestra del terminale
    bunx cap sync
  3. Verifica il supporto fatturazione

    import { NativePurchases } from '@capgo/native-purchases';
    const { isBillingSupported } = await NativePurchases.isBillingSupported();
    if (!isBillingSupported) {
    throw new Error('Billing is not available on this device');
    }
  4. Carica i prodotti direttamente dai negozi

    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. Implementa i flussi di acquisto e di ripristino

    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();
    • Crea prodotti e abbonamenti in-app in App Store Connect.
    • Utilizza StoreKit Local Testing o Sandbox tester per le QA.
    • Non sono richieste modifiche al manifesto. Assicurati che i tuoi prodotti siano approvati.
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,
}),
});
}
}
OpzionePiattaformaDescrizione
productIdentifieriOS + AndroidCodice SKU/ID prodotto configurato in App Store Connect / Google Play Console.
productTypeSolo per AndroidPURCHASE_TYPE.INAPP o PURCHASE_TYPE.SUBSPredefinito a INAPPSempre impostato a SUBS per le sottoscrizioni.
planIdentifierID piano base da Google Play Console. Richiesto per le sottoscrizioni, ignorato su iOS e per acquisti in-app.Sottoscrizioni su iOS
billingPlanTypePiano di fatturazione StoreKit per l'acquisto. Utilizzareper la fatturazione mensile con un impegno di 12 mesi quando 'monthly' per le sottoscrizioni product.pricingTerms esporge quella opzione.
quantityiOSSolo per acquisti in-app, predefinito a 1. L'Android acquista sempre un oggetto.
appAccountTokeniOS + AndroidUUID/string che collega l'acquisto al tuo utente. Richiesto essere UUID su iOS; L'Android accetta qualsiasi stringa obfuscatrice fino a 64 caratteri.
isConsumableAndroidImpostato su true per consumare automaticamente i token dopo aver concesso l'entitatività per i consumabili. Predefinito a false.

Usa getPurchases() per una vista transazionale di ogni transazione che i negozi segnalano:

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: Le sottoscrizioni includono isActive, expirationDate, willCancel, e supporto per l'ascolto di StoreKit 2. Le vendite in-app richiedono la validazione del ricevuto server.
  • Android: isActive/expirationDate non sono popolate; chiamare il Google Play Developer API con il purchaseToken per lo stato autorizzativo. purchaseState deve essere PURCHASED e isAcknowledged deve essere true.
  • isBillingSupported() – verificare la disponibilità di StoreKit / Google Play.
  • getProduct() / getProducts() – recuperare il prezzo, titolo localizzato, descrizione, offerte introduttive e termini di prezzo iOS supportati.
  • purchaseProduct() – avviare il flusso di acquisto di StoreKit 2 o del client di fatturazione, compresi i piani di fatturazione mensili di impegno iOS.
  • restorePurchases() – riprodurre le transazioni storiche e sincronizzare con il dispositivo corrente.
  • getPurchases() – elencare tutte le transazioni iOS o le fatturazioni di Play Billing.
  • manageSubscriptions() – aprire l'interfaccia utente di gestione delle sottoscrizioni native.
  • addListener('transactionUpdated') – gestire le transazioni di StoreKit 2 in attesa quando l'app si avvia (solo iOS).
  1. Mostra prezzi del negozio – Apple richiede di visualizzare product.title e product.priceString; non hardcoded mai.
  2. Utilizza appAccountToken – generare deterministicamente un UUID (v5) dal tuo ID utente per collegare le acquisizioni agli account.
  3. Verifica server-side – invia receipt (iOS) / purchaseToken (Android) al tuo backend per la verifica.
  4. Gestisci gli errori con cortesia – controlla le cancellazioni degli utenti, le fallite di rete e gli ambienti di fatturazione non supportati.
  5. Testare accuratamente – segui il guida del sandbox iOS e guida del sandbox Android.
  6. Offri la gestione di ripristino & – aggiungi pulsanti di interfaccia utente collegati a restorePurchases() e manageSubscriptions().

Dopo che il flusso di acquisto funziona, utilizza il Revenue Playbook per pianificare il tuo primo canale di pagamento: ambito del prodotto, SEO, prezzi, posizionamento del muro di pagamento, analisi e feedback di churn.

I prodotti non si caricano

  • Assicurati che l'ID bundle / ID dell'applicazione corrisponda alla configurazione del negozio.
  • Conferma che gli ID dei prodotti sono attivi e approvati (App Store) o attivati (Google Play).
  • Aspetta diverse ore dopo aver creato i prodotti; la propagazione del negozio non è istantanea.

Acquisto annullato o bloccato

  • Gli utenti possono annullare durante il flusso; avvolgi le chiamate in try/catch e visualizza messaggi di errore amichevoli.
  • Per Android, assicurati che gli account di test installino l'applicazione dal Play Store (track interno) affinché la fatturazione funzioni.
  • Controlla logcat/Xcode per gli errori di fatturazione quando si esegue l'applicazione sul dispositivo.

Stato della sottoscrizione non corretto

  • Usa getPurchases() per confrontare i dati del negozio con il cache delle tue entrate locali.
  • Sul sistema operativo Android, consulta sempre il Google Play Developer API per ottenere le date di scadenza o lo stato di rimborso. purchaseToken Sul sistema operativo iOS, controlla
  • e verifica le ricevute per rilevare i rimborsi o le revocazioni. isActive/expirationDate Continua da Getting Started

Sottosezione intitolata “Continua da Getting Started”

Se stai utilizzando

Getting Started per pianificare l'approvazione e la distribuzione del negozio, connettilo con Getting Started Usando @capgo/acquisti-nativi per la capacità nativa in Usando @capgo/acquisti-nativi, @capgo/capacitor-recensione-in-app per il dettaglio di implementazione in @capgo/capacitor-recensione-in-app, Usando @capgo/capacitor-recensione-in-app per la capacità nativa in Usando @capgo/capacitor-recensione-in-app, @capgo/capacitor-mercato-nativo per il dettaglio di implementazione in @capgo/capacitor-mercato-nativo, e Usando @capgo/capacitor-mercato-nativo per la capacità nativa in Usando @capgo/capacitor-mercato-nativo.