작성자: Bruno Oliveira (Android Developer Relations Team)
작성일: 2012년 12월 10일
원문: http://android-developers.blogspot.kr/2012/12/in-app-billing-version-3.html

인앱 결제는 Google Play(당시 안드로이드 마켓)에서 처음으로 소개된 이래로 상당한 진전을 이루어 왔습니다. 1년 반 이후, Google Play에서 최고 수익을 거두는 대다수의 앱에서 인앱 결제를 사용하고 있으며 수천 명의 개발자들이 시험 사용 후 구입을 결정(try-and-buy), 가상 상품, 구독(subscription) 등을 통해서 앱을 통하여 수익을 창출하고 있습니다.

인앱 결제는 개발자가 성공적으로 애플리케이션을 개발할 수 있도록 훨씬 강력하고 유연하게 개선되었습니다. 새롭게 소개되는 버전 3에서는 다음과 같은 신규 기능을 도입하였습니다.
  • 간단하게 애플리케이션을 개발, 디버깅, 유지할 수 있도록  디자인 개선. 연동 구현에 필요했던 몇백 라인 코드가 이제는 50줄이면 구현 가능.
  • 거래 손실을 줄이는 강력한 시스템 구조
  • 더욱 빠른 API 호출을 위한 로컬 캐싱
  • 개발자들이 오랫동안 기다려온 관리 구매(managed purchase) 소비 기능 및 상품 정보 쿼리 기능


입앱 결제 버전 3은 인앱 아이템을 사용하는 모든 애플리케이션에서 사용 가능합니다 (구독 지원은 조만간 발표). Google Play 스토어 최신 버전을 구동하는 Android 2.2 버전 이상의 디바이스에서 지원됩니다 (활성 디바이스 90% 이상).  

이전 버전에서 비동기 구조에 의해서 요구되었던  4개의 다른 애플리케이션 컴포넌트 대신, 새 버전의 API에서는 개발자가 단일 Activity 내에서 동기 요청을 하고 응답을 직접 처리할 수 있도록 했으며,  이는 코드 몇 줄로 구현이 가능합니다. 절감된 구현 비용은 새로운 인앱 결제 솔루션을 구현하는 개발자에게 좋은 기회를 제공합니다.


보다 용이한 구현

백그라운드 서비스를 통해서 비동기 노티를 보냈던 이전 모델과는 반대로, 새로운 API는 동기식이며 애플리케이션에 구매 결과를 바로 알려줍니다. 애플리케이션의 라이프사이클로 비동기 구매 결과 처리를 연동해야하는 필요성을 제거하여 인앱 아이템 판매를 위해서 작성해야 했던 코드를 상당히 간소화시켜 줍니다.  

구매를 시작하려면 간단히 API로부터  BuyIntent를 받아서 시작합니다. 

Bundle bundle = mService.getBuyIntent(3, "com.example.myapp",
   MY_SKU, ITEM_TYPE_INAPP, developerPayload);

PendingIntent pendingIntent = bundle.getParcelable(RESPONSE_BUY_INTENT);
if (bundle.getInt(RESPONSE_CODE) == BILLING_RESPONSE_RESULT_OK) {
   // Start purchase flow (this brings up the Google Play UI).
   // Result will be delivered through onActivityResult().
   startIntentSenderForResult(pendingIntent, RC_BUY, new Intent(),
       Integer.valueOf(0), Integer.valueOf(0), Integer.valueOf(0));
}

다음으로 Activity의 onActivityResult() 메소드로 전달된 구매 결과를 처리합니다.

public void onActivityResult(int requestCode, int resultCode, Intent data) {
   if (requestCode == RC_BUY) {
       int responseCode = data.getIntExtra(RESPONSE_CODE);
       String purchaseData = data.getStringExtra(RESPONSE_INAPP_PURCHASE_DATA);
       String signature = data.getStringExtra(RESPONSE_INAPP_SIGNATURE);

       // handle purchase here (for a permanent item like a premium upgrade,
       // this means dispensing the benefits of the upgrade; for a consumable
       // item like "X gold coins", typically the application would initiate
       // consumption of the purchase here)
   }
}


이전 버전과 달리, 이제 모든 구매는 Google Play에서 관리됩니다. 즉, 주어진 아이템의 소유권은 언제든 쿼리될 수 있습니다. 비관리 아이템 (unmanaged item) 메카니즘과 동일하게 구현하기 위해서, 애플리케이션은 구매하는 즉시 해당 아이템 소비가 가능하며 성공적으로 소비되면 아이템의 혜택을 제공할 수 있습니다.

로컬 캐싱

새로운 API는 Google Play 스토어 애플리케이션의 신규 기능을 활용하여 앱 결제 정보를 디바이스에서 로컬로 캐시하여 애플리케이션에서 쉽게 사용하게 해줍니다. 이러한 기능으로 많은 API 호출이 Google Play 네트워크 연결하는 대신 캐시 검색을 통해 이루어져서 API 응답 시간을 상당히 단축시킵니다. 예를 들어, 애플리케이션은 아래와 같은 호출을 통해서 소유한 아이템을 쿼리할 수 있습니다.  

Bundle bundle = mService.getPurchases(3, mContext.getPackageName(), ITEM_TYPE_INAPP);
if (bundle.getInt(RESPONSE_CODE) == BILLING_RESPONSE_RESULT_OK) {
   ArrayList mySkus, myPurchases, mySignatures;
   mySkus = bundle.getStringArrayList(RESPONSE_INAPP_ITEM_LIST);
   myPurchases = bundle.getStringArrayList(RESPONSE_INAPP_PURCHASE_DATA_LIST);
   mySignatures = bundle.getStringArrayList(RESPONSE_INAPP_PURCHASE_SIGNATURE_LIST);

   // handle items here
}
소유한 아이템을  쿼리하는 것은 이전 API 버전에서는 매우 부담되는 서버 호출이었기 때문에 개발자들이 자주 실행할 수가 없었습니다. 하지만 새로운 버전에서는 로컬 캐싱을 구현하였기 때문에 애플리케에션은 이제 실행할 때마다, 이후에도 필요한 만큼 해당 쿼리를 만들 수 있습니다.

상품 정보

새로운 API에서는 개발자들이 오랫동안 기다려온 기능이 도입 되었습니다.  바로 인앱 상품 정보를 Google Play에서 직접 쿼리할 수 있는 기능입니다. 이제 개발자는 프로그램을 통해서 아이템 타이틀, 설명, 가격 등을 얻을 수 있습니다. 통화 변환이나 표기 변환 등은 이제 더 이상 필요하지 않습니다. 가격 정보는 사용자의 통화로 표기되며 사용 언어에 따라서 표기됩니다. 

Bundle bundle = mService.getSkuDetails(3, "com.example.myapp",
       ITEM_TYPE_INAPP, skus); // skus is a Bundle with the list of SKUs to query
if (bundle.getInt(RESPONSE_CODE) == BILLING_RESPONSE_RESULT_OK) {
   List detailsList = bundle.getStringArrayList(RESPONSE_SKU_DETAILS_LIST);
   for (String details : detailsList) {
       // details is a JSON string with
       // SKU details (title, description, price, ...)
   }
}

예를 들면, 사용자가 보는 가격 정보를 변경하기 위해서 애프리케이션의 코드를 업데이트할 필요 없이 개발자 콘솔에서 가격을 업데이트하고 API를 호출하여 애플리케이션에서 업데이트 된 가격(특별 홍보나 할인 정보 등)을 보여줄 수 있는 것입니다.

샘플 애플리케이션

신규 API에 추가하여, 인앱 결제 구현법을 보여주는 새로운 샘플 애플리케이션을 발표합니다. 여기에는 JSON 문자열과 번들의 마샬링 및 언마샬링 데이터 구조, 서명 검증, 애플리케이션의 UI 쓰레드에서 개발자가 API를 직접 호출하도록 해주기 위하여 자동으로 백그라운드 작업을 관리하는 유틸리티 등과 같이 자주 사용하는 보일러 판 코드를 구현한 헬퍼 클래스가 포함되어 있습니다. 구현 프로세스를 훨씬 간소화할 수 있기 때문에 인앱 결제를 접해보지 않은 개발자는 샘플에서 코드를 사용하기를 강력하게 권장합니다. 샘플 애플리케이션은 Android SDK Manager를 통해서 다운로드 받을 수 있습니다.

앱 관련 키

인앱 결제 버전 3과 함께 도입된 기타 변경 사항에 따라, 라이센싱과 인앱 결제 키를 관리하는 방법이 개선되었습니다. 개발자가 아닌 각 앱마다 키가 설정되어 있으며 Google Play Developer Console 프리뷰에서 각 애플리케이션을 위한 “서비스 및 API” 페이지에서 확인 가능합니다. 기존 애플리케이션은 현재 보유한 키로 계속해서 사용이 가능합니다.

시작하기!

새로운 API를 사용하여 애플리케이션에 인앱 결제를 구현하시려면  업데이트된 In-App 결제 관련 문서를 확인하시고 인앱 상품 판매 교육 강의를 들어보세요. 인앱 결제 버전 3을 사용하려면, 새로운 Google Play 개발자 콘솔 프리뷰를 사용하셔야 합니다.