Per iniziare
Copia un prompt di configurazione con i passaggi di installazione e la guida markdown completa per questo 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.
Installazione
Sezione intitolata “Installazione”Puoi usare il nostro setup assistito dall'IA per installare il plugin. Aggiungi le skill Capgo al tuo strumento di IA usando il seguente comando:
npx skills add https://github.com/Cap-go/capgo-skills --skill capacitor-pluginsPoi usa il seguente prompt:
Use the `capacitor-plugins` skill from `Cap-go/capgo-skills` to install the `@capgo/native-purchases` plugin in my project.Se preferisci la configurazione manuale, installa il plugin eseguendo questi comandi e segui le istruzioni specifiche per piattaforma qui sotto:
-
Installa il pacchetto
Finestra del terminale bun add @capgo/native-purchases -
Sincronizza con i progetti nativi
Finestra del terminale bunx cap sync -
Verifica il supporto billing
import { NativePurchases } from '@capgo/native-purchases';const { isBillingSupported } = await NativePurchases.isBillingSupported();if (!isBillingSupported) {throw new Error('Billing is not available on this device');} -
Carica i prodotti direttamente dagli store
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 i flussi di acquisto & ripristino
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 prodotti e abbonamenti in-app in App Store Connect.
- Usa StoreKit Local Testing o tester Sandbox per il QA.
- Non serve modificare il manifest. Assicurati che i prodotti siano approvati.
- Crea prodotti e abbonamenti in-app nella Google Play Console.
- Carica almeno una build per i test interni e aggiungi i license tester.
- Aggiungi il permesso di billing a
AndroidManifest.xml:
<uses-permission android:name="com.android.vending.BILLING" /> - Crea prodotti e abbonamenti in-app in App Store Connect.
Esempio di servizio di acquisto
Sezione intitolata “Esempio di servizio di acquisto”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, }), }); }}Opzioni di acquisto obbligatorie
Sezione intitolata “Opzioni di acquisto richieste”| Opzione | Piattaforma | Descrizione |
|---|---|---|
productIdentifier | iOS + Android | SKU/Product ID configurato in App Store Connect / Google Play Console. |
productType | Solo Android | PURCHASE_TYPE.INAPP oppure PURCHASE_TYPE.SUBS. Valore predefinito: INAPP. Sempre impostato su SUBS per gli abbonamenti. |
planIdentifier | Abbonamenti Android | Base Plan ID di Google Play Console. Obbligatorio per gli abbonamenti, ignorato su iOS e per gli acquisti in-app. |
billingPlanType | Abbonamenti iOS | Piano di fatturazione StoreKit da acquistare. Usa 'monthly' per la fatturazione mensile con un impegno di 12 mesi quando product.pricingTerms offre quell'opzione. |
quantity | iOS | Solo per gli acquisti in-app, il valore predefinito è 1. Android acquista sempre un solo articolo. |
appAccountToken | iOS + Android | UUID/stringa che collega l'acquisto al tuo utente. Obbligatorio come UUID su iOS; Android accetta qualsiasi stringa offuscata fino a 64 caratteri. |
isConsumable | Android | Imposta su true per consumare automaticamente i token dopo aver concesso l'entitlement per i consumabili. Valore predefinito false. |
Verifica dello stato dell'entitlement
Sezione intitolata “Verifica dello stato dell'entitlement”Usa getPurchases() per una visione cross-platform di tutte le transazioni riportate dagli store:
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); }});Comportamento della piattaforma
Section titled “Platform behavior”- iOS: gli abbonamenti includono
isActive,expirationDate,willCancel, e supporto per i listener di StoreKit 2. Gli acquisti in-app richiedono la convalida del receipt lato server. - Android:
isActive/expirationDatenon vengono popolati; chiama l'API di Google Play Developer con ilpurchaseTokenper lo stato autorevole.purchaseStatedeve esserePURCHASEDeisAcknowledgeddeve esseretrue.
Riferimento rapido API
Sezione intitolata “Riferimento rapido API”isBillingSupported()– verifica la disponibilità di StoreKit / Google Play.getProduct()/getProducts()– recupera prezzo, titolo localizzato, descrizione, offerte introduttive e termini di prezzo iOS supportati.purchaseProduct()– avvia il flusso di acquisto di StoreKit 2 o del client Billing, inclusi i piani di fatturazione mensili su iOS.restorePurchases()– riapplica gli acquisti storici e sincronizza con il dispositivo attuale.getPurchases()– elenca tutte le transazioni iOS o gli acquisti Play Billing.manageSubscriptions()– apri l'interfaccia nativa per la gestione degli abbonamenti.addListener('transactionUpdated')– gestisci le transazioni StoreKit 2 in sospeso all'avvio dell'app (solo iOS).
Best practice
Sezione intitolata “Best practices”- Mostra i prezzi del store – Apple richiede di visualizzare
product.titleeproduct.priceString; non hardcodare mai. - Usa
appAccountToken– genera in modo deterministico un UUID (v5) dall'ID utente per collegare gli acquisti agli account. - Valida lato server – invia
receipt(iOS) /purchaseToken(Android) al tuo backend per la verifica. - Gestisci gli errori in modo appropriato – verifica annullamenti utente, errori di rete e ambienti di fatturazione non supportati.
- Testa a fondo – segui la guida sandbox iOS e guida sandbox Android.
- Ripristino e gestione offerte – aggiungi pulsanti UI collegati a
restorePurchases()emanageSubscriptions().
Prossimi passi sui ricavi
Sezione intitolata “Prossimi passi per le entrate”Dopo che il flusso di acquisto funziona, usa il Playbook dei ricavi per pianificare il tuo primo funnel a pagamento: ambito del prodotto, ASO, prezzi, posizionamento del paywall, analytics e feedback sul churn.
Risoluzione problemi
Sezione intitolata “Troubleshooting”I prodotti non vengono caricati
- Assicurati che il bundle ID / application ID corrisponda alla configurazione dello store.
- Verifica che i product ID siano attivi e approvati (App Store) o attivati (Google Play).
- Attendi alcune ore dopo aver creato i prodotti; la propagazione dello store non è istantanea.
Acquisto annullato o bloccato
- Users can cancel mid-flow; wrap calls in
try/catche mostra messaggi di errore chiari. - Per Android, assicurati che gli account di test installino l'app dal Play Store (internal track) per far funzionare il Billing.
- Controlla logcat/Xcode per errori di fatturazione durante l'esecuzione sul dispositivo.
Stato dell'abbonamento errato
- Usa
getPurchases()per confrontare i dati dello store con la cache locale degli entitlement. - Su Android, interroga sempre la Google Play Developer API con la
purchaseTokenper ottenere date di scadenza o stato dei rimborsi. - Su iOS, controlla
isActive/expirationDatee valida le ricevute per rilevare rimborsi o revoche.
Continua da Getting Started
Sezione intitolata “Continua da Getting Started”Se stai usando Per iniziare per pianificare l'approvazione e la distribuzione negli store, collegalo a Utilizzo di @capgo/native-purchases per la funzionalità nativa in Utilizzo di @capgo/native-purchases, @capgo/capacitor-in-app-review per i dettagli di implementazione in @capgo/capacitor-in-app-review, Utilizzo di @capgo/capacitor-in-app-review per la funzionalità nativa in Utilizzo di @capgo/capacitor-in-app-review, @capgo/capacitor-native-market per i dettagli di implementazione in @capgo/capacitor-native-market, e Utilizzo di @capgo/capacitor-native-market per la funzionalità nativa in Utilizzo di @capgo/capacitor-native-market.