내용으로 건너뛰기

Getting Started에서 계속

네이티브 구매 GitHub 저장소

AI-Assisted Setup을 사용하여 플러그인을 설치할 수 있습니다. AI 도구에 Capgo 스킬을 추가하려면 다음 명령어를 사용하세요:

터미널 창
npx skills add https://github.com/Cap-go/capgo-skills --skill capacitor-plugins

그런 다음 다음 프롬프트를 사용하세요:

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

만약 Manual Setup을 선호한다면, 다음 명령어를 실행하여 플러그인을 설치하고 아래에 있는 플랫폼에 맞는 지침을 따르시오:

  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();
    • App Store Connect에서 내 앱 제품 및 구독을 만들세요.
    • StoreKit Local Testing 또는 Sandbox 테스터를 사용하여 QA를 진행하세요.
    • 매니페스트 편집이 필요하지 않습니다. 제품이 승인되었는지 확인하세요.

구매 서비스 예제

구매 서비스 예제 섹션
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 + AndroidSKU/Product ID configured in App Store Connect / Google Play Console.
productType안드로이드 전용PURCHASE_TYPE.INAPP 또는 PURCHASE_TYPE.SUBS또는 INAPP. 기본값 SUBS . 항상 설정
planIdentifier구독을 위한안드로이드 구독
billingPlanTypeiOS 구독StoreKit 결제 플랜을 사용하여 구입합니다. 'monthly' 월별 결제 옵션을 노출할 때 12개월의 약속이 있는 경우 product.pricingTerms iOS
quantity인앱 구매에만 사용되며 기본값은 Android는 항상 1개의 항목을 구매합니다. 1iOS + Android
appAccountTokeniOS구매와 관련된 사용자 ID입니다. 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
  • : 구독에는, 및 StoreKit 2 리스너 지원이 포함됩니다. 앱 내 구매는 서버 수신 확인이 필요합니다. isActive, expirationDate, willCancelAndroid
  • 은 채워지지 않습니다. Google Play 개발자 __CAPGO_KEEP_0__에 Google Play Developer API를 호출하여: isActive/expirationDate API purchaseToken 권위적인 상태를 위해. purchaseState 해야 합니다. PURCHASED 그리고 isAcknowledged 해야 합니다. true.

API 빠른 참조

API 빠른 참조
  • isBillingSupported() – StoreKit / Google Play 가용성을 확인하세요.
  • getProduct() / getProducts() – 가격, 지역화된 제목, 설명, 소개 제안 및 iOS 가격 조건을 가져오세요.
  • purchaseProduct() – StoreKit 2 또는 Billing client 구매 흐름을 시작하세요. iOS 월간 약속 결제 계획도 포함됩니다.
  • restorePurchases() – 과거 구매를 재생하고 현재 기기와 동기화하세요.
  • getPurchases() – iOS 거래 목록 또는 Play Billing 구매 목록을 표시하세요.
  • manageSubscriptions() – 네이티브 구독 관리 UI를 열어주세요.
  • addListener('transactionUpdated') – iOS에서 앱이 시작될 때 StoreKit 2 거래를 처리하세요.

Best practices

Best practices
  1. 스토어 가격 표시 – 애플은 표시를 요구합니다. product.title 그리고 product.priceString; 절대 하드 코딩하지 마세요.
  2. 사용 appAccountToken – 사용자 ID에서 UUID (v5)를 결정적으로 생성하여 구매를 계정에 연결하세요.
  3. 서버에서 유효성 검사 – iOS에서 receipt (iOS) / purchaseToken Android에서 사용자 인증을 위해 백엔드에 전송하세요.
  4. 오류를 잘 처리하세요. – 사용자 취소, 네트워크 오류 및 비지원 결제 환경을 확인하세요.
  5. 잘 테스트하세요.iOS 샌드박스 가이드Android 샌드박스 가이드.
  6. 복원 및 관리를 제안하세요.restorePurchases() 다음 단계 manageSubscriptions().

구매 흐름이 작동하면 수입 플레이북 첫 번째 유료 채널을 계획하는 데 도움이 됩니다: 제품 범위, ASO, 가격, 결제 벽, 분석, churn feedback.

문제 해결

  • 제품 로드가 안됨
  • bundle ID / 애플리케이션 ID가 스토어 구성과 일치하는지 확인하세요.
  • 제품 ID가 활성화되고 승인된 상태인지 (App Store) 또는 활성화된 상태인지 (Google Play) 확인하세요.

제품을 생성한 후 몇 시간 기다리세요; 스토어 전파가 즉시 이루어지지 않습니다.

  • 구매가 취소되거나 멈춤 try/catch 그리고 사용자 친화적인 오류 메시지를 표시합니다.
  • 안드로이드의 경우, 테스트 계정은 내부 트랙으로 앱을 Play Store에서 설치하여 Billing이 작동하도록 하십시오.
  • 디바이스에서 실행 중인 경우 Billing 오류를 확인하기 위해 logcat/Xcode를 확인하십시오.

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

  • 사용하여 getPurchases() 스토어 데이터와 로컬 권한 캐시를 비교하기 위해 사용하십시오.
  • 안드로이드의 경우, Google Play Developer API에 항상 purchaseToken 을 사용하여 만료 날짜 또는 환불 상태를 얻으십시오.
  • iOS의 경우, isActive/expirationDate 을 확인하고 유효성을 검사하여 환불 또는 취소가 감지되도록 하십시오.

Getting Started에서 계속 진행하십시오.

Getting Started에서 계속 진행하는 절차

이 기능을 사용 중이라면 Getting Started 스토어 승인 및 배포를 계획하고 싶다면 Using @capgo/native-purchases for the native capability in Using @capgo/native-purchases, @capgo/capacitor-in-app-review for the implementation detail in @capgo/capacitor-in-app-review, Using @capgo/capacitor-in-app-review for the native capability in Using @capgo/capacitor-in-app-review, @capgo/capacitor-native-market for the implementation detail in @capgo/capacitor-native-market, and Using @capgo/capacitor-native-market Capgo의 @capgo/capacitor-native-market 기능을 사용하는 데 필요한 것입니다.