콘텐츠로 이동

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를 호출해 요청합니다. 앱 클라이언트가 결제 후 영수증 정보를 앱 서버에 전달하면, 앱 서버는 소모성 상품이면 소모성 상품 영수증 검증을, 구독 상품이면 구독 상품 영수증 검증을 호출합니다.

결제 제공자별 구현 절차는 아래를 참조하세요.

공통 파라미터

모든 메서드의 마지막 파라미터는 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 목록을 반환합니다.

Task<PaymentsListStoreProductIdsResult> ListStoreProductIdsAsync(StoreRequest request, ApiCallContext? context = null);

결과 케이스 — 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으로 조회한 현지 가격, 통화, 표시 가격, 제목, 설명 같은 상품 정보를 함께 보내면, 서버가 등록된 상품 정보와 비교하고 병합해 앱 상점에 표시할 최종 상품 목록을 반환합니다.

Task<PaymentsFetchAppleProductsResult> FetchAppleProductsAsync(ProductApple request, ApiCallContext? context = null);

결과 케이스 — PaymentsFetchAppleProductsResult

결과 케이스 와이어 코드 설명
Success — 조회에 성공했습니다.
PaymentBadRequest payment_bad_request 결제 요청을 처리할 수 없습니다.
PaymentInvalidParameter payment_invalid_parameter 결제 요청 파라미터가 유효하지 않습니다.
UnknownOutcome UNKNOWN 이 SDK 버전이 알지 못하는 새 결과입니다.
Failure FAILURE 호출을 마치지 못했습니다. 공통 Failure 코드도 이 케이스로 분기합니다.

구현 절차는 Apple 상품 상세 정보 조회를 참조하세요.


FetchGoogleProductsAsync

Google Play 인앱 상품 목록을 조회합니다. Google Play Billing으로 조회한 현지 가격, 통화, 표시 가격, 제목, 설명 같은 상품 정보를 함께 보내면, 서버가 등록된 상품 정보와 비교하고 병합해 앱 상점에 표시할 최종 상품 목록을 반환합니다.

Task<PaymentsFetchGoogleProductsResult> FetchGoogleProductsAsync(ProductGoogle request, ApiCallContext? context = null);

결과 케이스 — 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 계정 연동 검증과 차단 확인도 함께 수행합니다.

Task<PaymentsFetchSteamProductsResult> FetchSteamProductsAsync(ProductSteam request, ApiCallContext? context = null);

결과 케이스 — PaymentsFetchSteamProductsResult

결과 케이스 와이어 코드 설명
Success — 조회에 성공했습니다.
PaymentBadRequest payment_bad_request 결제 요청을 처리할 수 없습니다.
PaymentInvalidParameter payment_invalid_parameter 결제 요청 파라미터가 유효하지 않습니다.
UnknownOutcome UNKNOWN 이 SDK 버전이 알지 못하는 새 결과입니다.
Failure FAILURE 호출을 마치지 못했습니다. 공통 Failure 코드도 이 케이스로 분기합니다.

구현 절차는 Steam 상품 상세 정보 조회를 참조하세요.


FetchPgProductsAsync

웹 결제 PG 상품 목록을 조회합니다. PortOne, MyCard, Xsolla 같은 PG사가 여기에 해당합니다. 요청한 통화를 기준으로 등록된 상품과 통화별 가격 등급에 맞는 가격을 조합해 상점에 표시할 목록을 반환합니다.

Task<PaymentsFetchPgProductsResult> FetchPgProductsAsync(ProductPg request, ApiCallContext? context = null);

결과 케이스 — 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 결제는 아래 순서로 진행합니다.

  1. FetchSteamProductsAsync로 사용자의 통화에 맞춘 상품 목록을 조회합니다.
  2. StartCallbackListenerAsync()로 콜백 수신을 시작한 뒤 InitiatePurchaseAsync로 주문을 만듭니다.
  3. 사용자가 Steam 오버레이에서 결제를 승인하면 Steam Microtransactions 결제 Add-on의 MicroTxnAuthorizationResponse 이벤트로 승인 결과를 받습니다.
  4. RecordStorePurchaseAsync로 결제 결과를 저장합니다. 서버가 Steam QueryTxn으로 승인을 확인합니다.
  5. 앱 클라이언트가 영수증 정보를 앱 서버에 전달하고, 앱 서버가 소모성 상품 영수증 검증을 호출해 영수증을 검증합니다. 이 단계에서 Steam FinalizeTxn으로 실제 청구가 발생합니다.
  6. 앱 서버가 검증 결과를 확인하고 상품을 지급합니다.
  7. FinalizePurchaseAsync로 주문을 종료합니다.
  8. ItemResultAsync로 상품 지급 결과를 확정합니다.
Task<PaymentsInitiatePurchaseResult> InitiatePurchaseAsync(PurchaseInitRequest request, ApiCallContext? context = null);

결과 케이스 — PaymentsInitiatePurchaseResult

결과 케이스 와이어 코드 설명
Success — 주문을 만들었습니다.
PaymentBadRequest payment_bad_request 결제 요청을 처리할 수 없습니다.
PaymentInvalidParameter payment_invalid_parameter 결제 요청 파라미터가 유효하지 않습니다.
UnknownOutcome UNKNOWN 이 SDK 버전이 알지 못하는 새 결과입니다.
Failure FAILURE 호출을 마치지 못했습니다. 공통 Failure 코드도 이 케이스로 분기합니다.

구현 절차는 Steam 결제 세션 초기화를 참조하세요.


CreatePaymentUrlAsync

주문 정보를 바탕으로 사용자가 결제를 진행할 PG 결제 페이지 URL을 만들어 반환합니다. 앱이 WebView나 브라우저로 이 URL을 열면 사용자는 PG 결제 페이지에서 결제를 진행합니다. 발급된 URL은 주문 만료 시간 안에서만 유효합니다.

Task<PaymentsCreatePaymentUrlResult> CreatePaymentUrlAsync(OrderRequest request, ApiCallContext? context = null);

결과 케이스 — PaymentsCreatePaymentUrlResult

결과 케이스 와이어 코드 설명
Success — 결제 페이지 URL을 만들었습니다.
PaymentBadRequest payment_bad_request 결제 요청을 처리할 수 없습니다.
PaymentInvalidParameter payment_invalid_parameter 결제 요청 파라미터가 유효하지 않습니다.
UnknownOutcome UNKNOWN 이 SDK 버전이 알지 못하는 새 결과입니다.
Failure FAILURE 호출을 마치지 못했습니다. 공통 Failure 코드도 이 케이스로 분기합니다.

구현 절차는 PG 결제 페이지 URL 생성을 참조하세요.


CreatePrePurchaseAsync

사용자가 상품을 고르고 결제 버튼을 누른 뒤, 스토어 결제 창을 열기 직전에 호출합니다. 상품 ID, 결제 금액, 통화, 앱 서버, 국가와 언어, IapPayload 같은 결제 시도 정보를 사전 결제 기록으로 저장합니다. 저장한 기록은 구매 복구를 처리할 때 해당 결제 시도와 저장된 IapPayload를 찾는 데 사용합니다.

Task<PaymentsCreatePrePurchaseResult> CreatePrePurchaseAsync(PrePurchase request, ApiCallContext? context = null);

결과 케이스 — PaymentsCreatePrePurchaseResult

결과 케이스 와이어 코드 설명
Success — 결제 시도 정보를 저장했습니다.
PaymentBadRequest payment_bad_request 결제 요청을 처리할 수 없습니다.
PaymentInvalidParameter payment_invalid_parameter 결제 요청 파라미터가 유효하지 않습니다.
UnknownOutcome UNKNOWN 이 SDK 버전이 알지 못하는 새 결과입니다.
Failure FAILURE 호출을 마치지 못했습니다. 공통 Failure 코드도 이 케이스로 분기합니다.

구현 절차는 결제 전 구매 시도 정보 저장을 참조하세요.


RecordStorePurchaseAsync

스토어에서 결제가 끝난 직후 호출해 영수증과 스토어 거래 ID 같은 결제 결과를 서버에 저장합니다. 앱 서버가 영수증을 검증하기 전에 결제 사실을 먼저 남겨 두므로, 이후 단계가 네트워크 장애 등으로 중단되어도 이 기록이 영수증 검증, 상품 지급, 고객 지원과 정산의 근거가 됩니다.

Steam 결제에서는 이 단계에서 서버가 Steam QueryTxn으로 사용자의 결제 승인을 확인합니다.

Task<PaymentsRecordStorePurchaseResult> RecordStorePurchaseAsync(PurchaseRequest request, ApiCallContext? context = null);

결과 케이스 — 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

결제 상태를 확정하고 거래를 종료 상태로 바꿔, 같은 거래가 중복으로 지급되거나 다시 처리되지 않게 합니다. 앱 서버가 영수증 검증을 마친 뒤 호출합니다.

Task<PaymentsRequestPurchaseResult> RequestPurchaseAsync(PurchasePostRequest request, ApiCallContext? context = null);

결과 케이스 — 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 결제에서는 이 단계에서 거래를 완료합니다.

Task<PaymentsFinalizePurchaseResult> FinalizePurchaseAsync(PurchaseFinalizeRequest request, ApiCallContext? context = null);

결과 케이스 — 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으로 다시 확인하고, 결제가 성공했거나 승인된 주문을 복구합니다.

Task<PaymentsRestorePurchasesResult> RestorePurchasesAsync(PurchaseRestoreRequest request, ApiCallContext? context = null);

결과 케이스 — 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 서버에 기록하고 거래를 확정합니다. 앱 안에서 지급이 실제로 성공했는지 서버에서 확인해 결제와 지급의 일관성을 유지하며, 실패하거나 취소된 건의 환불과 재지급을 판단하는 근거로 사용합니다.

Task<PaymentsItemResultResult> ItemResultAsync(ItemResultBody request, ApiCallContext? context = null);

결과 케이스 — 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를 반환합니다.

Task<PaymentsPrepareSubscriptionResult> PrepareSubscriptionAsync(SubscriptionPrePurchaseRequest request, ApiCallContext? context = null);

결과 케이스 — 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에는 이 메서드에 보낸 값과 같은 값을 넣으세요.

Task<PaymentsPurchaseSubscriptionResult> PurchaseSubscriptionAsync(SubscriptionPurchaseRequest request, ApiCallContext? context = null);

결과 케이스 — 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인지 확인해 실제로 확정됐는지 판단하세요.

Task<PaymentsPostSubscriptionResult> PostSubscriptionAsync(SubscriptionPurchasePostRequest request, ApiCallContext? context = null);

결과 케이스 — 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 두 글자 국가 코드. 예: KR
  • Currency: ISO 4217 세 글자 통화 코드. 예: KRW
  • Language: ISO 639-1 두 글자 언어 코드. 예: ko
  • ServerId: 앱 서버 ID
  • AccountUuid: 결제한 사용자와 요청한 사용자가 같은지 확인하는 계정 UUID. 만드는 방법과 용도는 AccountUuid 규칙을 참조하세요.
  • AxylReceipt: 결제 영수증. 결제 제공자별로 넣는 값은 AxylReceipt 규칙을 참조하세요.
  • Meta: 서버가 함께 전달한 부가 정보. 가공되지 않은 원본 JSON 문자열로 담깁니다.

아래 요청 필드는 타입이 string?이지만 JSON 텍스트를 담습니다. SDK가 값을 가공하지 않고 요청 본문에 그대로 넣으므로 올바른 JSON 객체를 넣으세요. 예를 들어 ItemResultBody.ProjectPayloadInfo에는 {"serverId":"server01","eventId":"summer_sale"}처럼 넣습니다.

  • ItemResultBody.ProjectPayloadInfo
  • ProductGoogleOfferDetails.PreorderDetails
  • ProductGoogleOfferDetails.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, Google obfuscatedExternalAccountId와 비교할 값. 비교 결과는 앱 서버가 받는 소모성 상품 영수증 검증과 구독 상품 영수증 검증 응답의 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 결제에서는 서버가 저장된 주문 정보와 영수증을 비교합니다.

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입니다.