Zum Inhalt springen

Optionen für die Kopie der Seite

  1. Installieren Sie das Paket

    Terminal-Fenster
    bun add @capgo/native-purchases
  2. Synchronisiere mit native Projekten

    Terminalfenster
    bunx cap sync
  3. Überprüfe die Rechnungsbegleitung

    import { NativePurchases } from '@capgo/native-purchases';
    const { isBillingSupported } = await NativePurchases.isBillingSupported();
    if (!isBillingSupported) {
    throw new Error('Billing is not available on this device');
    }
  4. Lade Produkte direkt aus den Geschäften

    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. Implementiere Kauf- und Wiederherstellungsflüsse

    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();
    • Erstellen Sie in-App-Produkte und -Abonnements in App Store Connect.
    • Verwenden Sie StoreKit Local Testing oder Sandbox-Tester für QA.
    • Keine Manifest-Änderungen erforderlich. Stellen Sie sicher, dass Ihre Produkte genehmigt sind.
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,
}),
});
}
}
OptionPlattformBeschreibung
productIdentifieriOS + AndroidArtikelnummer/Produkt-ID in App Store Connect / Google Play Console konfiguriert.
productTypeNur für Android verfügbarPURCHASE_TYPE.INAPP oder PURCHASE_TYPE.SUBSStandardmäßig ist INAPPimmer auf SUBS für Abonnements
planIdentifierAbonnements für AndroidBasiskunden-ID aus Google Play Console. Erforderlich für Abonnements, wird bei iOS- und In-App-Käufen ignoriert.
billingPlanTypeAbonnements für iOSStoreKit-Billing-Plan zum Kauf. Verwenden Sie 'monthly' für monatliche Abrechnung mit einer 12-monatigen Verpflichtung, wenn product.pricingTerms die Option offenlegt.
quantityiOSNur für In-App-Käufe, standardmäßig 1Android kauft immer ein Produkt.
appAccountTokeniOS + AndroidEine UUID/Zeichenkette, die den Kauf mit Ihrem Benutzer verbindet. Erforderlich, dass es auf iOS eine UUID ist; Android akzeptiert jede verschlüsselte Zeichenkette bis zu 64 Zeichen.
isConsumableAndroidSetzen Sie auf true Zum automatischen Verbrauch von Tokenen nach der Gewährung von Entgelt für Verbrauchsgüter. Standardmäßig false.

Verwenden Sie getPurchases() für eine plattformübergreifende Ansicht aller Transaktionen, die die Stores melden:

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);
}
});
  • iOSIn den Abonnements sind isActive, expirationDate, willCancelund StoreKit 2-Hinweisunterstützung. In-App-Käufe erfordern eine Server-Belegevalidierung.
  • Android: isActive/expirationDate werden nicht befüllt; rufen Sie den Google Play-Entwickler API mit dem purchaseToken für die verbindliche Statusanzeige. purchaseState müssen PURCHASED und isAcknowledged müssen true.
  • isBillingSupported() – Überprüfen Sie die Verfügbarkeit in der App-Store oder Google Play.
  • getProduct() / getProducts() – Abrufen Sie den Preis, die lokalisierte Überschrift, Beschreibung, Einführungsangebote und unterstützte iOS-Preistypen.
  • purchaseProduct() – Starten Sie den Kauffluss von StoreKit 2 oder Billing-Klient, einschließlich iOS-Monatsverpflichtungsabrechnungsplänen.
  • restorePurchases() – Wiedergabe historischer Kaufvorgänge und Synchronisierung mit dem aktuellen Gerät.
  • getPurchases() – Auflisten aller iOS-Transaktionen oder Play-Billing-Käufe.
  • manageSubscriptions() – Öffnen Sie die native Abonnement-Verwaltungsoberfläche.
  • addListener('transactionUpdated') – Verarbeiten Sie bei App-Start die laufenden StoreKit 2-Transaktionen (nur iOS).
  1. Zeigen Sie den Ladenpreis an – Apple erfordert die Anzeige von product.title und product.priceString; never hardcode.
  2. Verwenden Sie appAccountToken – generieren Sie deterministisch eine UUID (v5) aus Ihrem Benutzer-ID, um Kaufe mit Konten zu verknüpfen.
  3. Validieren Sie serverseitig – senden Sie receipt (iOS) / purchaseToken (Android) an Ihren Backend für die Verifizierung.
  4. Fehler beherrschen – überprüfen Sie die Benutzerstornierungen, Netzwerkfehler und nicht unterstützte Bezahlumgebungen.
  5. Testen Sie gründlich – folge den iOS Sandbox-Leitfaden und Android Sandbox-Leitfaden.
  6. Wiederherstellung und Verwaltung anbieten – füge UI-Schaltflächen hinzu, die an restorePurchases() und manageSubscriptions().

Nachdem der Kauffluss funktioniert, verwende das Revenue Playbook um deinen ersten bezahlten Kanal zu planen: Produktumfang, ASO, Preis, Paywall-Platzierung, Analytics und Rückschläge zur Abmeldung.

Produkte laden nicht

  • Stellen Sie sicher, dass die Bundle-ID / Anwendungs-ID der Store-Konfiguration entspricht.
  • Bestätigen Sie, dass die Produkt-IDs aktiv und genehmigt (App Store) bzw. aktiviert (Google Play) sind.
  • Warten Sie einige Stunden nach der Erstellung von Produkten; die Store-Verbreitung ist nicht sofort.

Kauf wurde abgebrochen oder hängt

  • Benutzer können mitten im Flow abbrechen; Wrapen Sie Aufrufe in try/catch und freundliche Fehlermeldungen an der Oberfläche.
  • Für Android stellen Sie sicher, dass Testkonten die App vom Play Store (internem Track) installieren, damit Billing funktioniert.
  • Überprüfen Sie Logcat/Xcode für Fehler bei der Abrechnung, wenn Sie auf einem Gerät laufen.

Falsche Abonnementzustand

  • Verwenden Sie getPurchases() um Daten des Stores mit Ihrem lokalen Cache für Bezahlungen zu vergleichen.
  • Auf Android wird immer der Google Play Developer API abgefragt, um purchaseToken um Ablaufdaten oder den Status von Rückerstattungen zu erhalten.
  • Auf iOS prüfen Sie isActive/expirationDate und überprüfen Sie die Rechnungen, um Rückerstattungen oder Widerrufe zu erkennen.