IPaymentsService
인앱 결제를 Hive Axyl 서버에서 처리하는 서비스입니다. 상품 목록 조회, 결제 시도와 결제 결과 저장, 결제 확정, 구매 복구, 소모성 상품 지급 결과 저장, 구독 결제 처리를 제공합니다. 스토어 결제 화면 표시처럼 스토어 SDK를 직접 호출하는 작업은 결제 Add-on이 담당합니다. 역할 구분은 결제 Add-on과의 관계를 참조하세요.
영수증 검증은 이 서비스에서 하지 않고 앱 서버에서 처리합니다. 자세한 내용은 영수증 검증을 참조하세요.
- 인터페이스:
IPaymentsService - 네임스페이스:
Hive.Axyl.Payments - 패키지:
com.com2usplatform.hiveaxyl.payments
등록과 획득
using Hive.Axyl.Core;
using Hive.Axyl.Core.Unity; // HiveBootstrap
using Hive.Axyl.Payments;
var config = CoreConfig.CreateBuilder("{appId}").Build();
HiveBootstrap.Initialize(config, builder =>
{
builder.AddPayments(sandbox: true); // 개발·테스트 환경. 실제 서비스 빌드는 AddPayments()
});
IPaymentsService payments = HiveCore.Resolve<IPaymentsService>();
메서드 요약
'인증' 열의 의미는 인증 요구 표기를 참조하세요.
상품 조회
| 메서드 | 인증 | 설명 |
|---|---|---|
| ListStoreProductIdsAsync | 세션 필요 | 앱에 등록된 스토어별 상품 ID 목록을 조회합니다. |
| FetchAppleProductsAsync | 세션 필요 | StoreKit 상품 정보를 보내 Apple App Store 상품 목록을 조회합니다. |
| FetchGoogleProductsAsync | 세션 필요 | Google Play Billing 상품 정보를 보내 Google Play 상품 목록을 조회합니다. |
| FetchSteamProductsAsync | 세션 필요 | Steam 사용자의 통화에 맞춘 Steam 상품 목록을 조회합니다. |
| FetchPgProductsAsync | 세션 필요 | 요청한 통화에 맞춘 Payment Gateway(PG) 상품 목록을 조회합니다. |
소모성 상품 결제
| 메서드 | 인증 | 설명 |
|---|---|---|
| InitiatePurchaseAsync | 세션 필요 | Steam 결제 주문을 만들고 결제를 엽니다. |
| CreatePaymentUrlAsync | 세션 필요 | PG 결제 페이지 URL을 만듭니다. |
| CreatePrePurchaseAsync | 세션 필요 | 스토어 결제 창을 열기 직전에 결제 시도 정보를 저장합니다. |
| RecordStorePurchaseAsync | 세션 필요 | 스토어 결제가 끝난 직후 영수증과 결제 결과를 저장합니다. |
| RequestPurchaseAsync | 세션 필요 | 결제를 확정하고 거래를 종료합니다. |
| FinalizePurchaseAsync | 세션 필요 | Steam 또는 PG 결제를 최종 종료합니다. |
| RestorePurchasesAsync | 세션 필요 | Steam 또는 PG 결제에서 상품을 지급하지 못한 구매를 조회합니다. |
| ItemResultAsync | 세션 필요 | 소모성 상품의 지급 결과를 저장하고 거래를 확정합니다. |
구독
구독 결제는 Apple App Store와 Google Play만 지원합니다.
| 메서드 | 인증 | 설명 |
|---|---|---|
| PrepareSubscriptionAsync | 세션 필요 | 구독 결제 전에 상품 정보와 IapPayload를 저장합니다. |
| PurchaseSubscriptionAsync | 세션 필요 | 구독 영수증으로 구독 구매 정보를 조회해 저장합니다. |
| PostSubscriptionAsync | 세션 필요 | 구독 결제를 확정하고 거래를 종료합니다. |
영수증 검증
영수증 검증은 IPaymentsService 메서드로 하지 않고, 앱 서버가 Hive Axyl Server API를 호출해 요청합니다. 앱 클라이언트가 결제 후 영수증 정보를 앱 서버에 전달하면, 앱 서버는 소모성 상품이면 소모성 상품 영수증 검증을, 구독 상품이면 구독 상품 영수증 검증을 호출합니다.
결제 제공자별 구현 절차는 아래를 참조하세요.
- 소모성 상품: Apple 소모성 상품 영수증 검증, Google Play 소모성 상품 영수증 검증, Steam 소모성 상품 영수증 검증, PG 소모성 상품 영수증 검증
- 구독 상품: Apple 구독 상품 영수증 검증, Google Play 구독 상품 영수증 검증
공통 파라미터
모든 메서드의 마지막 파라미터는 ApiCallContext? context = null입니다. 생략하면 기본값이 적용됩니다. 자세한 내용은 호출 컨텍스트를 참조하세요.
모든 메서드는 요청 본문을 request 파라미터로 받으며, request는 Required입니다. 아래 메서드 설명에서는 요청 타입만 표기하고 파라미터 표는 생략합니다. 각 요청 타입의 필드는 데이터 타입에서 확인하세요.
발생 예외
ArgumentNullException:request가null인 경우
공통 Failure 코드
아래 코드는 서버가 코드로 응답하지만 기능 관점의 결과가 아니므로 Outcome이 아닌 Failure로 분기합니다. 원인 코드는 Failure.Problem.ExternalCode에 담깁니다. 결과 갈래와 분기 방법은 Core 결과 모델을 참조하세요.
bad_request: 잘못된 요청invalid_parameter: 요청 파라미터 형식 오류missing_field: 필수 필드나X-App-Id같은 필수 헤더 자체의 누락missing_app_id:X-App-Id헤더를 보냈지만 값이 빈 경우unauthorized: 인증 토큰이 없거나 유효하지 않은 경우token_expired: 인증 토큰 만료forbidden: 요청 권한 없음resource_not_found: 요청한 리소스 없음method_not_allowed: 허용되지 않은 요청 방식resource_conflict: 요청과 리소스 상태의 충돌unprocessable_content: 처리할 수 없는 요청 내용rate_limit_exceeded: 허용 한도를 넘은 요청 빈도internal_error: 서버 내부 오류service_unavailable: 서비스 일시 중단
메서드
ListStoreProductIdsAsync
앱에서 판매하는 인앱 상품의 상품 ID 목록을 조회합니다. 스토어별로 앱 ID, 소모성 상품 ID 목록, 구독 상품 ID 목록을 반환합니다.
- 요청: StoreRequest
- 응답: StoreResponseData
- 인증: 세션 필요
결과 케이스 — PaymentsListStoreProductIdsResult
| 결과 케이스 | 와이어 코드 | 설명 |
|---|---|---|
Success | — | 조회에 성공했습니다. |
PaymentBadRequest | payment_bad_request | 결제 요청을 처리할 수 없습니다. |
PaymentInvalidParameter | payment_invalid_parameter | 결제 요청 파라미터가 유효하지 않습니다. |
UnknownOutcome | UNKNOWN | 이 SDK 버전이 알지 못하는 새 결과입니다. |
Failure | FAILURE | 호출을 마치지 못했습니다. 공통 Failure 코드도 이 케이스로 분기합니다. |
구현 절차는 Apple 상품 ID 목록 조회와 Google Play 상품 ID 목록 조회를 참조하세요.
FetchAppleProductsAsync
Apple App Store 인앱 상품 목록을 조회합니다. StoreKit으로 조회한 현지 가격, 통화, 표시 가격, 제목, 설명 같은 상품 정보를 함께 보내면, 서버가 등록된 상품 정보와 비교하고 병합해 앱 상점에 표시할 최종 상품 목록을 반환합니다.
- 요청: ProductApple
- 응답: ProductResponseData
- 인증: 세션 필요
결과 케이스 — PaymentsFetchAppleProductsResult
| 결과 케이스 | 와이어 코드 | 설명 |
|---|---|---|
Success | — | 조회에 성공했습니다. |
PaymentBadRequest | payment_bad_request | 결제 요청을 처리할 수 없습니다. |
PaymentInvalidParameter | payment_invalid_parameter | 결제 요청 파라미터가 유효하지 않습니다. |
UnknownOutcome | UNKNOWN | 이 SDK 버전이 알지 못하는 새 결과입니다. |
Failure | FAILURE | 호출을 마치지 못했습니다. 공통 Failure 코드도 이 케이스로 분기합니다. |
구현 절차는 Apple 상품 상세 정보 조회를 참조하세요.
FetchGoogleProductsAsync
Google Play 인앱 상품 목록을 조회합니다. Google Play Billing으로 조회한 현지 가격, 통화, 표시 가격, 제목, 설명 같은 상품 정보를 함께 보내면, 서버가 등록된 상품 정보와 비교하고 병합해 앱 상점에 표시할 최종 상품 목록을 반환합니다.
- 요청: ProductGoogle
- 응답: ProductResponseData
- 인증: 세션 필요
결과 케이스 — PaymentsFetchGoogleProductsResult
| 결과 케이스 | 와이어 코드 | 설명 |
|---|---|---|
Success | — | 조회에 성공했습니다. |
PaymentBadRequest | payment_bad_request | 결제 요청을 처리할 수 없습니다. |
PaymentInvalidParameter | payment_invalid_parameter | 결제 요청 파라미터가 유효하지 않습니다. |
PaymentResourceNotFound | payment_resource_not_found | 결제 정보를 찾을 수 없습니다. |
UnknownOutcome | UNKNOWN | 이 SDK 버전이 알지 못하는 새 결과입니다. |
Failure | FAILURE | 호출을 마치지 못했습니다. 공통 Failure 코드도 이 케이스로 분기합니다. |
구현 절차는 Google Play 상품 상세 정보 조회를 참조하세요.
FetchSteamProductsAsync
Steam 상품 목록을 조회합니다. 통화와 국가는 요청에서 받지 않습니다. 서버가 StorePlayerId로 Steam GetUserInfo를 호출해 사용자의 통화와 국가를 정한 뒤, 그 통화의 가격 등급에 맞는 가격과 등록된 상품을 조합해 상점에 표시할 목록을 반환합니다. 서버는 이 호출에서 Steam 계정 연동 검증과 차단 확인도 함께 수행합니다.
- 요청: ProductSteam
- 응답: ProductResponseData
- 인증: 세션 필요
결과 케이스 — PaymentsFetchSteamProductsResult
| 결과 케이스 | 와이어 코드 | 설명 |
|---|---|---|
Success | — | 조회에 성공했습니다. |
PaymentBadRequest | payment_bad_request | 결제 요청을 처리할 수 없습니다. |
PaymentInvalidParameter | payment_invalid_parameter | 결제 요청 파라미터가 유효하지 않습니다. |
UnknownOutcome | UNKNOWN | 이 SDK 버전이 알지 못하는 새 결과입니다. |
Failure | FAILURE | 호출을 마치지 못했습니다. 공통 Failure 코드도 이 케이스로 분기합니다. |
구현 절차는 Steam 상품 상세 정보 조회를 참조하세요.
FetchPgProductsAsync
웹 결제 PG 상품 목록을 조회합니다. PortOne, MyCard, Xsolla 같은 PG사가 여기에 해당합니다. 요청한 통화를 기준으로 등록된 상품과 통화별 가격 등급에 맞는 가격을 조합해 상점에 표시할 목록을 반환합니다.
- 요청: ProductPg
- 응답: ProductResponseData
- 인증: 세션 필요
결과 케이스 — PaymentsFetchPgProductsResult
| 결과 케이스 | 와이어 코드 | 설명 |
|---|---|---|
Success | — | 조회에 성공했습니다. |
PaymentBadRequest | payment_bad_request | 결제 요청을 처리할 수 없습니다. |
PaymentInvalidParameter | payment_invalid_parameter | 결제 요청 파라미터가 유효하지 않습니다. |
UnknownOutcome | UNKNOWN | 이 SDK 버전이 알지 못하는 새 결과입니다. |
Failure | FAILURE | 호출을 마치지 못했습니다. 공통 Failure 코드도 이 케이스로 분기합니다. |
구현 절차는 PG 상품 정보 조회를 참조하세요.
InitiatePurchaseAsync
Steam 결제 전용 메서드입니다. FetchSteamProductsAsync로 상품 목록을 조회한 뒤에 호출하세요. Steam InitTxn으로 주문을 만들고 결제를 열며, 응답으로 Hive Axyl 주문 번호와 Steam 거래 ID를 받습니다. 호출이 끝나면 사용자가 Steam 오버레이에서 결제를 승인합니다. 승인됐지만 종료하지 못한 주문은 RestorePurchasesAsync로 복구합니다.
Steam 결제는 아래 순서로 진행합니다.
- FetchSteamProductsAsync로 사용자의 통화에 맞춘 상품 목록을 조회합니다.
- StartCallbackListenerAsync()로 콜백 수신을 시작한 뒤
InitiatePurchaseAsync로 주문을 만듭니다. - 사용자가 Steam 오버레이에서 결제를 승인하면 Steam Microtransactions 결제 Add-on의 MicroTxnAuthorizationResponse 이벤트로 승인 결과를 받습니다.
- RecordStorePurchaseAsync로 결제 결과를 저장합니다. 서버가 Steam
QueryTxn으로 승인을 확인합니다. - 앱 클라이언트가 영수증 정보를 앱 서버에 전달하고, 앱 서버가 소모성 상품 영수증 검증을 호출해 영수증을 검증합니다. 이 단계에서 Steam
FinalizeTxn으로 실제 청구가 발생합니다. - 앱 서버가 검증 결과를 확인하고 상품을 지급합니다.
- FinalizePurchaseAsync로 주문을 종료합니다.
- ItemResultAsync로 상품 지급 결과를 확정합니다.
- 요청: PurchaseInitRequest
- 응답: PurchaseInitResponseData
- 인증: 세션 필요
결과 케이스 — PaymentsInitiatePurchaseResult
| 결과 케이스 | 와이어 코드 | 설명 |
|---|---|---|
Success | — | 주문을 만들었습니다. |
PaymentBadRequest | payment_bad_request | 결제 요청을 처리할 수 없습니다. |
PaymentInvalidParameter | payment_invalid_parameter | 결제 요청 파라미터가 유효하지 않습니다. |
UnknownOutcome | UNKNOWN | 이 SDK 버전이 알지 못하는 새 결과입니다. |
Failure | FAILURE | 호출을 마치지 못했습니다. 공통 Failure 코드도 이 케이스로 분기합니다. |
구현 절차는 Steam 결제 세션 초기화를 참조하세요.
CreatePaymentUrlAsync
주문 정보를 바탕으로 사용자가 결제를 진행할 PG 결제 페이지 URL을 만들어 반환합니다. 앱이 WebView나 브라우저로 이 URL을 열면 사용자는 PG 결제 페이지에서 결제를 진행합니다. 발급된 URL은 주문 만료 시간 안에서만 유효합니다.
- 요청: OrderRequest
- 응답: OrderPayUrlResponseData
- 인증: 세션 필요
결과 케이스 — PaymentsCreatePaymentUrlResult
| 결과 케이스 | 와이어 코드 | 설명 |
|---|---|---|
Success | — | 결제 페이지 URL을 만들었습니다. |
PaymentBadRequest | payment_bad_request | 결제 요청을 처리할 수 없습니다. |
PaymentInvalidParameter | payment_invalid_parameter | 결제 요청 파라미터가 유효하지 않습니다. |
UnknownOutcome | UNKNOWN | 이 SDK 버전이 알지 못하는 새 결과입니다. |
Failure | FAILURE | 호출을 마치지 못했습니다. 공통 Failure 코드도 이 케이스로 분기합니다. |
구현 절차는 PG 결제 페이지 URL 생성을 참조하세요.
CreatePrePurchaseAsync
사용자가 상품을 고르고 결제 버튼을 누른 뒤, 스토어 결제 창을 열기 직전에 호출합니다. 상품 ID, 결제 금액, 통화, 앱 서버, 국가와 언어, IapPayload 같은 결제 시도 정보를 사전 결제 기록으로 저장합니다. 저장한 기록은 구매 복구를 처리할 때 해당 결제 시도와 저장된 IapPayload를 찾는 데 사용합니다.
- 요청: PrePurchase
- 응답: SuccessResponseData
- 인증: 세션 필요
결과 케이스 — PaymentsCreatePrePurchaseResult
| 결과 케이스 | 와이어 코드 | 설명 |
|---|---|---|
Success | — | 결제 시도 정보를 저장했습니다. |
PaymentBadRequest | payment_bad_request | 결제 요청을 처리할 수 없습니다. |
PaymentInvalidParameter | payment_invalid_parameter | 결제 요청 파라미터가 유효하지 않습니다. |
UnknownOutcome | UNKNOWN | 이 SDK 버전이 알지 못하는 새 결과입니다. |
Failure | FAILURE | 호출을 마치지 못했습니다. 공통 Failure 코드도 이 케이스로 분기합니다. |
구현 절차는 결제 전 구매 시도 정보 저장을 참조하세요.
RecordStorePurchaseAsync
스토어에서 결제가 끝난 직후 호출해 영수증과 스토어 거래 ID 같은 결제 결과를 서버에 저장합니다. 앱 서버가 영수증을 검증하기 전에 결제 사실을 먼저 남겨 두므로, 이후 단계가 네트워크 장애 등으로 중단되어도 이 기록이 영수증 검증, 상품 지급, 고객 지원과 정산의 근거가 됩니다.
Steam 결제에서는 이 단계에서 서버가 Steam QueryTxn으로 사용자의 결제 승인을 확인합니다.
- 요청: PurchaseRequest
- 응답: PurchaseResponseData
- 인증: 세션 필요
결과 케이스 — PaymentsRecordStorePurchaseResult
| 결과 케이스 | 와이어 코드 | 설명 |
|---|---|---|
Success | — | 결제 결과를 저장했습니다. |
PaymentBadRequest | payment_bad_request | 결제 요청을 처리할 수 없습니다. |
PaymentInvalidParameter | payment_invalid_parameter | 결제 요청 파라미터가 유효하지 않습니다. |
PaymentResourceNotFound | payment_resource_not_found | 결제 정보를 찾을 수 없습니다. |
PaymentUnauthorized | payment_unauthorized | 결제 요청 권한이 없습니다. |
VerifyError | verify_error | 결제 검증 중 오류가 발생했습니다. |
UnknownOutcome | UNKNOWN | 이 SDK 버전이 알지 못하는 새 결과입니다. |
Failure | FAILURE | 호출을 마치지 못했습니다. 공통 Failure 코드도 이 케이스로 분기합니다. |
구현 절차는 스토어 결제 결과 저장을 참조하세요.
RequestPurchaseAsync
결제 상태를 확정하고 거래를 종료 상태로 바꿔, 같은 거래가 중복으로 지급되거나 다시 처리되지 않게 합니다. 앱 서버가 영수증 검증을 마친 뒤 호출합니다.
- 요청: PurchasePostRequest
- 응답: PurchasePostResponseData
- 인증: 세션 필요
결과 케이스 — PaymentsRequestPurchaseResult
| 결과 케이스 | 와이어 코드 | 설명 |
|---|---|---|
Success | — | 결제를 확정했습니다. |
PaymentBadRequest | payment_bad_request | 결제 요청을 처리할 수 없습니다. |
PaymentInvalidParameter | payment_invalid_parameter | 결제 요청 파라미터가 유효하지 않습니다. |
PaymentResourceNotFound | payment_resource_not_found | 결제 정보를 찾을 수 없습니다. |
PaymentUnauthorized | payment_unauthorized | 결제 요청 권한이 없습니다. |
VerifyDuplicated | verify_duplicated | 이미 검증한 영수증입니다. |
VerifyError | verify_error | 결제 검증 중 오류가 발생했습니다. |
UnknownOutcome | UNKNOWN | 이 SDK 버전이 알지 못하는 새 결과입니다. |
Failure | FAILURE | 호출을 마치지 못했습니다. 공통 Failure 코드도 이 케이스로 분기합니다. |
구현 절차는 영수증 검증 후 결제 확정을 참조하세요.
FinalizePurchaseAsync
Steam 또는 PG 결제를 최종 종료합니다. Steam 결제에서는 주문을 종료합니다. 실제 청구는 앱 서버의 영수증 검증 단계에서 이미 끝났으므로 추가 청구는 발생하지 않습니다. PG 결제에서는 이 단계에서 거래를 완료합니다.
- 요청: PurchaseFinalizeRequest
- 응답: PurchaseFinalizeResponseData
- 인증: 세션 필요
결과 케이스 — PaymentsFinalizePurchaseResult
| 결과 케이스 | 와이어 코드 | 설명 |
|---|---|---|
Success | — | 결제를 종료했습니다. |
PaymentBadRequest | payment_bad_request | 결제 요청을 처리할 수 없습니다. |
PaymentInvalidParameter | payment_invalid_parameter | 결제 요청 파라미터가 유효하지 않습니다. |
PaymentResourceNotFound | payment_resource_not_found | 결제 정보를 찾을 수 없습니다. |
UnknownOutcome | UNKNOWN | 이 SDK 버전이 알지 못하는 새 결과입니다. |
Failure | FAILURE | 호출을 마치지 못했습니다. 공통 Failure 코드도 이 케이스로 분기합니다. |
구현 절차는 Steam 구매 완료 처리와 PG 구매 완료 처리를 참조하세요.
RestorePurchasesAsync
Steam 또는 PG 결제에서 상품을 지급하지 못한 이전 구매를 조회합니다. 네트워크 오류 등으로 지급하지 못한 상품을 다시 지급할 때 사용합니다. Steam 결제에서는 승인됐지만 종료하지 못한 주문을 Steam QueryTxn으로 다시 확인하고, 결제가 성공했거나 승인된 주문을 복구합니다.
- 요청: PurchaseRestoreRequest
- 응답: PurchaseRestoreResponseData
- 인증: 세션 필요
결과 케이스 — PaymentsRestorePurchasesResult
| 결과 케이스 | 와이어 코드 | 설명 |
|---|---|---|
Success | — | 조회에 성공했습니다. 복구할 구매는 Data.Restores에 담깁니다. |
PaymentBadRequest | payment_bad_request | 결제 요청을 처리할 수 없습니다. |
PaymentInvalidParameter | payment_invalid_parameter | 결제 요청 파라미터가 유효하지 않습니다. |
PaymentResourceNotFound | payment_resource_not_found | 결제 정보를 찾을 수 없습니다. |
UnknownOutcome | UNKNOWN | 이 SDK 버전이 알지 못하는 새 결과입니다. |
Failure | FAILURE | 호출을 마치지 못했습니다. 공통 Failure 코드도 이 케이스로 분기합니다. |
구현 절차는 Steam 미완료 거래 복구와 PG 상품 미지급 주문 조회를 참조하세요.
ItemResultAsync
앱 서버가 소모성 상품 지급을 마치면 이 메서드로 성공이나 취소 같은 지급 결과와 수량을 Hive Axyl 서버에 기록하고 거래를 확정합니다. 앱 안에서 지급이 실제로 성공했는지 서버에서 확인해 결제와 지급의 일관성을 유지하며, 실패하거나 취소된 건의 환불과 재지급을 판단하는 근거로 사용합니다.
- 요청: ItemResultBody
- 응답: SuccessResponseData
- 인증: 세션 필요
결과 케이스 — PaymentsItemResultResult
| 결과 케이스 | 와이어 코드 | 설명 |
|---|---|---|
Success | — | 지급 결과를 저장했습니다. |
InvalidQuantity | invalid_quantity | 지급 수량이 유효하지 않습니다. |
InvalidStatus | invalid_status | 지급 결과 상태 값이 유효하지 않습니다. |
PaymentBadRequest | payment_bad_request | 결제 요청을 처리할 수 없습니다. |
PaymentInvalidParameter | payment_invalid_parameter | 결제 요청 파라미터가 유효하지 않습니다. |
PaymentResourceNotFound | payment_resource_not_found | 결제 정보를 찾을 수 없습니다. |
UnknownOutcome | UNKNOWN | 이 SDK 버전이 알지 못하는 새 결과입니다. |
Failure | FAILURE | 호출을 마치지 못했습니다. 공통 Failure 코드도 이 케이스로 분기합니다. |
구현 절차는 Apple 상품 지급 결과 저장, Google Play 상품 지급 결과 저장, Steam 상품 지급 결과 저장, PG 상품 지급 결과 저장을 참조하세요.
PrepareSubscriptionAsync
구독 결제를 시작하기 전에 상품 정보와 IapPayload를 미리 저장하고, 저장한 사전 결제 기록의 ID를 반환합니다.
- 요청: SubscriptionPrePurchaseRequest
- 응답: SubscriptionPrePurchaseResponseData
- 인증: 세션 필요
결과 케이스 — PaymentsPrepareSubscriptionResult
| 결과 케이스 | 와이어 코드 | 설명 |
|---|---|---|
Success | — | 사전 결제 정보를 저장했습니다. |
PaymentBadRequest | payment_bad_request | 결제 요청을 처리할 수 없습니다. |
PaymentInvalidParameter | payment_invalid_parameter | 결제 요청 파라미터가 유효하지 않습니다. |
PaymentResourceNotFound | payment_resource_not_found | 결제 정보를 찾을 수 없습니다. |
UnknownOutcome | UNKNOWN | 이 SDK 버전이 알지 못하는 새 결과입니다. |
Failure | FAILURE | 호출을 마치지 못했습니다. 공통 Failure 코드도 이 케이스로 분기합니다. |
PurchaseSubscriptionAsync
구독 영수증으로 스토어의 구독 구매 정보를 조회해 구독 기록으로 저장합니다. 구독 결제가 끝난 뒤, 앱 서버가 영수증 검증을 요청하기 전에 호출합니다.
응답에는 저장된 구독 기록의 거래 ID와 조회 키가 담기며, 서버는 PostSubscriptionAsync 단계에서 이 조회 키로 같은 구독 기록을 찾습니다. PostSubscriptionAsync 요청의 AxylReceipt에는 이 메서드에 보낸 값과 같은 값을 넣으세요.
- 요청: SubscriptionPurchaseRequest
- 응답: SubscriptionPurchaseResponseData
- 인증: 세션 필요
결과 케이스 — PaymentsPurchaseSubscriptionResult
| 결과 케이스 | 와이어 코드 | 설명 |
|---|---|---|
Success | — | 구독 구매 정보를 저장했습니다. |
PaymentBadRequest | payment_bad_request | 결제 요청을 처리할 수 없습니다. |
PaymentInvalidParameter | payment_invalid_parameter | 결제 요청 파라미터가 유효하지 않습니다. |
PaymentResourceConflict | payment_resource_conflict | 결제 정보의 상태가 요청과 충돌합니다. |
PaymentResourceNotFound | payment_resource_not_found | 결제 정보를 찾을 수 없습니다. |
PaymentUnauthorized | payment_unauthorized | 결제 요청 권한이 없습니다. |
VerifyError | verify_error | 결제 검증 중 오류가 발생했습니다. |
UnknownOutcome | UNKNOWN | 이 SDK 버전이 알지 못하는 새 결과입니다. |
Failure | FAILURE | 호출을 마치지 못했습니다. 공통 Failure 코드도 이 케이스로 분기합니다. |
구현 절차는 Apple 구독 구매 정보 저장과 Google Play 구독 구매 정보 저장을 참조하세요.
PostSubscriptionAsync
구독 결제를 확정하고 거래를 종료합니다. 앱 서버가 영수증 검증을 마친 뒤 호출합니다. 확정할 구독 기록이 없어도 Success가 반환될 수 있으므로, 응답의 HiveAxylTransactionId가 null인지 확인해 실제로 확정됐는지 판단하세요.
- 요청: SubscriptionPurchasePostRequest
- 응답: SubscriptionPurchasePostResponseData
- 인증: 세션 필요
결과 케이스 — PaymentsPostSubscriptionResult
| 결과 케이스 | 와이어 코드 | 설명 |
|---|---|---|
Success | — | 요청을 처리했습니다. 실제 확정 여부는 Data.HiveAxylTransactionId로 확인합니다. |
PaymentBadRequest | payment_bad_request | 결제 요청을 처리할 수 없습니다. |
PaymentInvalidParameter | payment_invalid_parameter | 결제 요청 파라미터가 유효하지 않습니다. |
PaymentResourceNotFound | payment_resource_not_found | 결제 정보를 찾을 수 없습니다. |
PaymentUnauthorized | payment_unauthorized | 결제 요청 권한이 없습니다. |
VerifyDuplicated | verify_duplicated | 이미 검증한 영수증입니다. |
VerifyError | verify_error | 결제 검증 중 오류가 발생했습니다. |
UnknownOutcome | UNKNOWN | 이 SDK 버전이 알지 못하는 새 결과입니다. |
Failure | FAILURE | 호출을 마치지 못했습니다. 공통 Failure 코드도 이 케이스로 분기합니다. |
구현 절차는 Apple 구독 완료 처리와 Google Play 구독 완료 처리를 참조하세요.
데이터 타입
여러 타입이 공유하는 필드는 의미가 같습니다.
AppVersion: 앱 버전Country: ISO 3166-1 두 글자 국가 코드. 예:KRCurrency: ISO 4217 세 글자 통화 코드. 예:KRWLanguage: ISO 639-1 두 글자 언어 코드. 예:koServerId: 앱 서버 IDAccountUuid: 결제한 사용자와 요청한 사용자가 같은지 확인하는 계정 UUID. 만드는 방법과 용도는 AccountUuid 규칙을 참조하세요.AxylReceipt: 결제 영수증. 결제 제공자별로 넣는 값은 AxylReceipt 규칙을 참조하세요.Meta: 서버가 함께 전달한 부가 정보. 가공되지 않은 원본 JSON 문자열로 담깁니다.
아래 요청 필드는 타입이 string?이지만 JSON 텍스트를 담습니다. SDK가 값을 가공하지 않고 요청 본문에 그대로 넣으므로 올바른 JSON 객체를 넣으세요. 예를 들어 ItemResultBody.ProjectPayloadInfo에는 {"serverId":"server01","eventId":"summer_sale"}처럼 넣습니다.
ItemResultBody.ProjectPayloadInfoProductGoogleOfferDetails.PreorderDetailsProductGoogleOfferDetails.RentalDetails
AccountUuid 규칙
AccountUuid는 결제한 사용자와 요청한 사용자가 같은지 확인하는 계정 UUID입니다. 서버는 이 값을 만들거나 반환하지 않으므로 앱이 Player ID로 직접 만들어 요청에 넣습니다. Player ID를 포함하지 않는 단방향 값이므로 UUID만으로 Player ID를 알아낼 수 없습니다.
AccountUuid는 이 값을 받는 모든 요청에서 선택 필드입니다. 값을 넣지 않으면 요청 본문에서 빠지므로, 서버가 스토어 계정 식별자를 비교하거나 사전 결제 기록을 찾아야 하는 요청에는 값을 넣으세요.
생성 방법
AccountUuid는 RFC 4122 4.3절의 이름 기반 UUIDv5로 만듭니다. 네임스페이스 UUID와 이름을 SHA-1로 해시하는 방식이며, 결과는 RFC 4122 UUID 문자열입니다. MD5를 쓰는 UUIDv3, 난수 기반 UUIDv4, 시간 기반 UUIDv7은 사용할 수 없습니다.
이름에는 Player ID를 10진수 문자열 그대로 씁니다. 예를 들어 Player ID 1234567890의 이름은 "1234567890"이며, 앞에 0을 채우거나 16진수나 2진수로 바꾸면 다른 UUID가 됩니다. 네임스페이스는 앱이 정하며, 네임스페이스가 다르면 같은 Player ID에서도 다른 UUID가 만들어집니다. 같은 Player ID는 언제, 어느 기기, 어느 플랫폼에서 만들어도 같은 UUID여야 하므로, 한 앱의 모든 플랫폼에서 같은 네임스페이스를 쓰고 한번 정한 값은 바꾸지 마세요.
서버의 사용 방식
서버는 이 값을 아래 용도로 사용합니다.
- 스토어 계정 식별자 비교: Apple
appAccountToken, GoogleobfuscatedExternalAccountId와 비교할 값. 비교 결과는 앱 서버가 받는 소모성 상품 영수증 검증과 구독 상품 영수증 검증 응답의hiveAxylAccountUuidCompare에 담깁니다. - 사전 결제 기록 조회: 자동 갱신과 구매 복구에서 결제 전에 저장한 기록을 찾는 키. 호출할 때마다 값이 바뀌면 기록을 찾지 못하므로
IapPayload를 복구할 수 없습니다.
hiveAxylAccountUuidCompare는 1 일치, 2 불일치, 9 비교 불가 중 하나입니다. 한쪽 값이 없거나 UUID 형식이 아니면 2가 아니라 9가 되며, 2는 두 값이 모두 UUID 형식이면서 서로 다를 때만 나옵니다. 비교 결과가 1이 되려면 결제할 때 같은 AccountUuid를 Apple 결제에서는 PurchaseOptions.AppAccountToken에, Google Play 결제에서는 LaunchBillingFlowRequest.ObfuscatedAccountId에 넣어야 합니다.
구독 사전 결제 요청에도 AccountUuid를 보내세요
SubscriptionPrePurchaseRequest의 AccountUuid는 생략해도 요청이 성공합니다. 하지만 값이 없으면 스토어 영수증의 계정 식별자를 비교할 수 없어 다른 계정이 다른 사용자의 구독을 검증해도 통과합니다. 자동 갱신 알림에는 Player ID가 없으므로 지급 대상을 찾는 키로도 이 값을 사용합니다.
AxylReceipt 규칙
AxylReceipt에 넣는 값은 결제 제공자마다 다릅니다. Apple과 Google은 스토어가 발급한 값을, Steam과 PG는 Hive Axyl 서버가 발급한 값을 넣습니다. 앱 서버가 보내는 영수증 검증 요청의 axylReceipt에도 같은 값을 넣으세요. 값을 변형하면 영수증 검증에 실패합니다. Steam과 PG 결제에서는 서버가 저장된 주문 정보와 영수증을 비교합니다.
- Apple: StoreKit 2 거래의 JSON Web Signature(JWS)인 AppleTransaction.JwsRepresentation 원문.
header.payload.signature의 세 부분으로 구성됩니다. - Google: 구매 토큰인 GooglePurchase.PurchaseToken 문자열. 구매 토큰에는 상품 ID가 없으므로
ProductId필드가 있는 요청에서는ProductId도 함께 지정해야 하며, 지정하지 않으면 요청이 거부됩니다. - Steam: InitiatePurchaseAsync 또는 RestorePurchasesAsync 응답으로 받은
AxylReceipt원문 - PG: RestorePurchasesAsync 응답으로 받은
AxylReceipt원문
Google은 구매 토큰 대신 purchase_data와 signature를 담은 JSON 문자열도 받습니다. 이 형식에서는 purchase_data에 GooglePurchase.OriginalJson을, signature에 GooglePurchase.Signature를 넣습니다. OriginalJson은 Google Play가 반환한 원문 그대로 넣어야 하며, 다시 직렬화하면 서명 검증에 실패합니다.
ItemResultAsset
지급한 상품 정보입니다.
| 필드 | 타입 | 필수 여부 | 설명 |
|---|---|---|---|
AssetId | string? | Optional | 앱 안에서 고유한 상품 ID입니다. |
AssetName | string? | Optional | 앱 안에서 쓰는 상품 이름입니다. |
Quantity | int? | Optional | 지급 수량입니다. 1 이상이어야 합니다. |
ItemResultBody
소모성 상품의 지급 결과를 저장하는 요청입니다.
| 필드 | 타입 | 필수 여부 | 설명 |
|---|---|---|---|
Assets | IReadOnlyList<ItemResultAsset>? | Optional | 실제로 지급한 상품 목록입니다. 필드를 하나도 지정하지 않은 항목은 서버가 건너뛰므로, 보낼 항목이 없으면 이 필드를 생략하세요. |
AxylTransactionId | string | Required | Hive Axyl 결제 거래 ID입니다. 앱 서버가 소모성 상품 영수증 검증 응답에서 받아 앱 클라이언트에 전달한 hiveAxylTransactionId를 넣습니다. 접두사로 결제 제공자를 구분합니다. |
ProjectPayloadInfo | string? | Optional | 앱별 자유 형식 데이터를 담은 JSON 텍스트입니다. |
Status | int | Required | 지급 결과입니다. 1은 성공으로 확정, 2는 회수하지 않는 취소, 3은 회수하는 취소입니다. 그 밖의 값을 보내면 요청이 거부됩니다. |
OrderPayUrlResponseData
PG 결제 페이지 URL 생성 응답입니다.
| 필드 | 타입 | 필수 여부 | 설명 |
|---|---|---|---|
CreatedAt | DateTimeOffset? | Optional | 결제 페이지 URL을 만든 시각입니다. |
PayUrl | string? | Optional | 결제 페이지 URL입니다. 주문 만료 시간 안에서만 유효합니다. |
Meta | string? | Optional | 서버가 함께 전달한 부가 정보입니다. |
OrderRequest
PG 결제 페이지 URL 생성 요청입니다.
| 필드 | 타입 | 필수 여부 | 설명 |
|---|---|---|---|
AppVersion | string? | Optional | 앱 버전입니다. |
Country | string | Required | 국가 코드입니다. |
CustomPrice | string? | Optional | 상품에 설정된 금액 대신 앱 서버가 지정한 금액으로 결제할 때 사용하는 사용자 지정 결제 금액입니다. FixedCurrency, GameServerPriceVerifyKey와 함께 사용해야 합니다. |
FixedCurrency | string? | Optional | 결제 수단에 표시할 통화 코드입니다. CustomPrice를 사용할 때 필요합니다. |
GameServerPriceVerifyKey | string? | Optional | 사용자 지정 금액의 변조를 막기 위해 앱 서버가 발급한 금액 검증 키입니다. CustomPrice를 사용할 때 필요합니다. |
IapPayload | string? | Optional | 개발자가 정의해 앱 서버에 전달하는 JSON 문자열 메타데이터입니다. 결제 완료 후 앱 서버 콜백에 그대로 전달됩니다. |
Language | string | Required | 언어 코드입니다. 결제 수단 이름을 다국어로 표시할 때 사용합니다. |
Os | OrderRequestOs | Required | 앱 클라이언트의 OS입니다. |
ProductId | string | Required | 스토어에 등록한 인앱 상품 ID입니다. |
ProviderId | OrderRequestProviderId | Required | 결제 제공자입니다. Pg를 지정합니다. |
Quantity | int | Required | 구매 수량입니다. 1~999 범위입니다. |
ServerId | string? | Optional | 앱 서버 ID입니다. |
PrePurchase
스토어 결제 창을 열기 직전에 결제 시도 정보를 저장하는 요청입니다.
| 필드 | 타입 | 필수 여부 | 설명 |
|---|---|---|---|
AccountUuid | string? | Optional | 계정 UUID입니다. AccountUuid 규칙을 따릅니다. |
Country | string | Required | 국가 코드입니다. |
Currency | string | Required | 결제 통화 코드입니다. |
IapPayload | string? | Optional | 스토어 결제 시 개발자가 붙이는 JSON 문자열 payload입니다. 결제 완료 후 앱 서버 콜백에 그대로 전달됩니다. |
Language | string | Required | 언어 코드입니다. |
Price | decimal | Required | 현지 통화로 결제할 금액입니다. 통화에 따라 소수 자릿수가 다르며, KRW와 JPY는 0자리, USD와 EUR는 2자리입니다. 예: KRW 1200, USD 4.99 |
ProductId | string | Required | 스토어에 등록한 인앱 상품 ID입니다. |
ProviderId | PrePurchaseProviderId | Required | 결제 제공자입니다. |
RequestDate | DateTimeOffset? | Optional | 요청 시각입니다. UTC 기준입니다. |
ServerId | string? | Optional | 앱 서버 ID입니다. |
ProductApple
Apple App Store 상품 목록 조회 요청입니다.
| 필드 | 타입 | 필수 여부 | 설명 |
|---|---|---|---|
AppVersion | string? | Optional | 앱 버전입니다. |
Country | string | Required | 국가 코드입니다. |
Currency | string | Required | 통화 코드입니다. |
Language | string | Required | 언어 코드입니다. |
ProductType | string | Required | 조회할 상품 유형입니다. 구독은 subscription, 소모성 상품은 consumable입니다. |
Products | IReadOnlyList<ProductAppleProducts> | Required | StoreKit 2로 조회한 상품 목록입니다. |
ProviderId | ProductAppleProviderId | Required | 결제 제공자입니다. Apple을 지정합니다. |
ProductAppleProducts
StoreKit 2로 조회한 상품 하나의 정보입니다. ProductType을 제외한 값은 변환하지 않고 StoreKit 2가 반환한 원문 그대로 넣습니다.
| 필드 | 타입 | 필수 여부 | 설명 |
|---|---|---|---|
Description | string? | Optional | 상품 상세 설명입니다. |
DisplayName | string? | Optional | 상품 이름입니다. |
DisplayPrice | string? | Optional | 통화 기호를 포함한 표시 가격입니다. |
Id | string | Required | 상품 ID이자 서버가 등록된 상품과 맞춰 보는 키입니다. 비어 있으면 요청이 거부됩니다. |
Price | decimal? | Optional | 상품 가격입니다. USD, EUR처럼 소수 자릿수가 있는 통화도 값 그대로 넣습니다. |
PriceLocale | string? | Optional | 가격 로케일입니다. 서버가 이 값에서 통화와 국가를 추출하므로 원문 그대로 넣습니다. 예: ko_KR@currency=KRW |
ProductType | int? | Optional | 상품 유형 숫자 코드입니다. 0은 미지정, 1은 소모성, 2는 비소모성, 3은 자동 갱신 구독, 4는 비갱신 구독입니다. 목록에 없는 값은 거부되지 않고 0으로 처리됩니다. 요청 최상위의 ProductApple.ProductType과는 별개입니다. |
ProductDetails
Google Play Billing으로 조회한 상품 하나의 정보입니다. 중첩된 오퍼 정보까지 포함해 Google Play Billing이 반환한 값을 넣으며, ProductType은 숫자 코드로 넣습니다.
| 필드 | 타입 | 필수 여부 | 설명 |
|---|---|---|---|
Description | string? | Optional | 상품 설명입니다. |
OneTimePurchaseOfferDetails | ProductGoogleOfferDetails? | Optional | Google Play Billing의 ProductDetails.oneTimePurchaseOfferDetails입니다. |
OneTimePurchaseOfferDetailsList | IReadOnlyList<ProductGoogleOfferDetails>? | Optional | 할인 오퍼와 기본 오퍼를 함께 담은 1회성 상품 오퍼 목록입니다. 값이 있으면 OneTimePurchaseOfferDetails보다 우선합니다. |
ProductId | string | Required | 상품 ID이자 서버가 등록된 상품과 맞춰 보는 키입니다. 비어 있으면 요청이 거부됩니다. |
ProductType | int? | Optional | 상품 유형 숫자 코드입니다. 1은 소모성, 2는 구독입니다. 목록에 없는 값은 거부되지 않고 미지정 값인 0으로 처리됩니다. 요청 최상위의 ProductGoogle.ProductType과는 별개입니다. |
SubscriptionOfferDetails | IReadOnlyList<ProductGoogleSubscriptionOffer>? | Optional | 구독 오퍼 목록입니다. 목록이 비어 있지 않으면 구독 상품으로 처리되며, 가격은 각 오퍼의 PricingPhases에 있습니다. |
Title | string? | Optional | 상품 제목입니다. |
ProductGoogle
Google Play 상품 목록 조회 요청입니다.
| 필드 | 타입 | 필수 여부 | 설명 |
|---|---|---|---|
AppVersion | string? | Optional | 앱 버전입니다. |
Country | string | Required | 국가 코드입니다. |
Currency | string | Required | 통화 코드입니다. |
Language | string | Required | 언어 코드입니다. |
ProductType | string | Required | 조회할 상품 유형입니다. 구독은 subscription, 소모성 상품은 consumable입니다. |
Products | IReadOnlyList<ProductDetails> | Required | Google Play Billing으로 조회한 상품 목록입니다. |
ProviderId | ProductGoogleProviderId | Required | 결제 제공자입니다. Google을 지정합니다. |
ProductGoogleOfferDetails
Google Play Billing의 1회성 상품 오퍼 정보입니다.
| 필드 | 타입 | 필수 여부 | 설명 |
|---|---|---|---|
FormattedPrice | string? | Optional | Google Play가 형식에 맞춰 표시한 가격입니다. |
OfferId | string? | Optional | 오퍼 ID입니다. null이면 정가로 판매하는 기본 오퍼입니다. |
OfferToken | string? | Optional | 오퍼 토큰입니다. Google Play가 조회할 때마다 새로 발급하므로 캐시하거나 재사용하지 마세요. |
PreorderDetails | string? | Optional | 사전 예약 오퍼임을 나타내는 JSON 텍스트입니다. 값이 있으면 표시 가격 후보에서 제외됩니다. 서버는 내용을 읽지 않고 값이 있는지만 확인합니다. |
PriceAmount | decimal? | Optional | 통화 단위 금액입니다. PriceAmountMicros가 함께 있으면 PriceAmountMicros를 기준으로 합니다. |
PriceAmountMicros | long? | Optional | 마이크로 단위 금액입니다. 값이 있으면 이 값을 기준으로 합니다. |
PriceCurrencyCode | string? | Optional | 통화 코드입니다. |
RentalDetails | string? | Optional | 대여 오퍼임을 나타내는 JSON 텍스트입니다. 값이 있으면 표시 가격 후보에서 제외됩니다. 서버는 내용을 읽지 않고 값이 있는지만 확인합니다. |
ProductGooglePricingPhase
Google Play Billing의 구독 가격 단계입니다.
| 필드 | 타입 | 필수 여부 | 설명 |
|---|---|---|---|
BillingCycleCount | int? | Optional | 청구 주기 횟수입니다. 무한 반복 단계에서는 0입니다. |
BillingPeriod | string? | Optional | ISO 8601 기간 형식의 청구 기간입니다. 예: P1M |
FormattedPrice | string? | Optional | Google Play가 형식에 맞춰 표시한 가격입니다. |
PriceAmount | decimal? | Optional | 통화 단위 금액입니다. PriceAmountMicros가 함께 있으면 PriceAmountMicros를 기준으로 합니다. |
PriceAmountMicros | long? | Optional | 마이크로 단위 금액입니다. 값이 있으면 이 값을 기준으로 합니다. |
PriceCurrencyCode | string? | Optional | 통화 코드입니다. |
RecurrenceMode | int? | Optional | 반복 방식입니다. 1은 무한 반복, 2는 정해진 횟수만큼 반복, 3은 1회입니다. 표시 가격은 1인 단계에서 가져옵니다. |
ProductGoogleSubscriptionOffer
Google Play Billing의 구독 오퍼입니다. 가격은 PricingPhases에 있습니다.
| 필드 | 타입 | 필수 여부 | 설명 |
|---|---|---|---|
BasePlanId | string? | Optional | 기본 플랜 ID입니다. |
OfferId | string? | Optional | 오퍼 ID입니다. null이면 기본 오퍼입니다. |
OfferTags | IReadOnlyList<string>? | Optional | 오퍼 태그 목록입니다. |
OfferToken | string? | Optional | 오퍼 토큰입니다. Google Play가 조회할 때마다 새로 발급하므로 캐시하지 마세요. |
PricingPhases | IReadOnlyList<ProductGooglePricingPhase>? | Optional | 가격 단계 목록입니다. |
ProductOffer
상품 조회 응답에 담기는 1회성 오퍼 또는 구독 오퍼입니다. 오퍼는 OfferToken으로 구분합니다.
| 필드 | 타입 | 필수 여부 | 설명 |
|---|---|---|---|
BasePlanId | string? | Optional | 구독의 기본 플랜 ID입니다. 1회성 오퍼에서는 null입니다. |
Currency | string? | Optional | 통화 코드입니다. |
DisplayPrice | string? | Optional | 표시 가격입니다. |
OfferToken | string? | Optional | 오퍼 토큰입니다. Google Play가 조회할 때마다 새로 발급하므로 캐시하지 마세요. |
Price | decimal? | Optional | 통화의 소수 자릿수에 맞춘 가격입니다. |
ProductPg
PG 상품 목록 조회 요청입니다.
| 필드 | 타입 | 필수 여부 | 설명 |
|---|---|---|---|
AppVersion | string? | Optional | 앱 버전입니다. |
Country | string | Required | 국가 코드입니다. |
Currency | string | Required | 통화 코드입니다. |
Language | string | Required | 언어 코드입니다. |
ProductType | string? | Optional | 상품 유형입니다. |
ProviderId | ProductPgProviderId | Required | 결제 제공자입니다. Pg를 지정합니다. |
ServerId | string? | Optional | 앱 서버 ID입니다. 상품 조회에는 사용하지 않습니다. |
ProductProducts
상품 조회 응답에 담기는 상품 하나의 정보입니다.
| 필드 | 타입 | 필수 여부 | 설명 |
|---|---|---|---|
Currency | string? | Optional | 통화 코드입니다. |
Description | string? | Optional | 상품 설명입니다. |
DisplayOriginalPrice | string? | Optional | 표시용 원래 가격입니다. |
DisplayPrice | string? | Optional | 표시 가격입니다. |
Offers | IReadOnlyList<ProductOffer>? | Optional | 1회성 오퍼와 구독 오퍼 목록입니다. 오퍼가 없으면 null입니다. |
OriginalPrice | decimal? | Optional | 통화의 소수 자릿수에 맞춘 원래 가격입니다. 예: KRW 1100, USD 11.00 |
Price | decimal? | Optional | 통화의 소수 자릿수에 맞춘 가격입니다. 예: KRW 9900, USD 9.99 |
ProductId | string? | Optional | 상품 ID입니다. |
ProductType | string? | Optional | 상품 유형입니다. 구독은 subscription, 소모성 상품은 consumable입니다. |
Title | string? | Optional | 상품 제목입니다. |
ProductResponseData
상품 목록 조회 메서드가 공통으로 반환하는 응답입니다. Apple, Google, Steam, PG 모두 같은 형태입니다.
| 필드 | 타입 | 필수 여부 | 설명 |
|---|---|---|---|
AppVersion | string? | Optional | 앱 버전입니다. |
Country | string? | Optional | 국가 코드입니다. |
Currency | string? | Optional | 통화 코드입니다. |
Language | string | Required | 언어 코드입니다. |
Products | IReadOnlyList<ProductProducts>? | Optional | 상품 목록입니다. |
ProviderId | ProductProviderId | Required | 결제 제공자입니다. |
Meta | string? | Optional | 서버가 함께 전달한 부가 정보입니다. |
ProductSteam
Steam 상품 목록 조회 요청입니다. 통화와 국가는 요청에 넣지 않으며, 서버가 StorePlayerId로 정합니다.
| 필드 | 타입 | 필수 여부 | 설명 |
|---|---|---|---|
AppVersion | string? | Optional | 앱 버전입니다. |
Language | string | Required | 언어 코드입니다. |
ProductType | string? | Optional | 상품 유형입니다. |
ProviderId | ProductSteamProviderId | Required | 결제 제공자입니다. Steam을 지정합니다. |
ServerId | string? | Optional | 앱 서버 ID입니다. 상품 조회에는 사용하지 않습니다. |
StorePlayerId | long | Required | Steam 64비트 SteamID입니다. 서버가 이 값으로 Steam GetUserInfo를 호출해 통화와 국가를 정합니다. 1 이상이어야 합니다. |
PurchaseFinalizeRequest
Steam 또는 PG 결제를 최종 종료하는 요청입니다. 서버가 AxylReceipt에서 주문 번호를 읽으므로 요청에 주문 번호 필드가 없습니다.
| 필드 | 타입 | 필수 여부 | 설명 |
|---|---|---|---|
AxylReceipt | string | Required | 결제 영수증입니다. AxylReceipt 규칙을 따릅니다. |
ProviderId | PurchaseFinalizeRequestProviderId | Required | 결제 제공자입니다. Steam 또는 Pg를 지정합니다. |
PurchaseFinalizeResponseData
Steam 또는 PG 결제 종료 응답입니다.
| 필드 | 타입 | 필수 여부 | 설명 |
|---|---|---|---|
OrderId | string? | Optional | Steam 결제의 주문 ID입니다. PG 결제에서는 null이며 StoreTransactionId를 사용합니다. |
StoreTransactionId | string? | Optional | PG 결제의 스토어 거래 ID입니다. Steam 결제에서는 null이며 OrderId를 사용합니다. |
Meta | string? | Optional | 서버가 함께 전달한 부가 정보입니다. |
PurchaseInitRequest
Steam 결제 초기화 요청입니다.
| 필드 | 타입 | 필수 여부 | 설명 |
|---|---|---|---|
AppVersion | string? | Optional | 앱 버전입니다. |
Country | string | Required | 국가 코드입니다. |
Currency | string | Required | 통화 코드입니다. |
IapPayload | string? | Optional | 개발자가 정의한 payload입니다. 예: {"serverId":"server01"} |
Language | string | Required | 언어 코드입니다. |
ProductId | string | Required | 구매할 상품 ID입니다. |
ProviderId | PurchaseInitRequestProviderId | Required | 결제 제공자입니다. Steam을 지정합니다. |
ServerId | string? | Optional | 앱 서버 ID입니다. |
StorePlayerId | long | Required | 스토어 사용자 ID인 Steam 64비트 SteamID입니다. 1 이상이어야 합니다. |
PurchaseInitResponseData
Steam 결제 초기화 응답입니다. Steam 결제 창을 표시하는 데 필요한 정보를 담습니다.
| 필드 | 타입 | 필수 여부 | 설명 |
|---|---|---|---|
AxylReceipt | string? | Optional | 서버가 발급한 영수증입니다. 주문 번호, 금액, 통화, 상품, 앱 ID를 묶어 변조를 확인하는 데 사용합니다. 보관했다가 RecordStorePurchaseAsync와 FinalizePurchaseAsync 요청의 AxylReceipt, 앱 서버가 보내는 소모성 상품 영수증 검증 요청의 axylReceipt에 그대로 넣으세요. |
OrderId | string | Required | Hive Axyl 내부 주문 번호입니다. RecordStorePurchaseAsync 요청의 OrderId에 그대로 넣습니다. 앱 서버가 보내는 소모성 상품 영수증 검증 요청의 orderId에 넣으면 주문을 지정할 수 있으며, 생략하면 서버가 storeTransactionId나 axylReceipt로 주문을 찾습니다. |
ProductId | string | Required | 스토어에 등록한 인앱 상품 ID입니다. |
StoreTransactionId | string | Required | Steam Web API의 transid인 Steam 거래 ID입니다. Steam 결제 창을 표시하는 데 사용합니다. |
Meta | string? | Optional | 서버가 함께 전달한 부가 정보입니다. |
PurchasePostRequest
결제 확정 요청입니다. ProviderId와 AxylReceipt는 모든 결제 제공자에 공통이고, 나머지 필드는 결제 제공자에 따라 필요합니다.
| 필드 | 타입 | 필수 여부 | 설명 |
|---|---|---|---|
AxylReceipt | string | Required | 결제 영수증입니다. AxylReceipt 규칙을 따릅니다. |
FinalizationMsg | string? | Optional | 결제 완료 메시지입니다. Apple과 Google 결제에서만 저장됩니다. |
ProductId | string? | Optional | 스토어에 등록한 인앱 상품 ID입니다. Google 결제에서만 사용합니다. AxylReceipt가 구매 토큰이면 필수이고, purchase_data와 signature를 담은 JSON 문자열이면 영수증에서 읽으므로 생략합니다. |
ProviderId | PurchasePostRequestProviderId | Required | 결제 제공자입니다. |
StoreTransactionId | string? | Optional | 스토어 거래 ID입니다. Apple 결제에서만 사용하며, StoreKit 2 재검증 키이므로 Apple 결제에서는 필수입니다. |
PurchasePostResponseData
결제 확정 응답입니다.
| 필드 | 타입 | 필수 여부 | 설명 |
|---|---|---|---|
Meta | string? | Optional | 서버가 함께 전달한 부가 정보입니다. |
PurchaseRequest
스토어 결제가 끝난 뒤 영수증과 결제 정보를 저장하는 요청입니다.
| 필드 | 타입 | 필수 여부 | 설명 |
|---|---|---|---|
AccountUuid | string? | Optional | 계정 UUID입니다. AccountUuid 규칙을 따릅니다. |
AxylReceipt | string | Required | 결제 영수증입니다. AxylReceipt 규칙을 따릅니다. |
Country | string | Required | 국가 코드입니다. |
Currency | string? | Optional | 결제 통화 코드입니다. Price와 함께 서버 기록과 비교하는 데만 사용하며, 결제 기록에는 서버 값이 저장됩니다. Currency 없이 Price만 보내면 통화 비교를 생략하고 금액만 비교합니다. |
IapPayload | string? | Optional | 스토어 결제 시 개발자가 붙인 JSON 문자열 payload입니다. 앱 서버 검증과 결제 완료 콜백에 그대로 전달됩니다. |
Language | string | Required | 언어 코드입니다. |
OrderId | string? | Optional | Steam과 PG 결제의 주문 키인 Hive Axyl 내부 주문 번호입니다. Steam 결제에서는 InitiatePurchaseAsync 응답의 OrderId를 그대로 넣습니다. |
Price | decimal? | Optional | 현지 통화 결제 금액입니다. 결제 기록에는 이 값이 아니라 서버 값이 저장됩니다. 값을 보내면 서버가 비교합니다. 값이 다르면 Apple, Steam, PG 결제는 기본으로 요청을 거부하고, Google 결제는 요청을 거부하지 않습니다. 생략하면 비교하지 않습니다. |
ProductId | string | Required | 스토어에 등록한 인앱 상품 ID입니다. Steam과 PG 결제에서는 서버에 저장된 주문 정보를 사용하므로 이 값을 사용하지 않습니다. |
ProjectInfo | string? | Optional | 앱별 자유 형식 추가 데이터를 담은 JSON 문자열입니다. 저장만 하고 앱 서버에는 전달하지 않으므로, 앱 서버에 전달할 값은 IapPayload를 사용하세요. |
ProviderId | PurchaseRequestProviderId | Required | 결제 제공자입니다. |
Quantity | int? | Optional | 구매 수량입니다. |
RequestDate | DateTimeOffset? | Optional | 앱 클라이언트의 요청 시각입니다. 생략하면 서버의 현재 시각을 사용합니다. |
RequestType | int? | Optional | 요청 유형입니다. 1은 신규 구매, 2는 구매 복구입니다. |
ServerId | string? | Optional | 앱 서버 ID입니다. |
StoreTransactionId | string? | Optional | 스토어 측 주문 번호인 스토어 거래 ID입니다. |
PurchaseResponseData
결제 결과 저장 응답입니다.
| 필드 | 타입 | 필수 여부 | 설명 |
|---|---|---|---|
Meta | string? | Optional | 서버가 함께 전달한 부가 정보입니다. |
PurchaseRestoreRequest
Steam 또는 PG 구매 복구 요청입니다.
| 필드 | 타입 | 필수 여부 | 설명 |
|---|---|---|---|
AppVersion | string? | Optional | 앱 버전입니다. |
Country | string | Required | 국가 코드입니다. |
Language | string | Required | 언어 코드입니다. |
ProviderId | PurchaseRestoreRequestProviderId | Required | 결제 제공자입니다. Steam 또는 Pg를 지정합니다. |
ServerId | string? | Optional | 앱 서버 ID입니다. 지정하면 해당 서버의 주문만 반환하고, 생략하면 모든 주문을 반환합니다. |
PurchaseRestoreResponseData
구매 복구 응답입니다.
| 필드 | 타입 | 필수 여부 | 설명 |
|---|---|---|---|
Restores | IReadOnlyList<RestorePurchase>? | Optional | 복구할 수 있는 구매 목록입니다. |
Meta | string? | Optional | 서버가 함께 전달한 부가 정보입니다. |
RestorePurchase
복구할 수 있는 구매 하나의 정보입니다. ProviderId로 결제 제공자를 구분합니다.
| 필드 | 타입 | 필수 여부 | 설명 |
|---|---|---|---|
AxylReceipt | string? | Optional | 서버가 발급한 변조 확인용 영수증입니다. PG와 Steam 결제에서는 항상 반환되며, FinalizePurchaseAsync 요청의 AxylReceipt와 앱 서버가 보내는 소모성 상품 영수증 검증 요청의 axylReceipt에 그대로 넣습니다. Apple과 Google 결제에서는 스토어가 발급한 실제 영수증으로 검증하므로 null입니다. |
Currency | string? | Optional | 통화 코드입니다. |
GameServerPriceVerifyKey | string? | Optional | 앱 서버 금액 검증 키입니다. |
IapPayload | string? | Optional | 앱 서버에 전달할 추가 payload입니다. |
OrderId | string? | Optional | 주문 ID입니다. |
PaidDateTime | string? | Optional | 결제 완료 시각입니다. yyyy-MM-dd HH:mm:ss 형식입니다. |
PaidDateTimeMs | long? | Optional | 결제 완료 시각입니다. Unix epoch 밀리초입니다. |
Price | decimal? | Optional | 결제 금액입니다. |
ProductId | string? | Optional | 상품 ID입니다. |
ProviderId | RestorePurchaseProviderId | Required | 결제 제공자입니다. |
PurchaseDateTime | long? | Optional | 구매 시각입니다. Unix epoch 밀리초입니다. PG 결제에서는 StartedDateTime과 PaidDateTime을 대신 사용하므로 null입니다. |
Quantity | int? | Optional | 구매 수량입니다. |
StartedDateTime | string? | Optional | 결제 시작 시각입니다. yyyy-MM-dd HH:mm:ss 형식입니다. |
StartedDateTimeMs | long? | Optional | 결제 시작 시각입니다. Unix epoch 밀리초입니다. |
StoreTransactionId | string? | Optional | 스토어 거래 ID입니다. Steam은 Steam 거래 ID인 transid, PG는 스토어 거래 ID이며 OrderId와 다를 수 있습니다. |
StoreProduct
스토어 하나의 상품 ID 목록입니다.
| 필드 | 타입 | 필수 여부 | 설명 |
|---|---|---|---|
AppId | string? | Optional | 앱 ID입니다. |
ProductSubscriptions | IReadOnlyList<string>? | Optional | 구독 상품 ID 목록입니다. |
Products | IReadOnlyList<string>? | Optional | 소모성 상품 ID 목록입니다. |
ProviderId | StoreProductProviderId | Required | 결제 제공자입니다. |
StoreRequest
상품 ID 목록 조회 요청입니다.
| 필드 | 타입 | 필수 여부 | 설명 |
|---|---|---|---|
AppVersion | string? | Optional | 앱 버전입니다. |
Country | string | Required | 국가 코드입니다. |
Language | string | Required | 언어 코드입니다. |
ProviderId | StoreRequestProviderId | Required | 결제 제공자입니다. |
StoreResponseData
상품 ID 목록 조회 응답입니다.
| 필드 | 타입 | 필수 여부 | 설명 |
|---|---|---|---|
Stores | IReadOnlyList<StoreProduct> | Required | 스토어별 상품 ID 목록입니다. |
Meta | string? | Optional | 서버가 함께 전달한 부가 정보입니다. |
SubscriptionPrePurchaseRequest
구독 결제 전에 상품 정보와 IapPayload를 미리 저장하는 요청입니다.
| 필드 | 타입 | 필수 여부 | 설명 |
|---|---|---|---|
AccountUuid | string? | Optional | 계정 UUID입니다. AccountUuid 규칙을 따릅니다. 보내지 않아도 요청은 성공하지만, 스토어 계정 식별자 비교와 자동 갱신·구매 복구 때 사전 결제 기록 조회가 동작하지 않으므로 값을 보내세요. |
AppVersion | string? | Optional | 앱 버전입니다. |
Country | string | Required | 국가 코드입니다. |
Currency | string | Required | 통화 코드입니다. |
IapPayload | string? | Optional | 개발자가 정의한 payload입니다. |
Language | string | Required | 언어 코드입니다. |
Price | decimal | Required | 가격입니다. |
ProductId | string | Required | 상품 ID입니다. |
ProviderId | SubscriptionPrePurchaseRequestProviderId | Required | 결제 제공자입니다. |
RequestTimeMs | long? | Optional | 요청 시각입니다. Unix epoch 밀리초입니다. |
ServerId | string? | Optional | 앱 서버 ID입니다. |
SubscriptionPrePurchaseResponseData
구독 사전 결제 정보 저장 응답입니다.
| 필드 | 타입 | 필수 여부 | 설명 |
|---|---|---|---|
HiveAxylPrePurchaseId | string | Required | 저장한 사전 결제 기록의 ID입니다. UUIDv7 형식이며 기록을 추적하는 데 사용합니다. |
HiveAxylProductId | string | Required | 사전 결제를 기록한 구독 상품 ID입니다. |
Meta | string? | Optional | 서버가 함께 전달한 부가 정보입니다. |
SubscriptionPurchasePostRequest
구독 결제를 확정하고 거래를 종료하는 요청입니다.
| 필드 | 타입 | 필수 여부 | 설명 |
|---|---|---|---|
AppVersion | string? | Optional | 앱 버전입니다. |
AxylReceipt | string | Required | 결제 영수증입니다. AxylReceipt 규칙을 따릅니다. PurchaseSubscriptionAsync 요청에 보낸 값과 같은 값을 넣습니다. |
Country | string | Required | 국가 코드입니다. |
Currency | string | Required | 통화 코드입니다. |
Language | string | Required | 언어 코드입니다. |
ProductId | string | Required | 구독 상품 ID입니다. |
ProviderId | SubscriptionPurchasePostRequestProviderId | Required | 결제 제공자입니다. |
RequestTimeMs | long? | Optional | 요청 시각입니다. Unix epoch 밀리초입니다. |
RequestType | int? | Optional | 요청 유형입니다. 1은 신규 구매, 2는 구매 복구입니다. |
ServerId | string? | Optional | 앱 서버 ID입니다. |
SubscriptionPurchasePostResponseData
구독 결제 확정 응답입니다.
| 필드 | 타입 | 필수 여부 | 설명 |
|---|---|---|---|
HiveAxylProductId | string | Required | 확정한 구독 상품 ID입니다. 확정할 기록이 없었으면 요청 값이 그대로 반환됩니다. |
HiveAxylStoreTransactionId | string? | Optional | 구독 기록의 조회 키입니다. |
HiveAxylTransactionId | string? | Optional | 확정한 구독 기록의 거래 ID입니다. UUIDv7 형식입니다. 확정할 기록이 없었으면 null이므로, Success여도 이 값으로 실제 확정 여부를 판단하세요. |
Meta | string? | Optional | 서버가 함께 전달한 부가 정보입니다. |
SubscriptionPurchaseRequest
구독 구매 정보 저장 요청입니다.
| 필드 | 타입 | 필수 여부 | 설명 |
|---|---|---|---|
AppVersion | string? | Optional | 앱 버전입니다. |
AxylReceipt | string | Required | 결제 영수증입니다. AxylReceipt 규칙을 따릅니다. |
Country | string | Required | 국가 코드입니다. |
Currency | string | Required | 통화 코드입니다. |
Language | string | Required | 언어 코드입니다. |
OriginalPrice | decimal? | Optional | 할인 전 원래 가격입니다. |
Price | decimal | Required | 가격입니다. |
ProviderId | SubscriptionPurchaseRequestProviderId | Required | 결제 제공자입니다. |
RequestTimeMs | long? | Optional | 요청 시각입니다. Unix epoch 밀리초입니다. |
ServerId | string? | Optional | 앱 서버 ID입니다. |
StoreTransactionId | string? | Optional | 스토어 거래 ID입니다. Apple은 조회 키인 originalTransactionId가 거래 JWS 안에 있으므로 생략할 수 있으며, 값을 보내도 서버는 서명 검증을 통과한 JWS의 값을 사용합니다. Google은 보내지 않아도 되며, 서버가 영수증의 orderId로 조회 키를 만들고 orderId가 없으면 구매 토큰 해시를 사용합니다. |
SubscriptionPurchaseResponseData
구독 구매 정보 저장 응답입니다.
| 필드 | 타입 | 필수 여부 | 설명 |
|---|---|---|---|
HiveAxylProductId | string? | Optional | 저장된 구독 상품 ID입니다. 스토어 검증 결과에서 가져온 값입니다. |
HiveAxylStoreTransactionId | string? | Optional | 구독 기록의 조회 키입니다. 서버는 PostSubscriptionAsync로 구독을 확정할 때 이 키로 같은 기록을 찾습니다. |
HiveAxylTransactionId | string | Required | 저장된 구독 기록의 거래 ID입니다. UUIDv7 형식이며 구독 확정과 정산에 사용합니다. |
Meta | string? | Optional | 서버가 함께 전달한 부가 정보입니다. |
SuccessResponseData
반환할 데이터가 없는 메서드의 응답입니다.
| 필드 | 타입 | 필수 여부 | 설명 |
|---|---|---|---|
Meta | string? | Optional | 서버가 함께 전달한 부가 정보입니다. |
열거형
앱 코드에는 C# 멤버 이름을 입력하세요. 와이어 값은 서버와 주고받는 문자열입니다.
결제 제공자 열거형
요청과 응답 타입마다 전용 결제 제공자 열거형이 있습니다. 모든 결제 제공자 열거형은 멤버가 같으며, Unspecified의 와이어 값만 열거형마다 다릅니다.
| C# 멤버 | 와이어 값 | 설명 |
|---|---|---|
Unspecified | 열거형마다 다릅니다. | 값을 지정하지 않은 기본값입니다. 요청에 사용하지 마세요. |
Apple | APPLE | Apple App Store입니다. |
Google | GOOGLE | Google Play입니다. |
Pg | PG | PortOne, MyCard, Xsolla 같은 웹 결제 PG입니다. |
Steam | STEAM | Steam입니다. |
아래 표의 '지정할 값'은 요청 타입에 지정하는 결제 제공자입니다. 응답 타입에는 서버가 처리한 결제 제공자가 담깁니다.
| 열거형 | 사용 위치 | 지정할 값 | Unspecified 와이어 값 |
|---|---|---|---|
StoreRequestProviderId | StoreRequest.ProviderId | 모든 결제 제공자 | STORE_REQUEST_PROVIDER_ID_UNSPECIFIED |
StoreProductProviderId | StoreProduct.ProviderId | 응답 | STORE_PRODUCT_PROVIDER_ID_UNSPECIFIED |
ProductAppleProviderId | ProductApple.ProviderId | Apple | PRODUCT_APPLE_PROVIDER_ID_UNSPECIFIED |
ProductGoogleProviderId | ProductGoogle.ProviderId | Google | PRODUCT_GOOGLE_PROVIDER_ID_UNSPECIFIED |
ProductSteamProviderId | ProductSteam.ProviderId | Steam | PRODUCT_STEAM_PROVIDER_ID_UNSPECIFIED |
ProductPgProviderId | ProductPg.ProviderId | Pg | PRODUCT_PG_PROVIDER_ID_UNSPECIFIED |
ProductProviderId | ProductResponseData.ProviderId | 응답 | PRODUCT_PROVIDER_ID_UNSPECIFIED |
PurchaseInitRequestProviderId | PurchaseInitRequest.ProviderId | Steam | PURCHASE_INIT_REQUEST_PROVIDER_ID_UNSPECIFIED |
OrderRequestProviderId | OrderRequest.ProviderId | Pg | ORDER_REQUEST_PROVIDER_ID_UNSPECIFIED |
PrePurchaseProviderId | PrePurchase.ProviderId | 모든 결제 제공자 | PRE_PURCHASE_PROVIDER_ID_UNSPECIFIED |
PurchaseRequestProviderId | PurchaseRequest.ProviderId | 모든 결제 제공자 | PURCHASE_REQUEST_PROVIDER_ID_UNSPECIFIED |
PurchasePostRequestProviderId | PurchasePostRequest.ProviderId | 모든 결제 제공자 | PURCHASE_POST_REQUEST_PROVIDER_ID_UNSPECIFIED |
PurchaseFinalizeRequestProviderId | PurchaseFinalizeRequest.ProviderId | Steam, Pg | PURCHASE_FINALIZE_REQUEST_PROVIDER_ID_UNSPECIFIED |
PurchaseRestoreRequestProviderId | PurchaseRestoreRequest.ProviderId | Steam, Pg | PURCHASE_RESTORE_REQUEST_PROVIDER_ID_UNSPECIFIED |
RestorePurchaseProviderId | RestorePurchase.ProviderId | 응답 | RESTORE_PURCHASE_PROVIDER_ID_UNSPECIFIED |
SubscriptionPrePurchaseRequestProviderId | SubscriptionPrePurchaseRequest.ProviderId | Apple, Google | SUBSCRIPTION_PRE_PURCHASE_REQUEST_PROVIDER_ID_UNSPECIFIED |
SubscriptionPurchaseRequestProviderId | SubscriptionPurchaseRequest.ProviderId | Apple, Google | SUBSCRIPTION_PURCHASE_REQUEST_PROVIDER_ID_UNSPECIFIED |
SubscriptionPurchasePostRequestProviderId | SubscriptionPurchasePostRequest.ProviderId | Apple, Google | SUBSCRIPTION_PURCHASE_POST_REQUEST_PROVIDER_ID_UNSPECIFIED |
OrderRequestOs
앱 클라이언트의 OS입니다. OrderRequest.Os에 지정합니다.
| C# 멤버 | 와이어 값 | 설명 |
|---|---|---|
Unspecified | ORDER_REQUEST_OS_UNSPECIFIED | 값을 지정하지 않은 기본값입니다. 요청에 사용하지 마세요. |
Windows | WINDOWS | Windows입니다. |
Macos | MACOS | macOS입니다. |
Android | ANDROID | Android입니다. |
Ios | IOS | iOS입니다. |