메뉴로 바로가기

Getting Started

  1. 패키지를 설치하세요

    터미널 창
    bun add @capgo/native-purchases
  2. 자연어 프로젝트와 동기화

    터미널 창
    bunx cap sync
  3. 청구 지원 확인

    import { NativePurchases } from '@capgo/native-purchases';
    const { isBillingSupported } = await NativePurchases.isBillingSupported();
    if (!isBillingSupported) {
    throw new Error('Billing is not available on this device');
    }
  4. 스토어에서 직접 제품 로드

    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. 구매 및 복원 흐름 구현

    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를 진행하십시오.
    • manifest 편집이 필요하지 않습니다. 제품이 승인되어야 합니다.
    • __CAPGO_KEEP_0__

구매 서비스 예시

구매 서비스 예시
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 + Android__CAPGO_KEEP_0__
productType__CAPGO_KEEP_0__PURCHASE_TYPE.INAPP or PURCHASE_TYPE.SUBS. 기본값은 INAPP. 항상 SUBS 구독
planIdentifier구글 플레이 콘솔의 Base Plan ID. 구독에 필요하고 iOS 및 인앱 구매에서는 무시됩니다.스토어 키트 billing plan을 구입하기 위해 사용하세요. 월 12개월 계약과 함께 월별 청구를 위해
billingPlanType__CAPGO_KEEP_0____CAPGO_KEEP_0__ 'monthly' __CAPGO_KEEP_0__ product.pricingTerms __CAPGO_KEEP_0__을 공개합니다.
quantityiOS구매 내역이 앱 내에서만 사용할 수 있으며 기본값은 1. 안드로이드는 항상 1개의 아이템을 구매합니다.
appAccountTokeniOS + Android사용자와 구매를 연결하는 UUID/문자열입니다. iOS에서는 UUID가 필요하며, 안드로이드에서는 64자 이내의 암호화된 문자열을 허용합니다.
isConsumable안드로이드기본값은 true 입니다. false.

구매가 소비 가능한 경우, 사용자에게 권한을 부여한 후 자동으로 토큰을 소비합니다. 기본값은

입니다.

권한 상태를 확인하는 중입니다. getPurchases() for a cross-platform view of every transaction the stores report:

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구독은
  • 구글 플레이 개발자 __CAPGO_KEEP_0__를 호출하여: isActive/expirationDate are not populated; call the Google Play Developer API with the purchaseToken 는 필수입니다. purchaseState 그리고 PURCHASED and isAcknowledged must be true.

API quick reference

API quick reference
  • isBillingSupported() – 앱스토어 / 구글 플레이스토어 사용 가능 여부를 확인합니다.
  • getProduct() / getProducts() – 가격, 지역화된 제목, 설명, 소개 오퍼, 그리고 iOS 가격 조건을 가져옵니다.
  • purchaseProduct() – StoreKit 2 또는 Billing 클라이언트 구매 흐름을 시작합니다. iOS 월간 약속 결제 계획도 포함됩니다.
  • restorePurchases() – 역사적인 구매를 재생하고 현재 기기와 동기화합니다.
  • getPurchases() – iOS 거래 또는 Play Billing 구매 목록을 표시합니다.
  • manageSubscriptions() – 네이티브 구독 관리 UI를 열어줍니다.
  • addListener('transactionUpdated') – 앱이 시작될 때 StoreKit 2 거래를 처리합니다 (iOS 전용).
  1. 스토어 가격을 표시하세요. – 애플은 가격을 표시하는 것을 요구합니다. product.title 그리고 product.priceString; 결코 하드 코딩하지 마세요.
  2. 사용 appAccountToken – 사용자 ID에서 UUID (v5)를 결정적으로 생성하여 구매를 사용자 계정과 연결하세요.
  3. 서버에서 검증하세요 – (iOS) / receipt (Android) 구매를 검증하기 위해 백엔드에 전송하세요. purchaseToken 오류를 잘 처리하세요
  4. – 사용자 취소, 네트워크 오류 및 지원되지 않는 결제 환경을 확인하세요. __CAPGO_KEEP_0__
  5. 정확하게 테스트하세요iOS 샌드박스 가이드Android 샌드박스 가이드.
  6. 구매 후 복원 및 관리 – UI 버튼을 restorePurchases()manageSubscriptions().

수익성 다음 단계

수익성 다음 단계

구매 흐름이 작동한 후 수익성 플레이북 __CAPGO_KEEP_0__:

제품이 로드되지 않습니다

  • bundle ID / 애플리케이션 ID가 스토어 구성과 일치하는지 확인하세요.
  • 제품 ID가 활성화되고 승인된 상태인지 확인하세요 (애플 스토어) 또는 활성화된 상태인지 확인하세요 (구글 플레이).
  • 제품을 생성한 후 몇 시간 기다리세요; 스토어 전파는 즉시 이루어지지 않습니다.

구매가 취소되거나 중단되었습니다

  • 사용자는 중간에 취소할 수 있습니다; wrap calls in try/catch 안드로이드에서 테스트 계정은 Play Store (내부 트랙)에서 앱을 설치하여 Billing이 작동하도록 하세요.
  • 장치에서 실행 중일 때 Billing 오류를 확인하세요.
  • 로그캣/Xcode

구독 상태가 올바르지 않습니다

  • 사용하여 getPurchases() 스토어 데이터를 로컬 권한 캐시와 비교하세요.
  • 안드로이드에서 항상 Google Play Developer API와 purchaseToken 을 사용하여 만료 날짜 또는 환불 상태를 얻으세요.
  • iOS에서 isActive/expirationDate 을 확인하고 환불 또는 취소 상태를 검증하세요.

Getting Started에서 계속하세요

Getting Started에서 계속하세요

Capgo를 사용하여 Getting Started 스토어 승인 및 배포를 계획하는 경우, 이를 연결하세요. @capgo/구간갑세요 구간갑세요 게성요 구간갑세요 @capgo/구간갑세요, @capgo/capacitor-총세요세요 게성요 게성요 총세요 @capgo/capacitor-총세요, Using @capgo/capacitor-총세요 구간갑세요 게성요 게성요 총세요 Using @capgo/capacitor-총세요, @capgo/capacitor-총게성요 게성요 게성요 총게성요 @capgo/capacitor-총게성요, and Using @capgo/capacitor-총게성요 구간갑세요 게성요 게성요 총게성요 Using @capgo/capacitor-총게성요.