Panduan Memulai
Salin prompt setup yang berisi langkah install dan panduan markdown lengkap untuk plugin ini.
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.
Instalasi
Bagian berjudul “Instalasi”Anda bisa menggunakan AI-Assisted Setup kami untuk menginstal plugin ini. Tambahkan skill Capgo ke tool AI Anda dengan command berikut:
npx skills add https://github.com/Cap-go/capgo-skills --skill capacitor-pluginsLalu 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:
-
Instal package
Jendela terminal bun add @capgo/native-purchases -
Sync dengan proyek native
Jendela terminal bunx cap sync -
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');} -
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);}); -
Implementasi flow purchase & restore
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, // Android base plan id, required unless offerToken is passed; ignored on iOSproductType: 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.
- Buat produk in-app dan langganan di Google Play Console.
- Upload setidaknya satu build internal test dan tambahkan license tester.
- Tambahkan permission billing ke
AndroidManifest.xml:
<uses-permission android:name="com.android.vending.BILLING" /> - Buat produk dan langganan in-app di App Store Connect.
Contoh service pembelian
Bagian berjudul “Contoh service pembelian”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, }), }); }}Opsi pembelian wajib
Bagian berjudul “Opsi pembelian wajib”| Opsi | Platform | Deskripsi |
|---|---|---|
productIdentifier | iOS + Android | SKU/Product ID yang dikonfigurasi di App Store Connect / Google Play Console. |
productType | Hanya Android | PURCHASE_TYPE.INAPP atau PURCHASE_TYPE.SUBS. Defaultnya adalah INAPP. Selalu diatur ke SUBS untuk langganan. |
planIdentifier | Langganan Android | Base 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. |
offerToken | Android | Token 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. |
billingPlanType | Langganan iOS | StoreKit billing plan yang akan dibeli. Gunakan 'monthly' untuk penagihan bulanan dengan komitmen 12 bulan ketika product.pricingTerms mengekspos opsi tersebut. |
quantity | iOS | Hanya untuk in-app purchases, default ke 1. Android selalu membeli satu item. |
appAccountToken | iOS + Android | UUID/string yang menghubungkan pembelian ke pengguna Anda. Wajib berupa UUID di iOS; Android menerima string terofusiasi apa pun hingga 64 karakter. |
isConsumable | Android | Setel ke true untuk otomatis mengonsumsi token setelah memberikan entitlement untuk item yang dapat dikonsumsi. Defaultnya false. |
Memeriksa status entitlement
Bagian berjudul “Memeriksa status entitlement”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); }});Perilaku platform
Bagian berjudul “Perilaku platform”- iOS: Langganan mencakup
isActive,expirationDate,willCancel, serta dukungan listener StoreKit 2. In-app purchase memerlukan validasi receipt di server. - Android:
isActive/expirationDatetidak terisi; panggil Google Play Developer API denganpurchaseTokenuntuk status yang paling akurat.purchaseStateharusPURCHASEDdanisAcknowledgedharustrue.
Referensi cepat API
Bagian berjudul “API quick reference”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).
Praktik terbaik
Bagian berjudul “Best practices”- Tampilkan harga toko – Apple mewajibkan menampilkan
product.titledanproduct.priceString; jangan pernah hardcode. - Gunakan
appAccountToken– generate UUID (v5) secara deterministik dari user ID Anda untuk menghubungkan pembelian ke akun. - Validasi server-side – kirim
receipt(iOS) /purchaseToken(Android) ke backend Anda untuk verifikasi. - Tangani error dengan baik – periksa pembatalan pengguna, kegagalan jaringan, dan lingkungan billing yang tidak didukung.
- Uji secara menyeluruh – follow the panduan sandbox iOS dan panduan sandbox Android.
- Penawaran restore & manajemen – tambahkan tombol UI yang terhubung ke
restorePurchases()danmanageSubscriptions().
Breaking (typings TypeScript)
Bagian berjudul “Breaking (TypeScript typings)”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.
Pemecahan Masalah
Bagian berjudul “Troubleshooting”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/catchdan 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
purchaseTokento obtain expiration dates or refund status. - Di iOS, periksa
isActive/expirationDatedan validasi receipt untuk mendeteksi pengembalian dana atau pencabutan.
Lanjutkan dari Getting Started
Bagian berjudul “Lanjutkan dari Getting Started”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.