In-app Billing Overview (인앱 결제 개요)
Android Developer: Implementing In-App Billing
- 애플리케이션은 기기에 설치되어있는 Google Play 앱에 의해 노출되는 API를 사용하여 인앱 결제 서비스에 액세스 합니다.
- Google Play 앱이 애플리케이션과 Google Play 서버 사이에서 결제 요청과 응답을 전달합니다.
(실제로는, 애플리케이션이 Google Play 서버와 직접 통신하는 일은 없습니다.) - 애플리케이션은 프로세스 간 통신(IPC)으로 Google Play 앱에 결제 요청을 보내고 Google Play 앱으로 부터 응답을 받습니다.
- 애플리케이션은 자신과 Google Play 서버 사이의 네트워크 연결을 관리하지 않습니다.
- Google Play를 통해 게시하는 애플리케이션에만 인앱 결제를 구현할 수 있습니다.
- 인앱 구매 요청을 완료하려면 Google Play 앱이 네트워크를 통해 Google Play 서버에 액세스할 수 있으야 합니다.
Google Play 구매 흐름
- Google Play는 애플리케이션 구매에 사용되는 것과 동일한 백엔드 결제 서비스를 사용합니다.
- 사용자 입장에서는 일관되고 친숙한 구매 흐름을 통해 구매할 수 있습니다.
Google Play에서 인앱 결제 서비스를 사용하려면 Google Payments 판매자 계정이 있어야 합니다.
- 애플리케이션은 특정한 인앱 상품에 대한 결제 요청을 보내는 것으로 구매를 시작합니다.
- 그러면 Google Play가 결제 양식의 요청 및 유효성 검사와 재무상 트랜잭션의 처리를 비롯하여, 트랜잭션에 대한 모든 결제 세부정보를 처리합니다.
- 결제 프로세스가 완료되면 Google Play는 주문 번호, 주문 날짜 및 시간, 지불된 가격 등의 구매 세부정보를 애플리케이션으로 보냅니다.
- 어떤 지점에서도 애플리케이션이 재무상 트랜잭션을 처리할 필요가 없으며, 그 역할은 Google Play의 몫입니다.
샘플 애플리케이션
In-app Billing API (인앱 결제 API)
상품 유형
Google Play Developer Console을 사용하여 상품 유형, SKU, 가격, 상품 설명을 포함하여 상품을 정의합니다. (인앱 결제 관리)
관리되는 인앱 상품 (Managed Products)
관리되는 인앱 상품은 Google Play가 소유권 정보를 추적하고 관리하는 아이템입니다.
- 사용자가 관리되는 인앱 아이템을 구매하면 Google Play가 각 사용자별로 각 아이템에 대한 구매 정보를 저장합니다.
- Google Play에 쿼리하여 특정 사용자가 구매한 아이템의 상태를 복원할 수 있습니다.
- 사용자가 애플리케이션을 제거하거나 기기를 바꾸더라도 이 정보는 Google Play 서버에 영구 저장됩니다.
구독 (Subscriptions)
구독은 매달 또는 되풀이되는 결제로 앱 내에서 사용자들에게 콘텐츠, 서비스 또는 기능을 판매할 수 있도록 인앱 결제에서 제공되는 상품 유형입니다. (인앱 결제 구독)
인앱 상품과는 달리, 구독은 소비할 수 있는 상품이 아닙니다.
아이템 구매
Version 3 API를 사용하는 일반적인 구매 흐름은 다음과 같습니다.
isBillingSupported 요청을 보냅니다.
1. 애플리케이션에서 사용 중인 In-app Billing API의 대상 버전이 지원되는 버전인지 확인하기 위해 Google Play로2. 애플리케이션이 시작되거나 사용자가 로그인할 때 사용자가 어떤 아이템을 소유하고 있는지 확인하기 위해 Google Play로 검사하는 것이 좋은 방법입니다.
- 사용자의 인앱 구매를 쿼리하려면 getPurchases 요청을 보냅니다.
- 요청에 성공하면 Google Play는 구매한 아이템의 상품 ID 목록, 개별 구매 세부정보 목록, 구매를 위한 서명 목록이 포함된 Bundle을 반환합니다.
3. Google Play에서 정의한 인앱 상품의 세부정보를 쿼리하기 위해, 애플리케이션이 getSkuDetails 요청을 보낼 수 있습니다.
- 쿼리 요청에 상품 ID 목록을 지정해야합니다.
- 요청에 성공하면 Google Play는 상품의 가격, 제목, 설명, 구매 유형을 비롯한 상품 세부정보가 포함된 Bundle을 반환합니다.
4. 사용자가 인앱 상품을 소유하고 있지 않으면 상품 구매를 시작할 수 있습니다.
구매 요청을 시작하기 위해, 애플리케이션은 다른 매개변수와 함께 구매할 아이템의 상품 ID를 지정하는 getBuyIntent 요청을 보냅니다.
a. Google Play는 애플리케이션이 구매를 위한 결제 UI를 시작하기 위해 사용하는 PendingIntent가 포함된 Bundle을 반환합니다.
b. 애플리케이션은 startIntentSenderForResult 메서드를 호출하여 보류 중인 인텐트를 시작합니다.
c. 결제 흐름이 완료되면(즉, 사용자가 이이템을 구매에 성공하거나 구매를 취소하면) Google Play는 응답 Intent를 onActivityResult 메서드로 보냅니다.
- onActivityResult의 결과 코드에는 구매의 성공 또는 취소 여부를 나타내는 결과 코드가 있습니다.
- 응답 Intent에는 이 구매 트랜잭션을 고유하게 식별하기 위해 Google Play에서 생성되는 purchaseToken String을 포함하여, 구매 아이템에 대한 정보가 들어 있습니다.
- Intent에는 개인 개발자 키로 서명하는 구매 서명도 포함됩니다.
인앱 상품 소비 (Consuming In-app Products)
Google Play에서 모든 인앱 아이템 구매에 대한 소유권이 유지 관리되고, 필요한 경우 애플리케이션이 사용자의 구매 정보를 쿼리할 수 있습니다.
- 사용자가 인앱 구매에 성공하면 Google Play에 구매 내역이 기록됩니다.
- 일단 인앱 상품에 대한 구매가 이루어지면 해당 상품은 ‘소유된(owned)” 상태로 간주됩니다.
- “소유된(owned)” 상태의 인앱 상품은 Google Play에서 구매할 수 없습니다.
- “소유된(owned)” 인앱 상품에 대한 소비 요청을 보내야 Google Play에서 해당 상품을 다시 구매할 수 있는 상태가 됩니다.
인앱 상품을 소비하면 상품이 “소유되지 않은(unowned)” 상태로 되돌아가고, 이전의 구매 데이터가 삭제됩니다.
- 사용자가 소유한 제품의 목록을 검색하기 위해 애플리케이션이 Google Play로 getPurchases 호출을 보냅니다.
- 애플리케이션은 consumePurchases 호출을 보내서 소비 요청을 수행할 수 있습니다.
- 인앱 상품 구매 시 Google Play에서 받은 상품의 고유 purchaseToken String을 요청 인수에 지정해야 합니다.
- Google Play는 소비가 올바로 기록되었는지를 나타내는 상태 코드를 반환합니다.
비소비성(Non-consumable) 인앱 상품과 소비성(Consumable) 인앱 상품
비소비성 아이템
- 일반적으로 애플리케이션에서 한 번만 구매할 수 있습니다.
- 계속 이용할 수 있는 상품에 대해서는 소비를 구현하지 않습니다.
- 이런 아이템은 일단 구매하고 나면 사용자의 Google 계정에 영구적으로 연결됩니다.
- 비소비성 인앱 상품의 예로는 프리미엄 업그레이드나 레벨 팩이 있습니다.
소비성 아이템
- 여러 번 구매하도록 만들 수 있는 아이템에 대해서는 소비를 구현할 수 있습니다.
- 보통, 이런 아이템은 일시적으로 특정한 효과를 제공합니다.
- 예를 들어, 사용자의 게임 내 캐릭터가 라이프 포인트나 특별한 금화 같은 것을 얻어 비축해 둘 수 있습니다.
- 애플리케이션에서 구매한 아이템의 혜택이나 효과를 분배하는 것을 인앱 상품의 프로비저닝이라고 합니다.
- 인앱 상품을 사용자들에게 프로비저닝하는 방법을 관리하고 추적할 책임은 개발자에게 있습니다.
애플리케이션에서 소비성 인앱 상품을 프로비저닝하기 전에 Google Play로 소비 요청을 보내고 소비가 기록되었음을 나타내는 성공 응답을 받아야 합니다.
애플리케이션에서 소비성 구매 관리
다음은 소비성 인앱 상품을 구매하는 기본적인 흐름을 설명한 내용입니다.
- getBuyIntent 호출로 구매 흐름을 시작합니다.
- Google Play에서 구매가 성공적으로 완료되었는지를 나타내는 응답 Bundle을 받습니다.
- 구매가 성공한 경우 consumPurchase를 호출하여 구매를 소비합니다.
- Google Play에서 소비가 성공적으로 완료되었는지를 나타내는 응답 코드를 받습니다.
- 소비에 성공한 경우 애플리케이션에서 상품을 프로비저닝합니다.
다음으로, 사용자가 애플리케이션을 시작하거나 애플리케이션에 로그인할 때 사용자가 미결제 상태의 소비성 인앱 상품을 소유하고 있는지 확인하고, 소유하고 있으면 해당 아이템을 소비하고 프로비저닝합니다.
다음은 애플리케이션에 소비성 인앱 상품을 구현할 때 권장되는 애플리케이션 시작 흐름입니다.
- getPusrchases 요청을 보내서 사용자가 소유한 인앱 상품이 있는지 쿼리합니다.
- 소비성 인앱 상품이 있으면 consumePurchase를 호출하여 아이템을 소비합니다.
애플리케이션이 소비성 아이템에 대한 구매주문서를 완성했지만 소비 요청을 보낼 기회가 생기기도 전에 중지되거나 연결이 끊어졌을 수도 있기 때문에 이 단계가 꼭 필요합니다. - Google Play에서 소비가 성공적으로 완료되었는지를 나타내는 응답 코드를 받습니다.
- 소비에 성공한 경우 애플리케이션에서 상품을 프로비저닝합니다.
로컬 캐싱 (Local Caching)
Google Play 클라이언트는 인앱 결제 정보를 기기의 로컬 위치에서 캐시하므로, Version 3 API를 사용하여 이 정보를 더 자주 쿼리할 수 있습니다.
네트워크 연결을 통해 Google Play에 연결하는 방법 대신 캐시 조회를 통해 서비스되는 Version 3 API 호출이 많으며, 그 덕분에 API의 응답 시간이 대폭 단축되었습니다.
- getBuyIntent
- getPurchases
- isBillingSupported
- isPromoEligible