1. 소개
이 Codelab에서는 일회성 제품을 만들고, 구매 옵션을 정의하고, 지역별 가격을 설정하고, 일회성 제품의 구매 흐름을 테스트하는 데 중점을 둡니다.
시청자층
이 Codelab은 Play Console을 사용하여 일회성 제품 카탈로그를 관리하려는 Android 앱 개발자를 대상으로 합니다.
학습할 내용…
- 일회성 제품 객체 모델
- Google Play Console을 탐색하고 사용하여 일회성 제품 카탈로그를 관리하는 방법
- 일회성 제품 세부정보를 다양한 언어로 무료로 번역하는 방법
- 일회성 제품의 지역별 재고 및 가격을 구성하는 방법
- Play 결제 라이브러리 API를 사용하여 일회성 제품 세부정보를 쿼리하는 방법
- Play Billing Lab을 사용하여 일회성 제품을 테스트하는 방법
필요한 항목…
- 개발자 계정으로 Google Play Console에 액세스할 수 있습니다. 개발자 계정이 없으면 계정을 만들어야 합니다.
- 이 Codelab의 샘플 앱(GitHub에서 다운로드 가능)
- Android 스튜디오
2. 일회성 제품 프리미어
일회성 제품 객체 모델을 사용하면 제품 판매 방식을 더욱 유연하게 조정할 수 있으며 제품 관리의 복잡성을 줄일 수 있습니다. 객체 모델은 판매되는 항목과 판매 방식을 분리하여 동일한 사용 권한에 여러 가격대가 있도록 하고 사용자에게 마케팅하는 다양한 방법을 허용합니다. 객체 모델에는 세 가지 수준의 계층 구조가 있습니다.
- 일회성 제품 - 제품 객체는 사용자가 구매하는 항목을 정의합니다.
- 구매 옵션 - 구매 옵션은 사용자에게 사용 권한이 부여되는 방식과 가격, 제품이 제공되는 지역을 정의합니다. 하나의 제품에 여러 구매 옵션이 있을 수 있으며, 이는 지역별로 다른 가격을 나타낼 수 있습니다.
- 혜택 - 혜택은 연결된 구매 옵션의 가격에 영향을 줄 수 있으며, 할인이나 선주문을 모델링하는 데 사용할 수 있습니다. 하나의 구매 옵션에 여러 혜택이 있을 수 있습니다.
다음 다이어그램은 일회성 제품 객체 모델을 보여줍니다.
그림 1: 일회성 객체 모델
자세한 내용은 일회성 제품 개요를 참고하세요.
3. 샘플 앱 빌드
이 Codelab에서는 샘플 Android 앱을 사용하여 일회성 제품을 관리하는 방법을 보여줍니다. 샘플 앱은 다음 측면을 보여주는 완전한 소스 코드가 있는 완전한 기능을 갖춘 Android 앱으로 설계되었습니다.
- PBL과 앱 통합
- 일회성 제품 및 관련 구매 옵션 가져오기
- 지역별 가격으로 구매 흐름 실행
다음 데모 동영상은 샘플 앱이 배포되고 실행된 후의 모습과 동작을 보여줍니다.
일회성 제품과 Play 결제 라이브러리 (PBL)에 이미 익숙하다면 샘플 앱을 다운로드하여 사용해 보세요.
자격 요건
샘플 앱을 빌드하고 배포하기 전에 다음을 실행하세요.
- Google Play Console 개발자 계정을 만듭니다. 이미 개발자 계정이 있는 경우 이 단계를 건너뛰세요.
- Play Console에서 새 앱을 만듭니다. 앱을 만들 때 샘플 앱의 앱 이름을 지정할 수 있습니다.
- Android 스튜디오를 설치합니다.
빌드
이 빌드 단계의 목표는 샘플 앱의 서명된 Android App Bundle 파일을 생성하는 것입니다.
Android App Bundle을 생성하려면 다음 단계를 따르세요.
- GitHub에서 샘플 앱을 다운로드합니다.
- 샘플 앱 빌드. 빌드하기 전에 샘플 앱의 패키지 이름을 변경한 후 빌드합니다. Play Console에 다른 앱의 패키지가 있는 경우 샘플 앱에 제공하는 패키지 이름이 고유해야 합니다.
참고: 샘플 앱을 빌드하면 로컬 테스트에 사용할 수 있는 APK 파일만 생성됩니다. 하지만 Play Console에서 제품이 구성되지 않았기 때문에 앱을 실행해도 제품과 가격이 가져오지 않습니다. - 서명된 Android App Bundle을 생성합니다.
다음 단계는 Android App Bundle을 Google Play Console에 업로드하는 것입니다.
4. Play Console에서 일회성 제품 만들기
Google Play Console에서 일회성 제품을 만들려면 Play Console에 앱이 있어야 합니다. Play Console에서 앱을 만든 다음 이전에 만든 서명된 App Bundle을 업로드합니다.
앱 만들기
앱을 만들려면 다음 단계를 따르세요.
- 개발자 계정을 사용하여 Google Play Console에 로그인합니다.
- 앱 만들기를 클릭합니다. 그러면 앱 만들기 페이지가 열립니다.
- 앱 이름을 입력하고 기본 언어 및 기타 앱 관련 세부정보를 선택합니다.
- 앱 만들기를 클릭합니다. 그러면 Google Play Console에 앱이 만들어집니다.
이제 샘플 앱의 서명된 App Bundle을 업로드할 수 있습니다.
서명된 App Bundle 업로드
- 서명된 App Bundle을 Google Play Console 내부 테스트 트랙에 업로드합니다. 업로드한 후에만 Play Console에서 수익 창출 관련 기능을 구성할 수 있습니다.
- 테스트 및 출시 > 테스트 > 내부 버전 > 새 버전 만들기를 클릭합니다.
- 버전 이름을 입력하고 서명된 APK 파일을 업로드합니다.
- 다음을 클릭한 후 저장 및 게시를 클릭합니다.
이제 일회성 제품을 만들 수 있습니다.
일회성 제품 만들기
일회성 제품을 만들려면 다음 단계를 따르세요.
- Google Play Console의 왼쪽 탐색 메뉴에서 Play를 통한 수익 창출 > 제품 > 일회성 제품으로 이동합니다.
- 일회성 제품 만들기를 클릭합니다.
- 다음 제품 세부정보를 입력합니다.
- 제품 ID: 고유 ID를 입력합니다. 예를 들면 다음과 같습니다.
trending_movie_1 - (선택사항) 태그: 관련 태그를 추가합니다.
- 이름: 제품 이름을 입력합니다. 예를 들면 다음과 같습니다.
Product Movie - 설명: 제품 설명을 입력합니다. 예를 들면 다음과 같습니다.
Product Description
기본적으로 제품 이름과 설명은 영어 (미국) – en-US 언어로 표시됩니다. 다른 언어로 이름과 설명을 직접 입력할 수도 있습니다. 세부정보를 입력하려면 번역 관리를 클릭하고 번역된 텍스트를 입력할 언어를 선택한 다음 적용을 클릭합니다. 다음 이미지는 번역 관리 옵션을 보여줍니다.
그림 2: 번역 관리
선택한 언어가 언어 드롭다운에 표시됩니다. 각 언어를 선택하고 선택한 언어로 해당 이름과 설명을 입력합니다. 제품 이름과 설명을 무료로 자동 번역할 수도 있습니다. 자세한 내용은 이 Codelab의 일회성 제품 번역 섹션을 참고하세요.
참고: 이 Codelab에서는 아이콘 필드와 세금, 규정 준수, 프로그램 섹션의 구성을 건너뛰어도 됩니다. - 제품 ID: 고유 ID를 입력합니다. 예를 들면 다음과 같습니다.
- 다음을 클릭합니다.
- 구매 옵션을 추가하고 지역별 사용 가능 여부를 구성합니다. 일회성 제품에는 사용 권한이 부여되는 방식과 가격, 지역별 사용 가능 여부를 정의하는 구매 옵션이 하나 이상 필요합니다. 이 Codelab에서는 제품에 표준 구매 옵션을 추가합니다.
구매 옵션 섹션에서 다음 세부정보를 입력합니다.- 구매 옵션 ID: 고유 ID를 입력합니다. 예:
buy-movie - 구매 유형: 구매를 선택합니다.
- (선택사항) 태그: 이 구매 옵션에 해당하는 태그를 추가합니다.
- (선택사항) 고급 옵션을 클릭하여 고급 옵션을 구성합니다. 이 Codelab에서는 고급 옵션 구성을 건너뛰어도 됩니다.
- 구매 옵션 ID: 고유 ID를 입력합니다. 예:
- 다음으로 구매 옵션의 지역별 사용 가능 여부 및 가격을 구성해야 합니다. 지역별 사용 가능 여부에서 앱이 아직 게시되지 않은 지역을 포함하여 제품을 이용할 수 있는 지역을 지정합니다. 기본적으로 구매 옵션은 모든 지역에서 사용할 수 있습니다.
사용 가능 여부 및 가격 섹션에서 사용 가능 여부 및 액세스 수정 > 사용 불가로 설정을 클릭합니다. 모든 리전이 기본적으로 사용 가능으로 설정되어 있습니다.France,Spain,United States를 제외한 모든 국가를 선택한 다음 사용 불가로 설정을 클릭합니다.- 모든 지역 드롭다운에서 사용 가능한 국가 및 지역을 선택합니다. 이전 단계에서 선택한 국가만 표시됩니다.
- 사용 가능한 각 국가의 가격 열에서 수정 아이콘을 클릭합니다. 그러면 가격을 수정하는 대화상자가 표시됩니다. 다음 가격을 입력하고 저장합니다.
France에 10 EUR을 입력합니다.Spain에 8 EUR을 입력합니다.United States에 13 USD를 입력합니다.
- 활성화를 클릭합니다. 이렇게 하면 구매 구매 옵션으로 일회성 제품을 사용할 수 있습니다.
참고: 지역별 가격 통화는 사용자의 Play 국가 설정에 따라 표시됩니다. 예를 들어 사용자의 Play 국가가 프랑스로 설정된 경우 일회성 제품 가격은 유로로 표시됩니다.
일회성 제품 만들기 동영상
다음 동영상은 앞에서 설명한 일회성 제품 생성 단계를 보여줍니다.
대여 구매 옵션 추가
이제 이전에 만든 일회성 제품에 대여 구매 옵션을 추가합니다.
- Google Play Console의 왼쪽 탐색 메뉴에서 Play를 통한 수익 창출 > 제품 > 일회성 제품으로 이동합니다.
- 이전 단계에서 만든
trending_movie_1제품 ID가 있는 제품의 오른쪽 화살표를 클릭합니다. - 구매 옵션 추가를 클릭합니다.
- 구매 옵션 섹션에서 다음 세부정보를 입력합니다.
- 구매 옵션 ID:
rent-movie를 입력합니다. - 구매 유형: 대여를 선택합니다.
- 대여 기간: 48시간을 선택합니다.
- 대여 시작 기간: 24시간을 선택합니다.
- (선택사항) 태그: 이 구매 옵션에 해당하는 태그를 추가합니다.
- (선택사항) 고급 옵션을 클릭하여 고급 옵션을 구성합니다. 이 Codelab에서는 고급 옵션 구성을 건너뛰어도 됩니다.
- 구매 옵션 ID:
- 다음으로 구매 구매 옵션과 마찬가지로 대여 구매 옵션의 지역별 사용 가능 여부를 구성합니다. 이전 섹션의 6단계와 7단계를 참고하세요. 지역별 가격을 설정할 때는 대여에 대해 다른 가격을 설정하세요. 예:
France- 5유로Spain- 4유로United States- 7 USD
5. 일회성 제품 세부정보 번역
Google Play Console에서 제공되는 기계 번역 기능을 사용하면 추가 비용 없이 제품 이름과 설명을 번역할 수 있습니다.
제목과 설명을 번역하려면 다음 단계를 따르세요.
- Google Play Console의 왼쪽 탐색 메뉴에서 사용자 늘리기 > 번역 > 스토어 및 인앱 상품으로 이동합니다.
- 주문하기를 클릭합니다.
- 무료 기계 번역 옵션을 선택한 다음 다음을 클릭합니다.
- 번역 대상 언어에서 프랑스어 - fr-FR 및 스페인어 - es-ES를 선택한 다음 다음을 클릭합니다.
- 일회성 제품 및 정기 결제를 선택한 다음 번역 및 번역 보기를 클릭합니다. 그러면 면책 조항 배너가 표시됩니다. 면책 조항을 확인합니다.
- 이제 번역된 언어 목록이 표시됩니다. 언어의 검토 및 적용을 클릭합니다. 텍스트를 검토한 후 모든 번역 적용을 클릭합니다. 번역할 언어를 모두 선택한 후 이 단계를 반복합니다.
번역 후 Play Console에서 번역된 텍스트를 수정할 수 있습니다. 번역된 텍스트를 수정하려면 다음 단계를 따르세요.
- 일회성 제품 > [일회성 제품] > 일회성 제품 수정 > 일회성 제품 세부정보 수정 페이지를 엽니다.
- 언어 드롭다운에서 필요한 언어를 선택합니다. 그러면 선택한 언어로 텍스트가 표시됩니다. 다음 이미지는 번역된 텍스트를 수정할 언어를 선택하는 방법을 보여줍니다.
그림 3: 번역된 텍스트 수정 - 필요에 따라 텍스트를 수정한 다음 변경사항 저장을 클릭합니다.
번역된 텍스트는 사용자의 휴대전화 언어 환경설정에 따라 사용자에게 표시됩니다. 예를 들어 사용자 휴대전화의 언어가 프랑스로 설정된 경우 일회성 제품 제목과 설명이 프랑스어로 표시됩니다. 다음 샘플 이미지는 번역된 텍스트가 여러 언어로 표시되는 방식과 위치를 보여줍니다.
그림 4: 앱의 번역된 텍스트
변환 구성 동영상
다음 동영상은 앞에서 설명한 번역 구성 단계를 보여줍니다.
6. PBL과 통합
앱을 Play 결제 라이브러리 (PBL)와 통합하려면 다음 단계를 따르세요.
- 샘플 앱에 Play 결제 라이브러리 종속 항목을 추가합니다.
dependencies { val billing_version = "8.0.0" implementation("com.android.billingclient:billing-ktx:$billing_version") } - BillingClient를 초기화합니다. BillingClient는 앱에 상주하며 Play 결제 라이브러리와 통신하는 클라이언트 SDK입니다. 다음 코드 스니펫은 결제 클라이언트를 초기화하는 방법을 보여줍니다.
private BillingClient createBillingClient() { return BillingClient.newBuilder(activity) .enablePendingPurchases(PendingPurchasesParams.newBuilder().enableOneTimeProducts().build()) // For one-time products, add a listener to process and acknowledge the purchases. This will notify // Google the purchase was processed. // For client-only apps, use billingClient.acknowledgePurchase(). // If you have a secure backend, you must acknowledge purchases on your server using the // server-side API. // See https://developer.android.com/google/play/billing/security#acknowledge // In this sample snippet purchases aren't processed. You must // implement your business logic to process and acknowledge the purchases. .setListener((billingResult, purchases) -> {}) .enableAutoServiceReconnection() .build(); } - Google Play에 연결합니다.다음 코드 스니펫은 Google Play에 연결하는 방법을 보여줍니다.
/** * Starts the billing connection with Google Play. This method should be called exactly once * before any other methods in this class. * * @param productList The list of products to query for after the connection is established. */ public void startBillingConnection(List<Product> productList) { billingClient.startConnection( new BillingClientStateListener() { @Override public void onBillingSetupFinished(BillingResult billingResult) { if (billingResult.getResponseCode() == BillingResponseCode.OK) { Log.d(TAG, "Billing Client Connection Successful"); queryProductDetails(productList); } else { Log.e(TAG, "Billing Client Connection Failed: " + billingResult.getDebugMessage()); listener.onBillingSetupFailed(billingResult); // Propagate the error to the listener to show a message to the user. } } @Override public void onBillingServiceDisconnected() { Log.e(TAG, "Billing Client Connection Lost"); listener.onBillingError("Billing Connection Lost"); } }); } - 일회성 제품 세부정보를 가져옵니다.앱을 PBL과 통합한 후 앱에서 일회성 제품 세부정보를 가져와야 합니다. 다음 코드 스니펫은 앱에서 일회성 제품 세부정보를 가져오는 방법을 보여줍니다.
private void queryProductDetails(List<Product> productList) { QueryProductDetailsParams queryProductDetailsParams = QueryProductDetailsParams.newBuilder().setProductList(productList).build(); billingClient.queryProductDetailsAsync( queryProductDetailsParams, new ProductDetailsResponseListener() { @Override public void onProductDetailsResponse( BillingResult billingResult, QueryProductDetailsResult productDetailsResponse) { if (billingResult.getResponseCode() == BillingResponseCode.OK) { List<ProductDetails> productDetailsList = productDetailsResponse.getProductDetailsList(); listener.onProductDetailsResponse(productDetailsList); } else { Log.e(TAG, "QueryProductDetailsAsync Failed: " + billingResult.getDebugMessage()); listener.onBillingError("Query Products Failed: " + billingResult.getResponseCode()); } } }); }ProductDetails에서 일회성 제품 (이 예에서는trending_movie_1)을 가져오면 다음과 비슷한 응답이 표시됩니다.{ "productId": "trending_movie_1", "type": "inapp", "title": "Purrfect Mayhem: The Rewind Protocol (Movies All Day | Play Samples)", "name": "Purrfect Mayhem: The Rewind Protocol", "description": "Dr. Arid Thorne and a smart tiger named Yolo find a mysterious tape. It's a \"Rewind Protocol\" to fix time. A shadowy group, the Clockinator, hunts them to seize the tape's power.", "skuDetailsToken": "<---skuDetailsToken--->", "oneTimePurchaseOfferDetails": {}, "oneTimePurchaseOfferDetailsList": [ { "priceAmountMicros": 13000000, "priceCurrencyCode": "USD", "formattedPrice": "$13.00", "offerIdToken": "<---buy offerIdToken --->", "purchaseOptionId": "buy-option", "offerTags": [ "adventure", "mystery" ] }, { "priceAmountMicros": 7000000, "priceCurrencyCode": "USD", "formattedPrice": "$7.00", "offerIdToken": "<---rent offerIdToken--->", "purchaseOptionId": "rent-option", "offerTags": [ "adventure", "mystery" ], "rentalDetails": { "rentalPeriod": "P30D", "rentalExpirationPeriod": "PT24H" } } ] }oneTimePurchaseOfferDetailsList에서 구입 및 대여 구매 옵션을 사용할 수 있습니다. 이 목록에는 Play Console에서 구성된 2개의 구매 옵션 (buy-option 및 rent-option)이 있습니다. offerIdToken으로 각 구매 옵션을 고유하게 식별할 수 있습니다. - 대여 및 구매 혜택의 혜택 토큰을 가져옵니다. 6단계에서 결제 흐름을 시작하려면 혜택 토큰이 필요합니다.
@Override public void onProductDetailsResponse(List<ProductDetails> productDetailsList) { if (productDetailsList != null && !productDetailsList.isEmpty()) { // Iterate over all details of the queried product in step 4. for (ProductDetails productDetails : productDetailsList) { // Get the list of all the offers associated with the product. List<ProductDetails.OneTimePurchaseOfferDetails> offerDetailsList = productDetails.getOneTimePurchaseOfferDetailsList(); // Iterate over the offer details for (ProductDetails.OneTimePurchaseOfferDetails offerDetails : offerDetailsList) { // For a Rent purchase option, the // offerDetails.getRentalDetails() method returns // the rent information. If this information is present, // the offer corresponds to a Rent purchsae option. if (offerDetails.getRentalDetails() != null) { rentFormattedPrice = offerDetails.getFormattedPrice(); // Get the offerIdToken for the Rent purchase option rentOfferToken = offerDetails.getOfferToken(); rentMovieTags = offerDetails.getOfferTags(); } // If the offerDetails.getRentalDetails() returns // null, the offer corresponds to a Buy purchsae option. else { buyFormattedPrice = offerDetails.getFormattedPrice(); // Get the offerIdToken for the Buy purchase option buyOfferToken = offerDetails.getOfferToken(); buyMovieTags = offerDetails.getOfferTags(); } } updateUIButtons(); return; } } else { Log.e(TAG, "No product details found for " + productId); } } - 결제 흐름을 시작합니다.
/** * Launches the billing flow for the product with the given offer token. * * @param activity The activity instance from which the billing flow will be launched. * @param productDetails The product details of the product to purchase. * @param offerToken The offer token of the product to purchase. * @return The result of the billing flow. */ public void launchPurchase(Activity activity, ProductDetails productDetails, String offerToken) { ImmutableList<BillingFlowParams.ProductDetailsParams> productDetailsParamsList = ImmutableList.of( BillingFlowParams.ProductDetailsParams.newBuilder() .setProductDetails(productDetails) .setOfferToken(offerToken) .build()); BillingFlowParams billingFlowParams = BillingFlowParams.newBuilder() .setProductDetailsParamsList(productDetailsParamsList) .build(); billingClient.launchBillingFlow(activity, billingFlowParams); }
도움말: 실시간 개발자 알림 (RTDN)을 설정하여 재구매 유도 캠페인 및 기타 구매 수명 주기 관리 전략을 구현할 수도 있습니다. RTDN을 설정하고 정확한 추적 및 권한으로 알림을 처리하는 방법을 이해하려면 Play 결제 통합 극대화 Codelab을 살펴보는 것이 좋습니다.
7. 테스트 구매 옵션
실제 앱에서 일회성 제품을 제공하기 전에 라이선스 테스터와 Play Billing Lab을 사용하여 PBL 통합을 테스트할 수 있습니다.
일부 지역에서만 앱을 사용할 수 있고 지역별로 가격이 다른 경우 가격 현지화 및 재고를 테스트하는 방법을 알아봅니다.
자격 요건
- Google Play Console에서 라이선스 테스터를 추가한 다음 내부 테스트를 위해 라이선스 테스터를 사용 설정합니다.
- 휴대전화 또는 에뮬레이터에 Play Billing Lab 앱을 다운로드하여 설치합니다.
- 휴대전화나 에뮬레이터에서 이전에 만든 샘플 앱을 실행합니다.
구매 옵션의 지역별 가격 테스트
구매 옵션의 지역별 가격을 테스트하려면 다음 단계를 따르세요.
- Play Billing Lab 앱을 열고 라이선스 테스터로 로그인합니다.
- 구성 설정에서 수정을 클릭하고 국가를 선택한 다음
France적용을 클릭합니다. 여기서는 앱에 표시될 통화를 결정하는 Play 국가를 선택합니다. - 샘플 앱을 닫았다가 다시 엽니다. 이제
France의 구매 및 대여 통화가 유로로 표시됩니다.
다른 국가를 테스트하려면 2단계에서 Spain를 선택한 후 3단계를 실행합니다.
Play 결제 실험실 테스트 동영상
다음 동영상에서는 샘플 앱을 사용하여 지역별 가격 테스트 단계를 보여줍니다.
8. 다음 단계
- Play 결제 통합을 최대한 활용하는 방법을 알아보세요.
- 제품 구매 이탈을 분석하는 방법을 알아보세요.
- 사용자가 이러한 제품을 구매하기 시작하면 보안 백엔드에서 구매를 확인하고 처리하기 위한 권장사항을 따라야 합니다.
참조 문서
9. 마무리
축하합니다. Google Play Console을 탐색하여 새 일회성 제품을 만들고, 구매 옵션을 구성하고, Play 결제 랩을 사용하여 구매 흐름을 테스트했습니다. 이제 일회성 구매를 위한 Google Play의 유연한 제품 카탈로그를 더 자세히 이해할 수 있습니다.
설문조사
이 Codelab에 대한 의견을 보내주시면 감사하겠습니다. 잠시 시간을 내어 설문조사에 참여해 주세요.