Google Play Billing 결제 Add-on
Android에서 Google Play 인앱 결제 라이브러리인 Google Play Billing Library 9의 BillingClient를 감싸는 Add-on입니다. 연결 관리, 상품 조회, 구매 화면 실행, 구매 조회, 구매 확인과 소모를 각각의 메서드로 제공합니다. Add-on은 구매를 저장하지 않고, 상품 유형에 따라 구매 확인과 소모를 자동으로 고르지도 않으므로 이 흐름은 앱이 직접 결정합니다.
구매로 받은 영수증은 Payments 모듈로 Hive Axyl 서버에 기록한 뒤, 앱 서버가 Hive Axyl Server API로 검증합니다. 두 단계 모두 영수증 값으로 GooglePurchase.PurchaseToken을 사용합니다. 값을 넣는 방법은 AxylReceipt 규칙을, 검증 흐름은 영수증 검증을 참조하세요.
모듈 정보
- 패키지:
com.com2usplatform.hiveaxyl.payments.addon.google - 인터페이스:
IGooglePlayBillingPlugin - 네임스페이스:
Hive.Axyl.Payments.Addon.Google - 등록 메서드:
AddPlayBilling() - 지원 플랫폼: Android
- 최소 사양: Android API 29+, Unity 6000.0+
등록과 획득
HiveBootstrap.Initialize의 등록 단계에서 Payments 모듈과 함께 등록한 뒤 HiveCore.TryResolve<T>()로 가져옵니다.
using Hive.Axyl.Core;
using Hive.Axyl.Core.Unity; // HiveBootstrap
using Hive.Axyl.Payments;
using Hive.Axyl.Payments.Addon.Google;
HiveBootstrap.Initialize(config, builder =>
{
builder.AddPayments()
.AddPlayBilling();
});
if (HiveCore.TryResolve<IGooglePlayBillingPlugin>(out var billing))
{
// Android 빌드에서만 실행되는 코드
}
Unity 에디터에서는 등록되지 않습니다
이 Add-on은 Android로 빌드한 플레이어에서만 등록됩니다. Unity 에디터에서는 플랫폼을 Android로 바꿔도 등록되지 않으므로, HiveCore.Resolve<T>()를 쓰면 RegistrationNotFoundException이 발생합니다. 반드시 TryResolve<T>()로 확인한 뒤 사용하세요.
패키지 설치와 등록 절차는 Hive Axyl Google 결제 플러그인 설치를 참조하세요.
메서드 요약
모든 메서드는 마지막 파라미터로 CancellationToken ct = default를 받습니다. 호출 규약은 호출 컨텍스트를 참조하세요.
이 Add-on이 제공하는 메서드는 아래와 같습니다.
- StartConnectionAsync():
BillingClient생성과 연결 - EndConnectionAsync():
BillingClient연결 종료 - QueryProductDetailsAsync(): 상품 상세 정보와 조회하지 못한 상품 목록 조회
- LaunchBillingFlowAsync(): Google Play 구매 화면 실행
- QueryPurchasesAsync(): 활성 구매와 미완료 구매 조회
- AcknowledgePurchaseAsync(): 비소모성 상품이나 구독 상품의 구매 확인
- ConsumeAsync(): 소모성 상품의 구매 소모
메서드
StartConnectionAsync
하나의 BillingClient를 만들어 구매 업데이트 리스너와 보류 중인 구매 지원을 설정한 뒤 startConnection으로 연결합니다. Add-on은 자동으로 연결하지 않으므로 앱이 직접 호출하세요.
결과 케이스 — GooglePlayBillingServiceStartConnectionResult
| 결과 케이스 | 와이어 코드 | 설명 |
|---|---|---|
Success | — | 연결에 성공했습니다. |
AlreadyConnected | already_connected | BillingClient가 이미 연결되어 있어 아무 동작도 하지 않았습니다. |
UnknownOutcome | UNKNOWN | 이 SDK 버전이 알지 못하는 새 결과입니다. |
Failure | FAILURE | 호출을 마치지 못했습니다. Problem의 HiveError로 원인을 확인합니다. |
구현 절차는 BillingClient 연결을 참조하세요.
EndConnectionAsync
endConnection으로 연결을 종료합니다. 이미 연결이 끊긴 상태에서 호출해도 오류가 아닙니다. 연결을 종료하면 SDK가 보관하던 상품 조회 결과도 지워지므로, 다시 연결한 뒤 구매 화면을 실행하려면 QueryProductDetailsAsync()로 상품을 다시 조회하세요.
결과 케이스 — GooglePlayBillingServiceEndConnectionResult
| 결과 케이스 | 와이어 코드 | 설명 |
|---|---|---|
Success | — | 연결을 종료했습니다. |
UnknownOutcome | UNKNOWN | 이 SDK 버전이 알지 못하는 새 결과입니다. |
Failure | FAILURE | 호출을 마치지 못했습니다. Problem의 HiveError로 원인을 확인합니다. |
구현 절차는 BillingClient 연결을 참조하세요.
QueryProductDetailsAsync
지정한 상품 ID와 상품 유형으로 queryProductDetailsAsync를 호출합니다. Billing Library 9의 부분 실패 방식에 따라 조회한 상품은 ProductDetailsList에, 조회하지 못한 상품은 UnfetchedProductList에 담깁니다. 일부 상품을 조회하지 못해도 호출 전체가 실패하지는 않습니다.
| 파라미터 | 타입 | 필수 여부 | 설명 |
|---|---|---|---|
productIds | IReadOnlyList<string> | Required | Google Play Console에 등록한 상품 ID 목록입니다. |
productType | ProductType | Required | 조회할 상품 유형입니다. 한 번의 조회에는 Inapp과 Subs 중 하나만 지정합니다. |
결과 케이스 — GooglePlayBillingServiceQueryProductDetailsResult
| 결과 케이스 | 와이어 코드 | 설명 |
|---|---|---|
Success | — | 조회 요청을 처리했습니다. 조회하지 못한 상품은 Data.UnfetchedProductList에서 확인합니다. |
UnknownOutcome | UNKNOWN | 이 SDK 버전이 알지 못하는 새 결과입니다. |
Failure | FAILURE | 호출을 마치지 못했습니다. Problem의 HiveError로 원인을 확인합니다. |
발생 예외
ArgumentException:productIds가null이거나 비어 있는 경우
구현 절차는 Google Play 상품 상세 정보 조회를 참조하세요.
LaunchBillingFlowAsync
요청한 상품으로 launchBillingFlow를 호출해 Google Play 구매 화면을 실행합니다. 현재 포그라운드 Activity는 Add-on이 자동으로 가져옵니다. Success는 구매 화면을 실행했다는 뜻일 뿐이며, 실제 구매 결과는 PurchasesUpdated 이벤트로 전달됩니다.
결과 케이스 — GooglePlayBillingServiceLaunchBillingFlowResult
| 결과 케이스 | 와이어 코드 | 설명 |
|---|---|---|
Success | — | 구매 화면을 실행했습니다. 구매 결과는 PurchasesUpdated 이벤트에서 확인합니다. |
UnknownOutcome | UNKNOWN | 이 SDK 버전이 알지 못하는 새 결과입니다. |
Failure | FAILURE | 호출을 마치지 못했습니다. Problem의 HiveError로 원인을 확인합니다. |
발생 예외
ArgumentNullException:request가null인 경우ArgumentException:request.Products가null이거나 비어 있는 경우
호출 예시
구매 결과는 이벤트로 전달되므로 구매 화면을 실행하기 전에 PurchasesUpdated를 구독하세요. LaunchBillingFlowAsync()를 호출하기 전에 StartConnectionAsync()로 연결하고, 구매할 상품을 QueryProductDetailsAsync()로 조회하세요.
using Hive.Axyl.Core;
using Hive.Axyl.Payments.Addon.Google;
// 앱을 시작할 때 한 번만 구독합니다.
billing.PurchasesUpdated += args =>
{
foreach (GooglePurchase purchase in args.Purchases)
{
if (purchase.PurchaseState == PurchaseState.Purchased)
{
string purchaseToken = purchase.PurchaseToken; // Payments 모듈의 AxylReceipt
}
else if (purchase.PurchaseState == PurchaseState.Pending)
{
// 결제가 보류 중입니다. Purchased가 될 때까지 이용 권한을 제공하지 않습니다.
}
}
};
var result = await billing.LaunchBillingFlowAsync(new LaunchBillingFlowRequest
{
Products = new[]
{
new LaunchBillingFlowProductParams
{
ProductId = "{productId}",
OfferToken = offerToken, // QueryProductDetailsAsync로 조회한 오퍼 토큰
},
},
});
if (result is GooglePlayBillingServiceLaunchBillingFlowResult.Failure failure)
{
HiveError error = failure.Problem;
}
구매한 영수증은 PurchaseToken을 AxylReceipt로 삼아 RecordStorePurchaseAsync()로 결제 결과를 저장합니다. 구현 절차는 Google Play 결제 요청을 참조하세요.
QueryPurchasesAsync
queryPurchasesAsync로 지정한 상품 유형의 활성 구매와, 아직 구매 확인이나 소모를 하지 않은 미완료 구매를 조회합니다. Google Play에는 별도의 구매 복구 흐름이 없으므로 구매 복구에도 이 메서드를 사용합니다.
| 파라미터 | 타입 | 필수 여부 | 설명 |
|---|---|---|---|
productType | ProductType | Required | 조회할 상품 유형인 Inapp 또는 Subs입니다. |
결과 케이스 — GooglePlayBillingServiceQueryPurchasesResult
| 결과 케이스 | 와이어 코드 | 설명 |
|---|---|---|
Success | — | 조회에 성공했습니다. |
UnknownOutcome | UNKNOWN | 이 SDK 버전이 알지 못하는 새 결과입니다. |
Failure | FAILURE | 호출을 마치지 못했습니다. Problem의 HiveError로 원인을 확인합니다. |
구현 절차는 Google Play 미지급 영수증 재조회를 참조하세요.
AcknowledgePurchaseAsync
acknowledgePurchase로 비소모성 상품이나 구독 상품의 구매를 확인합니다. Add-on은 상품 유형에 따라 구매 확인과 ConsumeAsync() 중 하나를 자동으로 고르지 않으므로 앱이 선택합니다.
| 파라미터 | 타입 | 필수 여부 | 설명 |
|---|---|---|---|
purchaseToken | string | Required | 확인할 구매의 GooglePurchase.PurchaseToken 값입니다. |
결과 케이스 — GooglePlayBillingServiceAcknowledgePurchaseResult
| 결과 케이스 | 와이어 코드 | 설명 |
|---|---|---|
Success | — | 구매를 확인했습니다. |
PurchaseNotFound | purchase_not_found | 구매 토큰과 일치하는 구매가 없습니다. |
AlreadyAcknowledged | already_acknowledged | 이미 구매 확인을 마친 구매입니다. |
UnknownOutcome | UNKNOWN | 이 SDK 버전이 알지 못하는 새 결과입니다. |
Failure | FAILURE | 호출을 마치지 못했습니다. Problem의 HiveError로 원인을 확인합니다. |
발생 예외
ArgumentException:purchaseToken이null이거나 빈 문자열인 경우
구현 절차는 비소모성·구독 상품 구매 확인을 참조하세요.
ConsumeAsync
consumeAsync로 소모성 상품의 구매를 소모합니다. 소모하면 구매 확인도 함께 처리됩니다.
| 파라미터 | 타입 | 필수 여부 | 설명 |
|---|---|---|---|
purchaseToken | string | Required | 소모할 구매의 GooglePurchase.PurchaseToken 값입니다. |
- 응답: ConsumeResponse
결과 케이스 — GooglePlayBillingServiceConsumeResult
| 결과 케이스 | 와이어 코드 | 설명 |
|---|---|---|
Success | — | 구매를 소모했습니다. |
PurchaseNotFound | purchase_not_found | 구매 토큰과 일치하는 구매가 없습니다. |
UnknownOutcome | UNKNOWN | 이 SDK 버전이 알지 못하는 새 결과입니다. |
Failure | FAILURE | 호출을 마치지 못했습니다. Problem의 HiveError로 원인을 확인합니다. |
발생 예외
ArgumentException:purchaseToken이null이거나 빈 문자열인 경우
구현 절차는 소모성 상품 거래 완료 처리를 참조하세요.
이벤트
두 이벤트 모두 엔진 메인 스레드에서 호출되므로 핸들러 안에서 엔진 API를 사용해도 됩니다.
PurchasesUpdated
PurchasesUpdatedListener.onPurchasesUpdated 콜백이 호출될 때마다 발생합니다. LaunchBillingFlowAsync()로 실행한 구매의 결과뿐 아니라, 다른 기기에서의 구매, 프로모션 코드 사용, 보류 중이던 구매가 Purchased로 바뀐 경우처럼 구매 화면 실행과 별개로 일어난 구매도 전달됩니다.
| 파라미터 | 타입 | 설명 |
|---|---|---|
| — | PurchasesUpdatedEventArgs | 콜백 하나의 원본 데이터입니다. |
SDK는 응답 코드에 따라 분기하지 않습니다. 앱이 BillingResult.ResponseCode를 해석하고 Purchases를 처리하세요.
BillingServiceDisconnected
Billing 서비스 연결이 끊겨 onBillingServiceDisconnected가 호출될 때 발생합니다. Add-on은 자동으로 다시 연결하지 않으므로, StartConnectionAsync()를 다시 호출할지와 호출 시점은 앱이 결정합니다.
구현 절차는 BillingClient 연결을 참조하세요.
데이터 타입
AccountIdentifiers
Purchase.AccountIdentifiers의 원본 정보입니다.
| 필드 | 타입 | 필수 여부 | 설명 |
|---|---|---|---|
ObfuscatedAccountId | string? | Optional | getObfuscatedAccountId() 값입니다. SDK 로그에 기록되지 않습니다. |
ObfuscatedProfileId | string? | Optional | getObfuscatedProfileId() 값입니다. SDK 로그에 기록되지 않습니다. |
AcknowledgePurchaseResponse
필드가 없습니다.
BillingResult
com.android.billingclient.api.BillingResult의 원본 정보입니다. PurchasesUpdated 이벤트로 전달되며, 메서드 호출의 실패는 이 타입이 아니라 Failure의 HiveError로 전달됩니다. ResponseCode는 가공하지 않은 정수이므로 USER_CANCELED 같은 응답 코드는 앱이 해석합니다.
| 프로퍼티 | 타입 | 필수 여부 | 설명 |
|---|---|---|---|
ResponseCode | int | Required | getResponseCode() 값입니다. BillingClient.BillingResponseCode에 해당하는 원본 정수입니다. |
DebugMessage | string | Required | getDebugMessage() 값입니다. |
SubResponseCode | int | Required | Billing Library 9의 getSubResponseCode() 값입니다. PAYMENT_DECLINED_DUE_TO_INSUFFICIENT_FUNDS, USER_INELIGIBLE, NO_APPLICABLE_SUB_RESPONSE_CODE 같은 launchBillingFlow의 세부 응답 코드이며, SDK는 이 값으로 분기하지 않습니다. |
ConsumeResponse
필드가 없습니다.
EndConnectionResponse
필드가 없습니다.
GoogleProductDetails
com.android.billingclient.api.ProductDetails의 원본 정보입니다. 필드의 의미 해석은 앱이 담당합니다.
| 필드 | 타입 | 필수 여부 | 설명 |
|---|---|---|---|
ProductId | string | Required | getProductId() 값입니다. |
ProductType | ProductType | Required | getProductType() 값입니다. |
Title | string | Required | getTitle() 값입니다. 앱 이름 접미사가 포함됩니다. |
Description | string | Required | getDescription() 값입니다. |
Name | string | Required | getName() 값입니다. Title과 달리 앱 이름 접미사가 없는 상품 이름입니다. |
OneTimePurchaseOfferDetails | OneTimePurchaseOfferDetails? | Optional | getOneTimePurchaseOfferDetails() 값입니다. 오퍼가 하나인 1회성 상품에서만 설정되며, 구독 상품과 오퍼가 여러 개인 1회성 상품에서는 설정되지 않습니다. |
OneTimePurchaseOfferDetailsList | IReadOnlyList<OneTimePurchaseOfferDetails> | Required | getOneTimePurchaseOfferDetailsList() 값입니다. 오퍼가 여러 개인 1회성 상품에서 사용하며, 오퍼가 하나인 1회성 상품에서는 비어 있습니다. |
SubscriptionOfferDetails | IReadOnlyList<SubscriptionOfferDetails> | Required | 구독의 기본 플랜과 오퍼 목록인 getSubscriptionOfferDetails() 값입니다. 1회성 상품에서는 비어 있습니다. |
GooglePurchase
com.android.billingclient.api.Purchase의 원본 정보입니다. 서버 검증에 사용하는 Signature와 OriginalJson을 포함해 모든 값을 가공하지 않고 전달합니다. PurchaseToken, Signature, OriginalJson, OrderId는 민감 정보이므로 SDK 로그에 평문으로 기록되지 않습니다.
| 필드 | 타입 | 필수 여부 | 설명 |
|---|---|---|---|
OrderId | string? | Optional | getOrderId() 값입니다. 보류 중인 구매에서는 설정되지 않습니다. |
PackageName | string | Required | getPackageName() 값입니다. |
Products | IReadOnlyList<string> | Required | 상품 ID 목록인 getProducts() 값입니다. |
PurchaseTime | DateTimeOffset | Required | 구매 시각인 getPurchaseTime() 값입니다. |
PurchaseState | PurchaseState | Required | getPurchaseState() 값입니다. |
PurchaseToken | string | Required | getPurchaseToken() 값입니다. Payments 모듈 요청의 AxylReceipt, 앱 서버가 보내는 영수증 검증 요청의 axylReceipt, 구매 확인, 구매 소모에 사용합니다. |
Quantity | int | Required | getQuantity() 값입니다. |
Signature | string | Required | 서버 검증에 사용하는 Base64 RSA 서명인 getSignature() 값입니다. |
OriginalJson | string | Required | 서버 검증에 사용하는 원본 구매 JSON인 getOriginalJson() 값입니다. AxylReceipt에 purchase_data와 signature를 담은 JSON 문자열을 넣는 경우, 이 값을 다시 직렬화하지 말고 그대로 purchase_data에 넣으세요. |
IsAcknowledged | bool | Required | isAcknowledged() 값입니다. |
IsAutoRenewing | bool | Required | isAutoRenewing() 값입니다. |
IsSuspended | bool | Required | isSuspended() 값입니다. true이면 일시 중지됐거나 갱신에 실패한 구독이므로 이용 권한을 제공하지 않아야 합니다. |
AccountIdentifiers | AccountIdentifiers? | Optional | getAccountIdentifiers() 값입니다. |
PendingPurchaseUpdate | PendingPurchaseUpdate? | Optional | 선불 요금제의 보류 중인 충전, 업그레이드, 다운그레이드 정보인 getPendingPurchaseUpdate() 값입니다. |
LaunchBillingFlowProductParams
BillingFlowParams.ProductDetailsParams입니다. 구매할 상품과 그 상품에서 고른 오퍼 토큰을 지정합니다.
| 필드 | 타입 | 필수 여부 | 설명 |
|---|---|---|---|
ProductId | string | Required | QueryProductDetailsAsync()가 반환한 상품의 ProductDetails.getProductId() 값입니다. |
OfferToken | string | Required | 구독 상품은 SubscriptionOfferDetails.getOfferToken(), 오퍼가 여러 개인 1회성 상품은 OneTimePurchaseOfferDetails.getOfferToken() 값입니다. 오퍼가 하나인 1회성 상품에서는 빈 문자열을 넣으세요. |
LaunchBillingFlowRequest
| 필드 | 타입 | 필수 여부 | 설명 |
|---|---|---|---|
Products | IReadOnlyList<LaunchBillingFlowProductParams> | Required | BillingFlowParams.ProductDetailsParams 목록입니다. 하나 이상 있어야 합니다. |
ObfuscatedAccountId | string? | Optional | BillingFlowParams.Builder.setObfuscatedAccountId 값입니다. 앱이 지정하는 사기 방지용 사용자 식별자입니다. Payments 모듈 요청과 영수증 검증 요청에 보내는 AccountUuid와 같은 값을 넣어야 영수증 검증 응답의 계정 식별자 비교 결과가 일치로 나옵니다. SDK 로그에 기록되지 않습니다. |
ObfuscatedProfileId | string? | Optional | BillingFlowParams.Builder.setObfuscatedProfileId 값입니다. SDK 로그에 기록되지 않습니다. |
LaunchBillingFlowResponse
필드가 없습니다. 구매 화면을 실행했다는 뜻이며, 실제 구매 결과는 PurchasesUpdated 이벤트로 전달됩니다.
OneTimePurchaseOfferDetails
ProductDetails.OneTimePurchaseOfferDetails의 원본 정보입니다. 가격은 Google Play가 반환한 통화 그대로 전달하며, 다른 통화로 환산하거나 통화별 소수 자릿수에 맞춰 바꾸지 않습니다.
| 필드 | 타입 | 필수 여부 | 설명 |
|---|---|---|---|
FormattedPrice | string | Required | 현지화된 표시 문자열인 getFormattedPrice() 값입니다. 예: ₩1,200 |
PriceAmount | decimal | Required | getPriceAmountMicros() 값을 정밀도 손실 없이 담은 가격입니다. 마이크로 단위의 소수점 이하 6자리를 유지하므로 마이크로 단위 1200000은 1.200000이 됩니다. |
PriceCurrencyCode | string | Required | ISO 4217 통화 코드인 getPriceCurrencyCode() 값입니다. 예: KRW |
OfferId | string? | Optional | getOfferId() 값입니다. 오퍼가 여러 개인 1회성 상품에서만 설정됩니다. |
OfferToken | string? | Optional | getOfferToken() 값입니다. 오퍼가 여러 개인 1회성 상품에서만 설정되며, 구매 화면을 실행할 때 전달합니다. |
PreorderDetails | PreorderDetails? | Optional | 사전 예약 오퍼에서만 설정되는 getPreorderDetails() 값입니다. |
RentalDetails | RentalDetails? | Optional | 대여 오퍼에서만 설정되는 getRentalDetails() 값입니다. |
PendingPurchaseUpdate
Purchase.PendingPurchaseUpdate의 원본 정보입니다.
| 필드 | 타입 | 필수 여부 | 설명 |
|---|---|---|---|
Products | IReadOnlyList<string> | Required | getProducts() 값입니다. |
PurchaseToken | string | Required | getPurchaseToken() 값입니다. 민감 정보이므로 SDK 로그에 평문으로 기록되지 않습니다. |
PreorderDetails
사전 예약 1회성 상품 오퍼인 ProductDetails.OneTimePurchaseOfferDetails.PreorderDetails의 원본 정보입니다.
| 필드 | 타입 | 필수 여부 | 설명 |
|---|---|---|---|
PreorderPresaleEndTimeUnixMillis | long | Required | getPreorderPresaleEndTimeMillis() 값입니다. Unix epoch 밀리초입니다. |
PreorderReleaseTimeUnixMillis | long | Required | getPreorderReleaseTimeMillis() 값입니다. Unix epoch 밀리초입니다. |
PricingPhase
ProductDetails.PricingPhase의 원본 정보입니다.
| 필드 | 타입 | 필수 여부 | 설명 |
|---|---|---|---|
FormattedPrice | string | Required | getFormattedPrice() 값입니다. |
PriceAmount | decimal | Required | getPriceAmountMicros() 값을 정밀도 손실 없이 담은 가격입니다. 마이크로 단위의 소수점 이하 6자리를 유지합니다. |
PriceCurrencyCode | string | Required | getPriceCurrencyCode() 값입니다. |
BillingPeriod | string | Required | ISO 8601 기간 형식인 getBillingPeriod() 값입니다. 예: P1M |
BillingCycleCount | int | Required | getBillingCycleCount() 값입니다. |
RecurrenceMode | RecurrenceMode | Required | getRecurrenceMode() 값입니다. |
PurchasesUpdatedEventArgs
PurchasesUpdated 이벤트로 전달되는 onPurchasesUpdated 콜백 하나의 원본 데이터입니다. SDK는 응답 코드에 따라 분기하지 않으므로 앱이 BillingResult.ResponseCode를 해석하고 Purchases를 처리합니다.
| 프로퍼티 | 타입 | 필수 여부 | 설명 |
|---|---|---|---|
BillingResult | BillingResult | Required | 이 업데이트의 원본 BillingResult입니다. |
Purchases | IReadOnlyList<GooglePurchase> | Required | 업데이트된 구매 목록입니다. 사용자 취소처럼 BillingResult가 정상 응답이 아니면 비어 있습니다. |
QueryProductDetailsResponse
| 필드 | 타입 | 필수 여부 | 설명 |
|---|---|---|---|
ProductDetailsList | IReadOnlyList<GoogleProductDetails> | Required | 조회에 성공한 상품 목록입니다. |
UnfetchedProductList | IReadOnlyList<UnfetchedProduct> | Required | 조회하지 못한 상품과 원본 상태 코드 목록입니다. 모든 상품을 조회했으면 비어 있습니다. |
QueryPurchasesResponse
| 필드 | 타입 | 필수 여부 | 설명 |
|---|---|---|---|
Purchases | IReadOnlyList<GooglePurchase> | Required | 조회한 상품 유형의 활성 구매와 미완료 구매 목록입니다. |
RentalDetails
대여 1회성 상품 오퍼인 ProductDetails.OneTimePurchaseOfferDetails.RentalDetails의 원본 정보입니다.
| 필드 | 타입 | 필수 여부 | 설명 |
|---|---|---|---|
RentalPeriod | string | Required | ISO 8601 기간 형식인 getRentalPeriod() 값입니다. |
RentalExpirationPeriod | string | Required | ISO 8601 기간 형식인 getRentalExpirationPeriod() 값입니다. 설정되지 않으면 빈 문자열입니다. |
StartConnectionResponse
필드가 없습니다.
SubscriptionOfferDetails
ProductDetails.SubscriptionOfferDetails의 원본 정보입니다.
| 필드 | 타입 | 필수 여부 | 설명 |
|---|---|---|---|
BasePlanId | string | Required | getBasePlanId() 값입니다. |
OfferId | string? | Optional | getOfferId() 값입니다. 기본 플랜 자체에서는 설정되지 않습니다. |
OfferToken | string | Required | getOfferToken() 값입니다. 구매 화면을 실행할 때 전달합니다. |
PricingPhases | IReadOnlyList<PricingPhase> | Required | getPricingPhases().getPricingPhaseList() 값입니다. |
OfferTags | IReadOnlyList<string> | Required | getOfferTags() 값입니다. |
UnfetchedProduct
queryProductDetailsAsync에서 조회하지 못한 상품 하나입니다.
| 필드 | 타입 | 필수 여부 | 설명 |
|---|---|---|---|
ProductId | string | Required | 요청한 상품 ID입니다. |
StatusCode | int | Required | ProductDetailsResult의 상품별 원본 상태 코드입니다. |
열거형
Add-on 열거형은 C# 멤버 이름으로 지정합니다. 표의 '값'은 직렬화에 사용하는 정수입니다.
ProductType
BillingClient.ProductType입니다.
| C# 멤버 | 값 | 설명 |
|---|---|---|
Unspecified | 0 | 유효한 상품 유형이 아닌 기본값입니다. |
Inapp | 1 | 1회성 상품입니다. Google Play의 inapp에 해당합니다. |
Subs | 2 | 구독 상품입니다. Google Play의 subs에 해당합니다. |
PurchaseState
Purchase.getPurchaseState() 값입니다.
| C# 멤버 | 값 | 설명 |
|---|---|---|
Unspecified | 0 | 상태를 판단할 수 없습니다. Google이 문서화한 UNSPECIFIED_STATE에 해당합니다. |
Purchased | 1 | 구매가 완료됐습니다. |
Pending | 2 | 현금 결제 대기처럼 구매가 보류 중입니다. Purchased가 될 때까지 이용 권한을 제공하지 마세요. |
RecurrenceMode
PricingPhase.getRecurrenceMode() 값입니다.
| C# 멤버 | 값 | 설명 |
|---|---|---|
Unspecified | 0 | 반복 방식이 지정되지 않은 기본값입니다. |
InfiniteRecurring | 1 | 구독이 취소될 때까지 계속 반복합니다. |
FiniteRecurring | 2 | 정해진 청구 주기 횟수만큼 반복합니다. BillingCycleCount를 함께 확인합니다. |
NonRecurring | 3 | 한 번만 적용되고 반복하지 않습니다. |