Langsung ke konten

Panduan Memulai

GitHub

Anda bisa menggunakan AI-Assisted Setup kami untuk menginstal plugin ini. Tambahkan skill Capgo ke tool AI Anda dengan command berikut:

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

Lalu gunakan prompt berikut:

Use the `capacitor-plugins` skill from `Cap-go/capgo-skills` to install the `@capgo/native-purchases` plugin in my project.

Jika Anda lebih memilih Manual Setup, instal plugin dengan menjalankan perintah berikut dan ikuti petunjuk khusus platform di bawah ini:

  1. Instal package

    Jendela terminal
    bun add @capgo/native-purchases
  2. Sync dengan proyek native

    Jendela terminal
    bunx cap sync
  3. Cek dukungan billing

    import { NativePurchases } from '@capgo/native-purchases';
    const { isBillingSupported } = await NativePurchases.isBillingSupported();
    if (!isBillingSupported) {
    throw new Error('Billing is not available on this device');
    }
  4. Load produk langsung dari 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);
    });
  5. Implementasi flow purchase & restore

    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();
    • Buat produk dan langganan in-app di App Store Connect.
    • Gunakan StoreKit Local Testing atau tester Sandbox untuk QA.
    • Tidak perlu mengubah manifest. Pastikan produk Anda sudah disetujui.
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,
}),
});
}
}
OpsiPlatformDeskripsi
productIdentifieriOS + AndroidSKU/Product ID yang dikonfigurasi di App Store Connect / Google Play Console.
productTypeHanya AndroidPURCHASE_TYPE.INAPP atau PURCHASE_TYPE.SUBS. Defaultnya adalah INAPP. Selalu diatur ke SUBS untuk langganan.
planIdentifierLangganan AndroidBase Plan ID dari Google Play Console (Product.identifier pada langganan, bukan Product.planIdentifier). Wajib untuk langganan Android kecuali offerToken diberikan. Diabaikan di iOS dan pembelian in-app.
offerTokenAndroidToken untuk satu langganan tertentu atau penawaran satu kali, dari getProducts() / getProduct() panggilan pembelian yang sama. Untuk langganan, ini lebih diutamakan daripada planIdentifier. Token yang tidak cocok dengan penawaran saat ini akan ditolak.
billingPlanTypeLangganan iOSStoreKit billing plan yang akan dibeli. Gunakan 'monthly' untuk penagihan bulanan dengan komitmen 12 bulan ketika product.pricingTerms mengekspos opsi tersebut.
quantityiOSHanya untuk in-app purchases, default ke 1. Android selalu membeli satu item.
appAccountTokeniOS + AndroidUUID/string yang menghubungkan pembelian ke pengguna Anda. Wajib berupa UUID di iOS; Android menerima string terofusiasi apa pun hingga 64 karakter.
isConsumableAndroidSetel ke true untuk otomatis mengonsumsi token setelah memberikan entitlement untuk item yang dapat dikonsumsi. Defaultnya false.

Gunakan getPurchases() untuk melihat setiap transaksi yang dilaporkan store secara lintas platform:

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: Langganan mencakup isActive, expirationDate, willCancel, serta dukungan listener StoreKit 2. In-app purchase memerlukan validasi receipt di server.
  • Android: isActive/expirationDate tidak terisi; panggil Google Play Developer API dengan purchaseToken untuk status yang paling akurat. purchaseState harus PURCHASED dan isAcknowledged harus true.
  • isBillingSupported() – periksa ketersediaan StoreKit / Google Play.
  • getProduct() / getProducts() – ambil harga, judul terlokalisasi, deskripsi, penawaran intro, dan syarat harga iOS yang didukung.
  • purchaseProduct() – memulai alur pembelian StoreKit 2 atau Billing client, termasuk rencana tagihan komitmen bulanan iOS.
  • restorePurchases() – memutar ulang pembelian historis dan menyinkronkannya ke perangkat saat ini.
  • getPurchases() – menampilkan daftar semua transaksi iOS atau pembelian Play Billing.
  • manageSubscriptions() – membuka UI manajemen langganan native.
  • addListener('transactionUpdated') – menangani transaksi StoreKit 2 yang tertunda saat aplikasi Anda dimulai (hanya iOS).
  1. Tampilkan harga toko – Apple mewajibkan menampilkan product.title dan product.priceString; jangan pernah hardcode.
  2. Gunakan appAccountToken – generate UUID (v5) secara deterministik dari user ID Anda untuk menghubungkan pembelian ke akun.
  3. Validasi server-side – kirim receipt (iOS) / purchaseToken (Android) ke backend Anda untuk verifikasi.
  4. Tangani error dengan baik – periksa pembatalan pengguna, kegagalan jaringan, dan lingkungan billing yang tidak didukung.
  5. Uji secara menyeluruh – follow the panduan sandbox iOS dan panduan sandbox Android.
  6. Penawaran restore & manajemen – tambahkan tombol UI yang terhubung ke restorePurchases() dan manageSubscriptions().

Product.subscriptionPeriod kini opsional. Android mengabaikannya pada penawaran prepaid (non-recurring), yang hanya memiliki harga. Membaca product.subscriptionPeriod.unit tanpa pengecekan adalah error TypeScript. Gunakan product.subscriptionPeriod?.unit. Detail ada di Penawaran langganan Android.

Langkah berikutnya untuk pendapatan

Bagian berjudul “Langkah selanjutnya pendapatan”

Setelah alur pembelian berfungsi, gunakan Strategi Pendapatan untuk merencanakan funnel berbayar pertama Anda: cakupan produk, ASO, harga, penempatan paywall, analitik, dan umpan balik churn.

Produk tidak dimuat

  • Pastikan bundle ID / application ID sesuai dengan konfigurasi store.
  • Konfirmasi bahwa product ID aktif dan disetujui (App Store) atau diaktifkan (Google Play).
  • Tunggu beberapa jam setelah membuat produk; propagasi store tidak instan.

Pembelian dibatalkan atau macet

  • Users can cancel mid-flow; wrap calls in try/catch dan tampilkan pesan error yang ramah.
  • Untuk Android, pastikan akun uji menginstal aplikasi dari Play Store (internal track) agar Billing berfungsi.
  • Periksa logcat/Xcode untuk error billing saat dijalankan di perangkat.

Status langganan tidak benar

  • Gunakan getPurchases() untuk membandingkan data store dengan cache entitlement lokal Anda.
  • Di Android, selalu kueri Google Play Developer API dengan purchaseToken to obtain expiration dates or refund status.
  • Di iOS, periksa isActive/expirationDate dan validasi receipt untuk mendeteksi pengembalian dana atau pencabutan.

Jika Anda menggunakan Panduan Memulai untuk merencanakan persetujuan store dan distribusi, hubungkan dengan Menggunakan @capgo/native-purchases untuk kemampuan native saat menggunakan @capgo/native-purchases, @capgo/capacitor-in-app-review untuk detail implementasi di @capgo/capacitor-in-app-review, Menggunakan @capgo/capacitor-in-app-review untuk kapabilitas native di bagian Menggunakan @capgo/capacitor-in-app-review, @capgo/capacitor-native-market untuk detail implementasi di @capgo/capacitor-native-market, dan Menggunakan @capgo/capacitor-native-market untuk kemampuan native di Menggunakan @capgo/capacitor-native-market.