コンテンツに進む

Getting Started

  1. パッケージをインストールする

    ターミナルウィンドウ
    bun add @capgo/native-purchases
  2. Sync with native projects

    Terminal window
    bunx cap sync
  3. Check billing support

    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 products directly from the stores

    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. Implement purchase & restore flows

    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();
    • StoreKit Local Testing または Sandbox テスターを使用して QA を実行します。
    • マニフェストの編集は必要ありません。製品が承認されていることを確認してください。
    • Google Play Console でインアプリ製品とサブスクリプションを作成します。
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,
}),
});
}
}
オプションプラットフォーム説明
productIdentifieriOS + AndroidApp Store Connect / Google Play Console で設定された SKU / Product ID
productTypeAndroid onlyPURCHASE_TYPE.INAPP または PURCHASE_TYPE.SUBS. Defaults to INAPP. Always set to SUBS サブスクリプション用
planIdentifierAndroid のサブスクリプションGoogle Play Console から取得する基本プラン ID。サブスクリプションの場合必須、iOS とインアプリ購入の場合無視
billingPlanTypeiOS のサブスクリプションStoreKit の課金プランを購入する際に使用する。 'monthly' for 月額課金の場合、12 か月間のコミットメントを表す場合 product.pricingTerms for 月額課金の場合、12 か月間のコミットメントを表す場合
quantityexposes that option.Only for in-app purchases, defaults to 1. Android always purchases one item.
appAccountTokeniOS + AndroidUUID/文字列で購入をユーザーに紐付けます。iOSでは必ずUUIDで、Androidでは64文字以内に暗号化された文字列を受け付けます。
isConsumableAndroidを設定します。 true を自動的に消費するように設定します。消耗可能なものの特権を与えられた後、デフォルトは false.

を使用すると、すべてのストアから報告されるトランザクションのクロスプラットフォームビューが得られます。 getPurchases() クリップボードにコピー

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: サブスクリプションには isActive, expirationDate, willCancel、およびStoreKit 2リスナーをサポートする。インアプリ購入にはサーバー受領の検証が必要です。
  • Android: isActive/expirationDate は、Google Play Developer APIに、 purchaseToken の権威あるステータスを確認するために呼び出す必要があります。 purchaseStatePURCHASEDisAcknowledgedtrue.

APIのクイックリファレンス

「API」のクイックリファレンス
  • isBillingSupported() – StoreKit / Google Play の利用可能性を確認する。
  • getProduct() / getProducts() – iOS の価格、ローカライズされたタイトル、説明、イントロオファー、サポートされている iOS の価格条件を取得する。
  • purchaseProduct() – StoreKit 2 または Billing クライアントの購入フローを開始する、iOS の月額コミットメントの請求計画を含む。
  • restorePurchases() – 歴史的な購入を再生し、現在のデバイスにsyncする。
  • getPurchases() – iOS のすべての取引またはPlay Billing の購入をリストする。
  • manageSubscriptions() – ネイティブのサブスクリプション管理UIを開く。
  • addListener('transactionUpdated') – アプリが起動したときに、iOS のみの保留中のStoreKit 2 の取引を処理する。

ベストプラクティス

「ベストプラクティス」
  1. ストア価格の表示 – Apple は表示することを要求する product.title そして、ハードコーディングは避けること。 product.priceString__CAPGO_KEEP_0__を使用して、
  2. 購入をユーザーアカウントに紐付けするために、ユーザーIDからUUID(v5)を決定論的に生成してください。 appAccountToken サーバーサイドで検証する
  3. __CAPGO_KEEP_0__を送信して (iOS) / (Android) をバックエンドに送信して検証してください。 receipt エラーを柔軟に処理する purchaseToken __CAPGO_KEEP_0__でユーザーキャンセル、ネットワークエラー、非対応の請求環境を確認してください。
  4. 徹底的にテストする __CAPGO_KEEP_0__に従って、
  5. iOSの場合、 Androidの場合 iOS サンドボックス ガイドAndroid サンドボックス ガイド.
  6. Offer restore & 管理 – add UI ボタンを restorePurchases()manageSubscriptions().

購入フローが機能したら、 Revenue Playbook を使用して、最初の有料チャネルを計画してください: 製品範囲、ASO、価格設定、パイウォールの配置、分析、および脱落フィードバック。

トラブルシューティング

Section titled “Troubleshooting”

製品が読み込まれません

  • Bundle ID / アプリケーション ID がストアの設定と一致していることを確認してください。
  • 製品 ID が有効かつ承認済み (App Store) または有効化済み (Google Play) であることを確認してください。
  • 製品を作成した後数時間待ってください。ストアのプロパゲーションは即時ではありません。

購入がキャンセルされたり、途中で止まったりします

  • ユーザーは途中でキャンセルすることができます。呼び出しを囲んで、フレンドリーなエラーメッセージを表面化してください。 try/catch Android の場合、テストアカウントは Play Store (内部トラック) からアプリをインストールするようにして、Billing が機能するようにしてください。
  • デバイスで実行している場合、Billing エラーを確認するには logcat/Xcode を参照してください。
  • サブスクリプションの状態が不正です

Capgo

  • Capacitor getPurchases() ローカルエンタイトルキャッシュとストアデータを比較します。
  • Androidでは、常にGoogle Play Developer APIにアクセスして purchaseToken 期限切れ日または払い戻しステータスを取得します。
  • iOSでは、 isActive/expirationDate と受け取りを検証して払い戻しまたは取り消しを検出します。

Getting Startedから続けてください

「Getting Startedから続けてください」

Capacitorを使用している場合、 Getting Started ストアの承認と配布を計画するには、 Using @capgo/native-purchases for the native capability in Using @capgo/native-purchases, @capgo/capacitor-in-app-review 実装詳細については @capgo/capacitor-in-app-review を参照してください。 @capgo/capacitor-in-app-review を使用します。 @capgo/capacitor-in-app-review のネイティブ機能については @capgo/capacitor-native-market @capgo/capacitor-native-market の実装詳細については、 @capgo/capacitor-native-market を使用します。 @capgo/capacitor-native-market のネイティブ機能については