1. 소개
이 Codelab에서는 일회성 제품 (OTP)을 만들고 제품의 선주문 혜택을 추가하는 데 중점을 둡니다.
참고: 이 Codelab을 시작하기 전에 일회성 제품 EAP 신청 양식을 작성하여 선주문 기능에 대한 액세스를 요청해야 합니다.
시청자층
이 Codelab은 일회성 제품에 익숙하고 일회성 제품에 사전 주문 혜택을 추가하는 방법을 이해하려는 Android 앱 개발자를 대상으로 합니다.
기본 요건
일회성 제품을 처음 사용하는 경우 지역별 제품 가격으로 새로운 시장 개척하기 Codelab을 완료하는 것이 좋습니다.
학습할 내용…
- Google Play Console을 사용하여 일회성 제품의 선주문 혜택을 만드는 방법
- Play 결제 라이브러리 API를 사용하여 일회성 제품 및 해당 사전 주문 혜택 세부정보를 쿼리하는 방법
필요한 항목…
- 개발자 계정으로 Google Play Console에 액세스할 수 있습니다. 개발자 계정이 없으면 계정을 만들어야 합니다.
- 이 Codelab의 샘플 앱(GitHub에서 다운로드 가능)
- Android 스튜디오
2. 샘플 앱 빌드
이 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에 업로드하는 것입니다.
3. Play Console에서 선주문으로 OTP 만들기
Google Play Console에서 일회성 제품 (OTP)을 만들려면 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를 입력합니다. 예를 들면 다음과 같습니다.
upcoming_movie_1 - (선택사항) 태그: 관련 태그를 추가합니다.
- 이름: 제품 이름을 입력합니다. 예를 들면 다음과 같습니다.
Product Movie - 설명: 제품 설명을 입력합니다. 예를 들면 다음과 같습니다.
Product Description - (선택사항) 아이콘 이미지 추가: 제품을 나타내는 아이콘을 업로드합니다.
- 제품 ID: 고유 ID를 입력합니다. 예를 들면 다음과 같습니다.
- 다음을 클릭합니다.
- 구매 옵션을 추가하고 지역별 사용 가능 여부를 구성합니다. 일회성 제품에는 사용 권한이 부여되는 방식과 가격, 지역별 사용 가능 여부를 정의하는 구매 옵션이 하나 이상 필요합니다. 이 Codelab에서는 제품에 표준 구매 옵션을 추가합니다. 구매 옵션 섹션에서 다음 세부정보를 입력합니다.
- 구매 옵션 ID: 고유 ID를 입력합니다. 예를 들면 다음과 같습니다.
buy-movie - 구매 유형: 구매를 선택합니다.
- (선택사항) 태그: 이 구매 옵션에 해당하는 태그를 추가합니다.
- (선택사항) 고급 옵션을 클릭하여 고급 옵션을 구성합니다. 이 Codelab에서는 고급 옵션 구성을 건너뛰어도 됩니다.
- 구매 옵션 ID: 고유 ID를 입력합니다. 예를 들면 다음과 같습니다.
- 다음으로 구매 옵션의 지역별 사용 가능 여부 및 가격을 구성해야 합니다. 지역별 사용 가능 여부에서 앱이 아직 게시되지 않은 지역을 포함하여 제품을 이용할 수 있는 지역을 지정합니다. 기본적으로 구매 옵션은 모든 지역에서 사용할 수 있습니다.구매 가능 여부 및 가격 섹션에서 구매 가능 여부 및 액세스 권한 수정을 클릭합니다.
- 사용 불가로 설정을 선택합니다.
United States국가만 선택 해제한 다음 사용 불가로 설정을 클릭합니다. 이제 일회성 제품은United States에서만 사용할 수 있습니다.- 모든 지역 드롭다운에서 사용 가능한 국가 및 지역을 선택합니다.
United States만 표시됩니다. - 가격 아이콘을 클릭합니다. 그러면 가격을 설정하는 대화상자가 표시됩니다.
- 10달러를 입력한 후 저장을 클릭합니다.
- 초안으로 저장을 클릭합니다.
참고: 아직 구매 옵션을 활성화하지 마세요. 선주문 혜택을 구성한 후 활성화됩니다. 지역별 사용 가능 여부가 설정된 활성 구매 옵션에는 선주문 혜택을 추가할 수 없기 때문입니다.
선주문 혜택 추가하기
이제 이전에 만든 구매 구매 옵션에 선주문 혜택을 추가합니다. 선주문 혜택을 사용하면 사용자가 공식 출시 전에 상품을 구매할 수 있습니다. 선주문 혜택은 구입 구매 옵션에서만 지원되며 지역의 신규 제품에 대해서만 구성할 수 있습니다.
선주문 혜택을 추가하려면 다음 두 단계를 따르세요.
- 선주문 혜택을 위해 구매 구매 옵션을 준비합니다.
- 구매 옵션의 선주문 혜택을 추가합니다.
선주문 혜택을 위해 '구매' 구매 옵션 준비
- Google Play Console에서 샘플 앱을 열고 Play로 수익 창출 > 제품 > 일회성 제품으로 이동합니다.
- 일회성 제품 페이지에서 제품의 오른쪽 화살표 (
upcoming_movie_1)를 클릭합니다. 그러면 일회성 제품 수정 페이지가 열립니다. - 이전에 만든
buy-movie구매 옵션의 오른쪽 화살표를 클릭합니다. 그러면 구매 옵션 수정 페이지가 열립니다. - 사용 가능 여부 및 액세스 수정을 클릭한 다음 사용 가능으로 설정하고 사용자가 선주문할 수 있도록 허용을 선택합니다.
- 모든 지역 드롭다운에서 사용 가능한 국가 및 지역을 선택합니다. 이전에 구성한
United States만 표시됩니다. - 국가를 선택한 다음 선주문만 가능하도록 설정을 클릭합니다.
- 저장을 클릭합니다.
아직 구매 옵션에 선주문 혜택을 추가하지 않았습니다. 다음 단계는 선주문 혜택을 추가하는 것입니다.
선주문 혜택 추가하기
- Google Play Console에서 샘플 앱을 열고 Play로 수익 창출 > 제품 > 일회성 제품으로 이동합니다.
- 일회성 제품 페이지에서 제품 (
upcoming_movie_1)의 혜택 추가 > 선주문을 클릭합니다. 그러면 선주문 추가 페이지가 열립니다. - 선주문 세부정보를 입력합니다.
- 선주문 ID:
preorder-offer-1를 입력합니다. - (선택사항) 할인 추가: 없음, 비율 또는 정액 할인을 선택할 수 있습니다. 이 Codelab에서는 없음을 선택합니다.
- (선택사항) 태그: 관련 태그를 추가합니다.
- 시작일 및 시간: 최소 3일 후의 날짜를 설정합니다.
- 종료일 및 시간: 시작일로부터 최소 24시간 후의 날짜를 설정합니다.
- 선주문 후 사용 가능 여부: 선주문 기간이 지난 후 제품을 즉시 사용 가능으로 설정할지 아니면 특정 날짜/시간에 사용 가능으로 설정할지 선택합니다.
- (선택사항) 더 낮은 가격 보장: 사용자가 선주문 가격과 출시 시점의 가격 중 더 낮은 가격으로 청구되도록 하려면 이 옵션을 선택합니다. 이는 초기 구매자에게 강력한 인센티브가 될 수 있습니다.
- 선주문 ID:
- 저장을 클릭합니다.
- 일회성 제품 (upcoming_movie_1)의 일회성 제품 수정 페이지를 엽니다.
- 구매 구매 옵션 (
buy-movie)의 활성화를 클릭합니다. - 구매 구매 옵션에서 선주문 혜택 (
preorder-offer-1)의 활성화를 클릭합니다. 이렇게 하면 선주문 혜택이 활성화되고 이전에 선주문 세부정보에서 구성한 날짜에 게시됩니다.
선주문 혜택 만들기 동영상
다음 동영상은 앞에서 설명한 선주문 혜택 생성 단계를 보여줍니다.
4. PBL과 통합
앱을 Play 결제 라이브러리 (PBL)와 통합하려면 다음 단계를 따르세요.
- 샘플 앱에 Play 결제 라이브러리 종속 항목을 추가합니다.
dependencies { val billing_version = "8.1.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에서 일회성 제품 (이 예에서는upcoming_movie_1)을 가져오면 다음과 비슷한 응답이 표시됩니다. 선주문 혜택 세부정보는{ "productId": "upcoming_movie_1", "type": "inapp", "title": "Purrfect Mayhem: The Final Playback (Movies All Day | Play Samples)", "name": "Purrfect Mayhem: The Final Playback", "description": "Yolo and Thorne must reach the original broadcasting site to initiate the \"Final Playback\" and save the timeline. Follow them through their race against the Clockinators.", "skuDetailsToken": "<---skuDetailsToken--->", "oneTimePurchaseOfferDetails": {}, "oneTimePurchaseOfferDetailsList": [ { "priceAmountMicros": 8500000, "priceCurrencyCode": "USD", "formattedPrice": "$8.50", "offerIdToken": "<---offerIdToken--->", "offerId": "preorder", "purchaseOptionId": "buy-option", "offerTags": [], "validTimeWindow": { "startTimeMillis": 1756771200000, "endTimeMillis": 1785542400000 }, "preorderDetails": { "preorderReleaseTimeMillis": 1785542400000, "preorderPresaleEndTimeMillis": 1785542400000 } } ] }oneTimePurchaseOfferDetailsList에서 확인할 수 있습니다. 이 목록에는 Play Console에서 선주문 혜택이 구성된 구매 옵션 (buy-option)이 1개 있습니다. offerIdToken으로 각 구매 옵션을 고유하게 식별할 수 있습니다. - 선주문 혜택 세부정보와 함께 혜택 토큰을 가져옵니다. 6단계에서 결제 흐름을 시작하려면 혜택 토큰이 필요합니다.
@Override public void onProductDetailsResponse(List<ProductDetails> productDetailsList) { if (productDetailsList != null && !productDetailsList.isEmpty()) { // Process productDetailsList returned by QueryProductDetailsResult for (ProductDetails productDetails : productDetailsResult.getProductDetailsList()) { for (OneTimePurchaseOfferDetails oneTimePurchaseOfferDetails : productDetails.getOneTimePurchaseOfferDetailsList()) { // Checks if the offer is a preorder offer. if (oneTimePurchaseOfferDetails.getPreorderDetails() != null) { // Process the returned PreorderDetails OneTimePurchaseOfferDetails.PreorderDetails preorderDetails = oneTimePurchaseOfferDetails.getPreorderDetails(); // Get preorder release time in millis. long preorderReleaseTimeMillis = preorderDetails.getPreorderReleaseTimeMillis(); // Get preorder presale end time in millis. long preorderPresaleEndTimeMillis = preorderDetails.getPreorderPresaleEndTimeMillis(); // Get offer ID String offerId = oneTimePurchaseOfferDetails.getOfferId(); // Get the associated purchase option ID if (oneTimePurchaseOfferDetails.getPurchaseOptionId() != null) { String purchaseOptionId = oneTimePurchaseOfferDetails.getPurchaseOptionId(); } } } } } 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); }
5. 테스트 구매 옵션
실제 앱에서 일회성 제품을 제공하기 전에 라이선스 테스터와 Play Billing Lab을 사용하여 PBL 통합을 테스트할 수 있습니다.
Play Billing Lab을 사용하여 구매 옵션을 테스트하는 방법을 알아보려면 지역별 제품 가격으로 새로운 시장 공략 Codelab을 참고하세요.
6. 다음 단계
- 제품 구매 이탈을 분석하는 방법을 알아보세요.
- 지역별 가격 책정을 사용하여 새로운 시장을 공략하는 방법을 알아보세요.
- Play 결제 통합을 최대한 활용하는 방법을 알아보세요.
- 사용자가 이러한 제품을 구매하기 시작하면 보안 백엔드에서 구매를 확인하고 처리하기 위한 권장사항을 따라야 합니다.
참조 문서
7. 축하합니다.
축하합니다. Google Play Console을 탐색하여 일회성 제품의 선주문 혜택을 성공적으로 만들었습니다. 이제 일회성 구매를 위한 Google Play의 유연한 제품 카탈로그를 더 자세히 이해할 수 있습니다.
설문조사
이 Codelab에 대한 의견을 보내주시면 감사하겠습니다. 잠시 시간을 내어 설문조사에 참여해 주세요.