알림: 2022년 8월 2일부터 모든 신규 앱은 결제 라이브러리 버전 4 이상을 사용해야 합니다. 2022년 11월 1일부터는 기존 앱의 모든 업데이트에도 결제 라이브러리 버전 4 이상이 요구됩니다. 자세히 알아보기

Google Play 결제 라이브러리 4에서 5로의 이전 가이드

컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요.

이 주제에서는 Google Play 결제 라이브러리 4에서 Google Play 결제 라이브러리 5로 이전하는 방법과 새로운 정기 결제 기능을 사용하는 방법을 설명합니다.

개요

Google Play 결제 라이브러리 5에서는 정기 결제 기본 요금제와 정기 결제 혜택을 도입했습니다. 이러한 기능은 정기 결제를 판매하는 방식을 확장하고 계속 늘어나는 SKU를 만들고 관리할 필요를 제거하여 운영 비용을 줄입니다. 자세한 내용은 Play Console의 최근 정기 결제 변경사항을 참고하세요.

기존의 모든 정기 결제 제품은 Play 결제 라이브러리 5의 2022년 5월 출시와 새로운 정기 결제 플랫폼에 따라 이 새로운 패러다임으로 자동 전환되었습니다. 이 전환에 관한 자세한 내용은 Play Console 도움말에서 이전 정기 결제 사용 섹션을 참고하세요.

Play Console 또는 Play Developer API를 사용하면 여러 기본 요금제(각각 여러 혜택 포함)가 있는 단일 정기 결제를 구성할 수 있습니다. 정기 결제 혜택에는 유연한 가격 모델과 지원 옵션이 있습니다. 다양한 자동 갱신 및 선불 요금제를 사용하여 정기 결제 수명 주기 동안 혜택을 만들 수 있습니다. 자세한 내용은 통합 가이드를 참고하세요.

이전 단계

제품 카탈로그 만들기

앱을 이전하기 전에 Play 결제 라이브러리 5 통합을 위한 새 정기 결제 플랫폼의 항목 구조에 따라 새 제품을 만드는 것이 좋습니다. 단일 정기 결제에서 동일한 사용 권한 혜택을 나타내는 이전 카탈로그의 중복 제품을 통합하고, 기본 요금제 및 혜택 구성을 사용하여 제공하려는 모든 옵션을 나타낼 수 있습니다. 이 권장사항에 관한 자세한 내용은 Play Console 도움말에서 이전 정기 결제 사용 섹션을 참고하세요.

2022년 5월 출시 이후에는 전환된 정기 결제 제품을 수정하지 않는 것이 좋습니다. 이러한 이전 빌드에 영향을 미칠 수 있는 변경사항을 도입하지 않고 지원 중단된 메서드(예: querySkuDetailsAsync())를 사용하는 앱 버전으로 판매되도록 제품을 그대로 두어야 합니다.

전환 프로세스를 통해 2022년 5월 전 카탈로그에 있던 정기 결제 제품은 읽기 전용으로 되어 기존 통합에 문제를 일으킬 수 있는 실수로 인한 변경을 방지합니다. 이러한 정기 결제도 변경할 수는 있지만 프런트엔드 및 백엔드 통합에 영향을 미칠 수 있습니다.

  • 프런트엔드에서 querySkuDetailsAsync()를 사용하여 정기 결제 제품 세부정보를 가져오는 앱 버전은 이전 버전과 호환되는 기본 요금제 및 혜택만 판매할 수 있으며, 이전 버전과 호환되는 기본 요금제 및 혜택의 조합은 하나만 있을 수 있습니다. 따라서 전환된 정기 결제에 새 요금제나 혜택을 추가하면 추가된 새 기본 요금제나 혜택은 이러한 이전 버전의 앱에서 판매할 수 없습니다.

  • 백엔드에서는 Play Console UI에서 전환된 정기 결제를 수정하면 inappproducts 엔드포인트를 사용하여 이를 관리할 수 없습니다(이 목적으로 엔드포인트를 호출한 경우). 또한 새로운 정기 결제 구매 상태 엔드포인트(purchases.subscriptionsv2.get)로 이전하여 이러한 정기 결제 구매를 관리해야 합니다. 이전 구매 상태 엔드포인트(purchases.subscriptions.get)는 이전 버전과 호환되는 기본 요금제 및 혜택 구매를 처리하는 데 필요한 데이터만 반환하기 때문입니다. 자세한 내용은 정기 결제 구매 상태 관리 섹션을 참고하세요.

새로운 API로 정기 결제 카탈로그 관리

Google Play Developer API로 정기 결제 제품 카탈로그를 자동으로 관리하는 경우 새로운 정기 결제 제품 정의 엔드포인트를 사용하여 정기 결제와 기본 요금제, 혜택을 만들고 관리해야 합니다. 이 버전의 제품 카탈로그 API 변경사항에 관한 자세한 내용은 2022년 5월 정기 결제 기능 가이드를 참고하세요.

Google Play 결제 정기 결제의 자동 제품 카탈로그 관리 모듈을 이전하려면 inappproducts API를 새로운 Subscription Publishing API로 대체하여 정기 결제 카탈로그를 관리하고 게시하세요. 새로운 엔드포인트는 세 가지입니다.

이러한 새로운 엔드포인트에는 기본 요금제 및 혜택 태그, 지역 타겟팅, 선불 요금제 등 카탈로그의 새로운 기능을 모두 활용하는 데 필요한 기능이 모두 있습니다.

일회성 구매 제품의 인앱 상품 카탈로그를 관리하려면 inappproducts API를 계속 사용해야 합니다.

.

지원 중단된 메서드(예: querySkuDetailsAsync())를 사용하는 앱 버전은 이전 버전과 호환되지 않는 기본 요금제나 혜택을 판매할 수 없습니다. 이전 버전과 호환되는 혜택 관련 내용은 여기에서 확인할 수 있습니다.

Google Play 결제 라이브러리 업데이트

새 정기 결제 제품 카탈로그를 만들고 나면 Google 결제 라이브러리 5로 앱을 이전할 수 있습니다. 기존 Play 결제 라이브러리 종속 항목을 앱의 build.gradle 파일의 업데이트된 버전으로 바꿉니다.

dependencies {
    def billingVersion = "5.0.0"

    implementation "com.android.billingclient:billing:$billingVersion"
}

메서드 호출을 수정하지 않았더라도 프로젝트가 즉시 빌드됩니다. Play 결제 라이브러리 5는 이전 버전과 호환되기 때문입니다. 하지만 SKU 개념은 지원 중단된 것으로 간주합니다.

결제 클라이언트 초기화 및 Google Play 연결 설정

Android 앱에서 구매를 시작하는 첫 번째 단계는 동일하게 유지됩니다.

구매 가능한 제품 표시

사용자가 구매할 수 있는 모든 혜택을 획득하려면 다음 단계를 따르세요.

  • SkuDetailsParamsQueryProductDetailsParams로 바꿉니다.
  • BillingClient.queryProductDetailsAsync()를 사용하도록 BillingClient.querySkuDetailsAsync() 호출을 전환합니다.

이제 쿼리 결과는 SkuDetails가 아닌 ProductDetails입니다. 각 ProductDetails 항목에는 제품(ID, 제품명, 유형 등)에 관한 정보가 포함되어 있습니다. 정기 결제 제품의 경우 ProductDetails에는 정기 결제 혜택 세부정보 목록인 List<ProductDetails.SubscriptionOfferDetails>가 포함되어 있습니다. 일회성 구매 제품의 경우 ProductDetails에는 ProductDetails.OneTimePurchaseOfferDetails가 포함되어 있습니다. 이를 통해 사용자에게 표시할 혜택을 결정할 수 있습니다.

다음 예는 이러한 변경사항을 적용하기 전과 후의 앱 모습을 보여줍니다.

Kotlin

val skuList = ArrayList<String>()

skuList.add("up_basic_sub")

val params = SkuDetailsParams.newBuilder()

params.setSkusList(skuList).setType(BillingClient.SkuType.SUBS)

billingClient.querySkuDetailsAsync(params.build()) {
    billingResult,
    skuDetailsList ->
    // Process the result
}

자바

List<String> skuList = new ArrayList<>();

skuList.add("up_basic_sub");

SkuDetailsParams.Builder params = SkuDetailsParams.newBuilder();

params.setSkusList(skuList).setType(SkuType.SUBS);

billingClient.querySkuDetailsAsync(params.build(),
    new SkuDetailsResponseListener() {
        @Override
        public void onSkuDetailsResponse(BillingResult billingResult,
                List<SkuDetails> skuDetailsList) {
            // Process the result.
        }
    }
);

Kotlin

val productList =
    listOf(
        QueryProductDetailsParams.Product.newBuilder()
            .setProductId("up_basic_sub")
            .setProductType(BillingClient.ProductType.SUBS)
            .build()
    )

val params = QueryProductDetailsParams.newBuilder().setProductList(productList)

billingClient.queryProductDetailsAsync(params.build()) {
    billingResult,
    productDetailsList ->
    // Process the result
}

자바

ImmutableList<Product> productList = ImmutableList.of(Product.newBuilder()
                                            .setProductId("up_basic_sub")
                                            .setProductType(ProductType.SUBS)
                                            .build());

QueryProductDetailsParams params = QueryProductDetailsParams.newBuilder()
    .setProductList(productList)
    .build();

billingClient.queryProductDetailsAsync(
        params,
        new ProductDetailsResponseListener() {
                public void onProductDetailsResponse(BillingResult billingResult, List<ProductDetails> productDetailsList) {
                    // Process the result
                }
        }
);

queryProductDetailsAsync의 콜백은 List<ProductDetails>를 반환합니다. 각 ProductDetails 항목에는 제품(ID, 제품명, 유형 등)에 관한 정보가 포함되어 있습니다. 주요 차이점은 이제 정기 결제 제품에도 사용자에게 제공되는 모든 혜택이 포함된 List<ProductDetails.SubscriptionOfferDetails>가 포함된다는 것입니다.

이전 버전의 Play 결제 라이브러리는 새 객체(정기 결제, 기본 요금제, 혜택 등)를 지원하지 않으므로 새 시스템은 각 정기 결제 SKU를 이전 버전과 호환되는 단일 기본 요금제 및 혜택으로 변환합니다. 사용 가능한 일회성 구매 제품도 ProductDetails 객체로 포팅됩니다. 일회성 구매 제품의 혜택 세부정보는 getOneTimePurchaseOfferDetails() 메서드로 액세스할 수 있습니다.

드물게 일부 기기는 오래된 버전의 Google Play 서비스로 인해 ProductDetailsqueryProductDetailsAsync()를 지원하지 않습니다. 이 경우를 적절하게 지원하려면 queryProductDetailsAsync를 호출하기 전에 isFeatureSupported()를 지원하여 PRODUCT_DETAILS 기능을 확인하세요. 응답이 OK이면 기기가 이 기능을 지원하는 것으로, queryProductDetailsAsync()를 호출해도 좋습니다. 응답이 FEATURE_NOT_SUPPORTED이면 대신 querySkuDetailsAsync()를 사용하여 이전 버전과 호환되는 제품 목록을 요청할 수 있습니다. Play 결제 라이브러리 5 이전 버전과의 호환성 기능을 사용하는 방법을 자세히 알아보려면 2022년 5월 정기 결제 기능 가이드를 참고하세요.

혜택 구매 흐름 시작

혜택의 구매 흐름을 시작하는 것은 SKU의 흐름을 시작하는 것과 매우 유사합니다. 버전 5를 사용하여 구매 요청을 시작하려면 다음을 실행하세요.

  • BillingFlowParamsSkuDetails를 사용하는 대신 ProductDetailsParams를 사용합니다.
  • 혜택 세부정보(예: 혜택 ID, 기본 요금제 ID 등)는 SubscriptionOfferDetails 객체를 사용하여 가져올 수 있습니다.

사용자가 선택한 혜택으로 제품을 구매하려면 선택한 혜택의 offerToken을 가져와서 ProductDetailsParams 객체에 전달합니다.

BillingFlowParams 객체를 만든 후 BillingClient를 사용하여 결제 흐름을 시작하는 것은 동일하게 유지됩니다.

다음 예는 이러한 변경사항을 적용하기 전과 후의 앱 모습을 보여줍니다.

Kotlin

// An activity reference from which the billing flow will be launched.
val activity : Activity = ...;
// Retrieve a value for "skuDetails" by calling querySkuDetailsAsync().
val billingFlowParams = BillingFlowParams.newBuilder()
                            .setSkuDetails(skuDetails)
                            .build()

val billingResult = billingClient.launchBillingFlow(activity, billingFlowParams)

자바

// An activity reference from which the billing flow will be launched.
Activity activity = ...;
// Retrieve a value for "skuDetails" by calling querySkuDetailsAsync().
BillingFlowParams billingFlowParams = BillingFlowParams.newBuilder()
        .setSkuDetails(skuDetails)
        .build();

BillingResult billingResult = billingClient.launchBillingFlow(activity, billingFlowParams)

Kotlin

// An activity reference from which the billing flow will be launched.
val activity : Activity = ...;
// Retrieve a value for "productDetails" by calling queryProductDetailsAsync()
// Get the offerToken of the selected offer
val offerToken = productDetails.subscriptionOfferDetails?.get(selectedOfferIndex)?.offerToken

val productDetailsParamsList =
    listOf(
        BillingFlowParams.ProductDetailsParams.newBuilder()
            .setProductDetails(productDetails)
            .setOfferToken(offerToken)
            .build()
    )
val billingFlowParams =
    BillingFlowParams.newBuilder()
        .setProductDetailsParamsList(productDetailsParamsList)
        .build()

// Launch the billing flow
val billingResult = billingClient.launchBillingFlow(activity, billingFlowParams)

자바

// Retrieve a value for "productDetails" by calling queryProductDetailsAsync()
// Get the offerToken of the selected offer
String offerToken = productDetails
                     .getSubscriptionOfferDetails()
                     .get(selectedOfferIndex)
                     .getOfferToken();
// Set the parameters for the offer that will be presented
// in the billing flow creating separate productDetailsParamsList variable
ImmutableList<ProductDetailsParams> productDetailsParamsList =
        ImmutableList.of(
                 ProductDetailsParams.newBuilder()
                     .setProductDetails(productDetails)
                     .setOfferToken(offerToken)
                     .build()
        );

BillingFlowParams billingFlowParams = BillingFlowParams.newBuilder()
            .setProductDetailsParamsList(productDetailsParamsList)
            .build();

// Launch the billing flow
BillingResult billingResult = billingClient.launchBillingFlow(activity, billingFlowParams);

구매 처리

Google Play 결제 라이브러리 5로 구매를 처리하는 것은 이전 버전과 유사합니다.

사용자가 소유한 모든 활성 구매를 가져오고 새 구매를 쿼리하려면 다음을 실행하세요.

  • BillingClient.SkuType 값을 queryPurchasesAsync()에 전달하는 대신 BillingClient.ProductType 값이 포함된 QueryPurchasesParams 객체를 전달합니다.

다음 예는 이러한 변경사항을 적용하기 전과 후의 앱 모습을 보여줍니다.

Kotlin

billingClient.queryPurchasesAsync(BillingClient.SkuType.SUBS) {
    billingResult,
    purchaseList -> {
        // Process the result
    }
}

자바


billingClient.queryPurchasesAsync(
    BillingClient.SkuType.SUBS,
    new PurchasesResponseListener() {
        public void onQueryPurchasesResponse(
                BillingResult billingResult,
                List<Purchase> purchases) {
            // process the result
        }
    }
);

Kotlin

billingClient.queryPurchasesAsync(
    QueryPurchasesParams.newBuilder()
        .setProductType(BillingClient.ProductType.SUBS)
        .build()
) { billingResult, purchaseList ->
    // Process the result
}

자바

billingClient.queryPurchasesAsync(
    QueryPurchasesParams.newBuilder().setProductType(ProductType.SUBS).build(),
    new PurchasesResponseListener() {
        public void onQueryPurchasesResponse(
                BillingResult billingResult,
                List<Purchase> purchases) {
            // Process the result
        }
    }
);

앱 외부 구매대기 중인 거래를 관리하는 단계는 변경되지 않았습니다.

새 API로 정기 결제 구매 상태 관리

이전 단계에서 만든 새 제품의 구매를 처리할 수 있도록 백엔드의 정기 결제 구매 상태 관리 구성요소를 이전해야 합니다. 현재 정기 결제 구매 상태 관리 구성요소는 2022년 5월 출시 전에 정의한 전환된 정기 결제 제품에서 평소대로 작동하며 이전 버전과 호환되는 혜택의 구매를 관리하는 데 충분하지만 새 기능은 지원하지 않습니다.

백엔드에서 구매 상태를 확인하고 Play 결제 정기 결제 사용 권한을 관리하는 정기 결제 구매 상태 관리 모듈을 위한 새 Subscription Purchases API를 구현해야 합니다. 이 API의 이전 버전은 새 플랫폼에서 구매를 관리하는 데 필요한 모든 세부정보를 반환하지 않습니다. 이전 버전의 변경사항에 관한 자세한 내용은 2022년 5월 새로운 정기 결제 기능 가이드를 참고하세요.

일반적으로 SubscriptionNotification 실시간 개발자 알림을 받을 때마다 Subscription Purchases API를 호출하여 정기 결제 상태에 관한 최신 정보를 가져옵니다. purchases.subscriptions.get 호출을 Subscription Purchases API의 새 버전인 purchases.subscriptionsv2.get으로 바꿔야 합니다. 새 모델에서 정기 결제의 구매 사용 권한을 관리하는 데 충분한 정보를 제공하는 SubscriptionPurchaseV2라는 새 리소스가 있습니다.

이 새로운 엔드포인트는 제품을 판매하는 앱의 버전과 제품이 정의된 시점(2022년 5월 출시 전 또는 후)과 관계없이 모든 정기 결제 제품 및 모든 구매의 상태를 반환합니다. 따라서 이전 후에는 이 버전의 정기 결제 구매 상태 관리 모듈만 있으면 됩니다.