Memulai
-
Instal paket
Terminal window npm i @capgo/native-purchasesTerminal window pnpm add @capgo/native-purchasesTerminal window yarn add @capgo/native-purchasesTerminal window bun add @capgo/native-purchases -
Sinkronkan dengan proyek native
Terminal window npx cap syncTerminal window pnpm cap syncTerminal window yarn cap syncTerminal window bunx cap sync -
Periksa dukungan billing
import { NativePurchases } from '@capgo/native-purchases';const { isBillingSupported } = await NativePurchases.isBillingSupported();if (!isBillingSupported) {throw new Error('Billing tidak tersedia di perangkat ini');} -
Muat produk langsung dari toko
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, // Gunakan PURCHASE_TYPE.INAPP untuk produk satu kali});products.forEach((product) => {console.log(product.title, product.priceString);}); -
Implementasikan alur pembelian & pemulihan
import { NativePurchases, PURCHASE_TYPE } from '@capgo/native-purchases';const monthlyPlanId = 'monthly-plan'; // Base Plan ID dari Google Play Consoleconst transaction = await NativePurchases.purchaseProduct({productIdentifier: 'com.example.premium.monthly',planIdentifier: monthlyPlanId, // WAJIB untuk langganan Android, diabaikan di iOSproductType: PURCHASE_TYPE.SUBS,quantity: 1,});console.log('Transaction ID', transaction.transactionId);await NativePurchases.restorePurchases();- Buat produk in-app dan langganan di App Store Connect.
- Gunakan StoreKit Local Testing atau Sandbox tester untuk QA.
- Tidak perlu edit manifest. Pastikan produk Anda disetujui.
- Buat produk in-app dan langganan di Google Play Console.
- Unggah setidaknya build uji internal dan tambahkan tester lisensi.
- Tambahkan izin billing ke
AndroidManifest.xml:
<uses-permission android:name="com.android.vending.BILLING" /> - Buat produk in-app dan langganan di App Store Connect.
Contoh layanan pembelian
Section titled “Contoh layanan 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 saja)
async initialize() { const { isBillingSupported } = await NativePurchases.isBillingSupported(); if (!isBillingSupported) throw new Error('Billing tidak tersedia');
const { products } = await NativePurchases.getProducts({ productIdentifiers: [this.premiumProduct, this.monthlySubId], productType: PURCHASE_TYPE.SUBS, });
console.log('Produk dimuat', 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, // WAJIB untuk langganan Android 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) { // simpan hak akses secara lokal console.log('Membuka kunci', productIdentifier); }
private async refreshEntitlements() { const { purchases } = await NativePurchases.getPurchases({ productType: PURCHASE_TYPE.SUBS, }); console.log('Pembelian saat ini', purchases); }
private async handleTransaction(transaction: Transaction) { console.log('Update transaksi StoreKit:', 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 yang diperlukan
Section titled “Opsi pembelian yang diperlukan”| Opsi | Platform | Deskripsi |
|---|---|---|
productIdentifier | iOS + Android | SKU/Product ID yang dikonfigurasi di App Store Connect / Google Play Console. |
productType | Android saja | PURCHASE_TYPE.INAPP atau PURCHASE_TYPE.SUBS. Default ke INAPP. Selalu set ke SUBS untuk langganan. |
planIdentifier | Langganan Android | Base Plan ID dari Google Play Console. Diperlukan untuk langganan, diabaikan di iOS dan pembelian in-app. |
quantity | iOS | Hanya untuk pembelian in-app, default ke 1. Android selalu membeli satu item. |
appAccountToken | iOS + Android | UUID/string yang menghubungkan pembelian ke pengguna Anda. Harus UUID di iOS; Android menerima string tersamarkan hingga 64 karakter. |
isConsumable | Android | Set ke true untuk otomatis mengonsumsi token setelah memberikan hak akses untuk consumable. Default ke false. |
Memeriksa status hak akses
Section titled “Memeriksa status hak akses”Gunakan getPurchases() untuk tampilan lintas platform dari setiap transaksi yang dilaporkan toko:
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('Langganan iOS aktif sampai', purchase.expirationDate); }
const isAndroidIapValid = ['PURCHASED', '1'].includes(purchase.purchaseState ?? '') && purchase.isAcknowledged;
if (isAndroidIapValid) { console.log('Berikan hak akses in-app untuk', purchase.productIdentifier); }});Perilaku platform
Section titled “Perilaku platform”- iOS: Langganan mencakup
isActive,expirationDate,willCancel, dan dukungan listener StoreKit 2. Pembelian in-app memerlukan validasi receipt server. - Android:
isActive/expirationDatetidak diisi; panggil Google Play Developer API denganpurchaseTokenuntuk status otoritatif.purchaseStateharusPURCHASEDdanisAcknowledgedharustrue.
Referensi API cepat
Section titled “Referensi API cepat”isBillingSupported()– periksa ketersediaan StoreKit / Google Play.getProduct()/getProducts()– ambil harga, judul lokal, deskripsi, penawaran intro.purchaseProduct()– mulai alur pembelian StoreKit 2 atau Billing client.restorePurchases()– putar ulang pembelian historis dan sinkronkan ke perangkat saat ini.getPurchases()– daftar semua transaksi iOS atau pembelian Play Billing.manageSubscriptions()– buka UI manajemen langganan native.addListener('transactionUpdated')– tangani transaksi StoreKit 2 yang tertunda saat aplikasi Anda dimulai (iOS saja).
Praktik terbaik
Section titled “Praktik terbaik”- Tampilkan harga toko – Apple mengharuskan menampilkan
product.titledanproduct.priceString; jangan hardcode. - Gunakan
appAccountToken– buat UUID secara deterministik (v5) dari ID pengguna Anda untuk menghubungkan pembelian ke akun. - Validasi sisi server – 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 – ikuti panduan sandbox iOS dan panduan sandbox Android.
- Tawarkan pemulihan & manajemen – tambahkan tombol UI yang terhubung ke
restorePurchases()danmanageSubscriptions().
Pemecahan masalah
Section titled “Pemecahan masalah”Produk tidak dimuat
- Pastikan bundle ID / application ID cocok dengan konfigurasi toko.
- Konfirmasikan product ID aktif dan disetujui (App Store) atau diaktifkan (Google Play).
- Tunggu beberapa jam setelah membuat produk; propagasi toko tidak instan.
Pembelian dibatalkan atau macet
- Pengguna dapat membatalkan di tengah alur; bungkus panggilan dalam
try/catchdan tampilkan pesan error yang ramah. - Untuk Android, pastikan akun uji menginstal aplikasi dari Play Store (track internal) agar Billing berfungsi.
- Periksa logcat/Xcode untuk error billing saat berjalan di perangkat.
Status langganan salah
- Gunakan
getPurchases()untuk membandingkan data toko dengan cache hak akses lokal Anda. - Di Android, selalu kueri Google Play Developer API dengan
purchaseTokenuntuk mendapatkan tanggal kedaluwarsa atau status refund. - Di iOS, periksa
isActive/expirationDatedan validasi receipt untuk mendeteksi refund atau revokasi.