구매 정보 기록
소모성 상품 결제에서는 스토어 결제창을 열기 전에 구매 시도 정보를, 결제 완료 후에 영수증과 거래 정보를 기록합니다. 이 두 기록을 기준으로 영수증 검증과 상품 지급을 같은 구매 건으로 처리합니다. 구독 상품은 Apple 결제와 Google 결제의 구독 구매 정보 저장 절차를 따르세요.
스토어 결제창 호출, 영수증 검증, 상품 지급은 결제 제공자별 결제 흐름에서 처리합니다. 영수증 검증은 앱 클라이언트가 전달한 영수증으로 앱 서버가 Hive Axyl Server API를 호출해 요청합니다. 결제 확정 요청과 지급 결과 기록의 역할은 결제 확정과 지급 결과 기록을 참조하세요.
처리 순서
1. 결제 전 구매 시도 정보 저장
CreatePrePurchaseAsync()는 사용자가 선택한 상품, 결제 예정 금액, 통화, 국가와 언어, 앱 서버, IapPayload를 사전 구매 추적 레코드로 저장합니다. 스토어 결제창을 열기 직전에 호출하세요.
CreatePrePurchaseAsync
호출 파라미터
| 필드명 | 타입 | 필수 여부 | 설명 |
|---|---|---|---|
| request | PrePurchase | Required | 구매 사전 정보 저장 요청 데이터 객체입니다. |
| context | ApiCallContext | Optional | 호출 단위 설정 객체입니다. 멱등키·취소 토큰·요청 정책을 지정하며, 생략하면 기본값이 사용됩니다. |
PrePurchase 요청 데이터는 아래와 같습니다.
| 필드명 | 타입 | 필수 여부 | 설명 |
|---|---|---|---|
Country | string | Required | 국가 코드 (ISO 3166-1 두 자리) |
Currency | string | Required | 결제 통화 (ISO 4217 세 자리) |
Language | string | Required | 언어 코드 (ISO 639-1 두 자리) |
Price | decimal | Required | 결제 예정 금액입니다. 통화에 따라 소수점이 포함될 수 있습니다. |
ProductId | string | Required | 마켓에 등록된 인앱 상품 ID |
ProviderId | PrePurchaseProviderId | Required | 마켓·결제 수단 식별자(enum). 멤버: Apple(Apple App Store), Google(Google Play), Steam(Steam), Pg(웹 결제 PG: PortOne·MyCard·Xsolla) |
ServerId | string | Optional | Hive 콘솔 앱 서버를 참조해 앱 정보 > 앱 서버에서 앱 서버를 등록한 뒤 앱 서버 탭에서 확인하는 서버 ID |
AccountUuid | string | Optional | 로그인한 사용자의 playerId로 생성한 UUIDv5 값입니다. 스토어 결제창을 열기 전에 전달합니다. AccountUuid 생성을 참조하세요. |
IapPayload | string | Optional | 개발자가 마켓 결제 시 첨부하는 페이로드(JSON 문자열). 구매 완료 후 앱 서버 콜백에 그대로 전달됩니다. |
RequestDate | DateTimeOffset | Optional | 요청 시각(UTC)입니다. 생략하면 서버의 현재 시각을 사용합니다. |
호출 예시
PaymentsCreatePrePurchaseResult의 성공 결과와 이 메서드에서 정의한 도메인별 결과(Outcome)는 아래 예시와 응답 상태에서 확인합니다. 요청 수행이 불가능한 공통 실패(Failure)의 결과 모델과 처리 원칙은 공통 오류 처리를 참조하세요.
using System;
using Hive.Axyl.Payments;
using Hive.Axyl.Core;
// payments: 초기화 시 등록된 IPaymentsService (자세한 획득은 [모듈 설치 및 초기화](../init.md) 참고)
IPaymentsService payments = HiveCore.Resolve<IPaymentsService>();
// 사용자가 결제 버튼을 누른 시점의 상품 정보로 요청 객체 생성
var request = new PrePurchase
{
Country = "KR",
Currency = "KRW",
Language = "ko",
Price = 1200.0m,
ProductId = "com.game.item.gold_100",
ProviderId = PrePurchaseProviderId.Google,
ServerId = "server01",
RequestDate = DateTimeOffset.UtcNow,
AccountUuid = accountUuid // 결제 사용자 식별 값
};
PaymentsCreatePrePurchaseResult result = await payments.CreatePrePurchaseAsync(request);
switch (result)
{
case PaymentsCreatePrePurchaseResult.Success success:
// 사전 저장 성공. 반환 데이터는 없습니다. 스토어 결제창 호출을 진행하세요.
break;
// 요청 값 문제 — 필수값과 형식 확인
case PaymentsCreatePrePurchaseResult.PaymentBadRequest:
case PaymentsCreatePrePurchaseResult.PaymentInvalidParameter:
Debug.LogError("요청 파라미터를 확인하세요.");
break;
case PaymentsCreatePrePurchaseResult.UnknownOutcome unknownOutcome:
Debug.LogWarning($"알 수 없는 결과: {unknownOutcome.Code}");
break;
// 공통 Failure 처리
case PaymentsCreatePrePurchaseResult.Failure failure:
HiveError err = failure.Problem;
Debug.LogError($"[{err.Code}] {err.Message} (trace: {err.TraceId})");
break;
// 안전망: 처리하지 않은 결과
default:
Debug.LogWarning($"처리되지 않은 결과: {result.GetType().Name}");
break;
}
응답 데이터
성공 시 별도 반환 데이터는 없습니다.
응답 예시
응답 상태
아래 표에는 PaymentsCreatePrePurchaseResult의 성공 결과와 이 메서드에서 정의한 도메인별 결과(Outcome)를 정리했습니다. 요청 수행이 불가능한 공통 실패(Failure)의 결과 모델과 처리 원칙은 공통 오류 처리를 참조하세요. 성공 시 별도의 반환 데이터는 없습니다.
| 응답 케이스 | 설명 | 앱 클라이언트 대응 |
|---|---|---|
Success | 사전 저장 성공 | 스토어 결제창 호출 진행 |
PaymentBadRequest | 결제 요청을 처리할 수 없습니다. | 요청 값과 호출 조건을 점검 |
PaymentInvalidParameter | 결제 요청 파라미터가 유효하지 않습니다. | 요청 필드 값을 점검 |
UnknownOutcome | SDK가 알 수 없는 도메인별 결과입니다. | 실패로 처리하고 결과 코드를 기록 |
Failure | 공통 Failure입니다. 공통 오류 처리를 참조하세요. | 공통 오류 처리 기준에 따라 처리 |
2. 스토어 결제 결과 저장
RecordStorePurchaseAsync()는 스토어 결제 완료 직후 영수증, 거래 ID 등 결제 결과를 저장합니다. 영수증 검증 전에 원본 결제 사실을 기록하므로, 이후 단계가 중단되어도 검증, 상품 지급, 고객 지원, 정산의 근거로 활용할 수 있습니다.
RecordStorePurchaseAsync
호출 파라미터
| 필드명 | 타입 | 필수 여부 | 설명 |
|---|---|---|---|
| request | PurchaseRequest | Required | 결제 결과 저장 요청 데이터 객체입니다. |
| context | ApiCallContext | Optional | 호출 단위 설정 객체입니다. 멱등키·취소 토큰·요청 정책을 지정하며, 생략하면 기본값이 사용됩니다. |
PurchaseRequest 요청 데이터는 아래와 같습니다.
| 필드명 | 타입 | 필수 여부 | 설명 |
|---|---|---|---|
AccountUuid | string | Optional | 로그인한 사용자의 playerId로 생성한 UUIDv5 값입니다. 스토어 결제가 끝난 뒤 구매 결과 기록에 전달합니다. 결제 시작 단계에 전달한 경우 같은 값을 사용하세요. AccountUuid 생성을 참조하세요. |
AxylReceipt | string | Required | 마켓 영수증입니다. Apple은 JWS, Google은 구매 토큰(purchaseToken), Steam과 PG는 Hive Axyl 서버가 발급한 봉인 영수증을 전달합니다. |
Country | string | Required | 국가 코드(ISO 3166-1 두 자리)입니다. |
Currency | string | Optional | 결제 통화(ISO 4217 세 자리)입니다. Price와 짝을 이뤄 서버가 기록한 값과 대조하는 데 사용합니다. 둘 중 하나만 보내면 통화는 대조하지 않고 금액만 대조합니다. |
IapPayload | string | Optional | 개발자가 마켓 결제 시 첨부한 페이로드(JSON 문자열). 앱 서버 검증과 구매 완료 콜백에 그대로 전달됩니다. |
Language | string | Required | 언어 코드(ISO 639-1 두 자리)입니다. |
OrderId | string | Optional | Hive Axyl 내부 주문 번호입니다. Steam/PG에 사용합니다. |
Price | decimal | Optional | 결제 금액입니다. 통화에 따라 소수점이 포함될 수 있습니다. 보내면 서버가 기록한 금액과 대조하고, 생략하면 대조하지 않습니다. Apple, Steam, PG 결제는 금액이 다르면 요청을 거절하고, Google 결제는 기록만 합니다. 결제 내역에 남는 금액은 서버가 확인한 값입니다. |
ProductId | string | Required | 마켓에 등록한 인앱 상품 ID입니다. |
ProjectInfo | string | Optional | 앱별 자유 형식 JSON 문자열입니다. 값은 저장만 하며 앱 서버로 전달하지 않습니다. 앱 서버로 전달할 값은 IapPayload에 설정하세요. |
ProviderId | PurchaseRequestProviderId | Required | 마켓·결제 수단 식별자입니다. |
Quantity | int | Optional | 구매 수량 |
RequestDate | DateTimeOffset | Optional | 클라이언트 요청 시각(UTC)입니다. 생략하면 서버의 현재 시각을 사용합니다. |
RequestType | int | Optional | 요청 유형입니다. 1: 신규 구매, 2: 구매 복원 |
ServerId | string | Optional | Hive 콘솔 앱 서버를 참조해 등록한 앱 서버 ID입니다. |
StoreTransactionId | string | Optional | 마켓 측 스토어 거래 ID입니다. |
호출 예시
PaymentsRecordStorePurchaseResult의 성공 결과와 이 메서드에서 정의한 도메인별 결과(Outcome)는 아래 예시와 응답 상태에서 확인합니다. 요청 수행이 불가능한 공통 실패(Failure)의 결과 모델과 처리 원칙은 공통 오류 처리를 참조하세요.
using System;
using Hive.Axyl.Payments;
using Hive.Axyl.Core;
// payments: 초기화 시 등록된 IPaymentsService (자세한 획득은 [모듈 설치 및 초기화](../init.md) 참고)
IPaymentsService payments = HiveCore.Resolve<IPaymentsService>();
// 스토어 결제 완료 직후, 마켓이 발급한 영수증으로 요청 객체 생성
var request = new PurchaseRequest
{
AxylReceipt = purchaseToken, // Google: 구매 토큰
ProviderId = PurchaseRequestProviderId.Google,
ProductId = "com.game.item.gold_100",
Price = 1200.0m,
Currency = "KRW",
Country = "KR",
Language = "ko",
Quantity = 1,
StoreTransactionId = "GPA.3389-9543-8198-17604",
RequestType = 1, // 1: 신규 구매
RequestDate = DateTimeOffset.UtcNow,
ServerId = "server01",
AccountUuid = accountUuid // 결제 사용자 식별 값
};
PaymentsRecordStorePurchaseResult result = await payments.RecordStorePurchaseAsync(request);
switch (result)
{
case PaymentsRecordStorePurchaseResult.Success success:
// 저장 성공. success.Data.Meta를 확인할 수 있습니다.
break;
// 요청 값 또는 결제 상태 문제
case PaymentsRecordStorePurchaseResult.PaymentBadRequest:
case PaymentsRecordStorePurchaseResult.PaymentInvalidParameter:
case PaymentsRecordStorePurchaseResult.PaymentResourceNotFound:
case PaymentsRecordStorePurchaseResult.PaymentUnauthorized:
case PaymentsRecordStorePurchaseResult.VerifyError:
Debug.LogError("요청 값과 결제 상태를 확인하세요.");
break;
case PaymentsRecordStorePurchaseResult.UnknownOutcome unknownOutcome:
Debug.LogWarning($"알 수 없는 결과: {unknownOutcome.Code}");
break;
// 공통 Failure 처리
case PaymentsRecordStorePurchaseResult.Failure failure:
HiveError err = failure.Problem;
Debug.LogError($"[{err.Code}] {err.Message} (trace: {err.TraceId})");
break;
// 안전망: 처리하지 않은 결과
default:
Debug.LogWarning($"처리되지 않은 결과: {result.GetType().Name}");
break;
}
응답 데이터
성공 시 PaymentsRecordStorePurchaseResult.Success의 Data(PurchaseResponseData)에 결과가 담깁니다.
| 필드명 | 타입 | 필수 여부 | 설명 |
|---|---|---|---|
Data.Meta | string | Optional | 응답 메타 정보 |
응답 예시
응답 상태
아래 표에는 PaymentsRecordStorePurchaseResult의 성공 결과와 이 메서드에서 정의한 도메인별 결과(Outcome)를 정리했습니다. 요청 수행이 불가능한 공통 실패(Failure)의 결과 모델과 처리 원칙은 공통 오류 처리를 참조하세요.
| 응답 케이스 | 설명 | 앱 클라이언트 대응 |
|---|---|---|
Success | 결제 결과 저장 성공 | 앱 서버에 영수증을 전달해 영수증 검증 단계로 진행 |
PaymentBadRequest | 결제 요청을 처리할 수 없습니다. | 요청 값과 호출 조건을 점검 |
PaymentInvalidParameter | 결제 요청 파라미터가 유효하지 않습니다. | AxylReceipt 등 요청 필드를 점검 |
PaymentResourceNotFound | 저장할 결제 정보를 찾을 수 없습니다. | 영수증과 거래 정보를 점검 |
PaymentUnauthorized | 결제 요청 권한이 없습니다. | 앱과 인증 상태를 점검 |
VerifyError | 결제 검증 중 오류가 발생했습니다. | 영수증과 마켓 결제 상태를 점검 |
UnknownOutcome | SDK가 알 수 없는 도메인별 결과입니다. | 실패로 처리하고 결과 코드를 기록 |
Failure | 공통 Failure입니다. 공통 오류 처리를 참조하세요. | 공통 오류 처리 기준에 따라 처리 |
다음 단계
구매 흐름을 구현하려면 Apple App Store 결제, Google Play 결제, Steam 결제, PG 결제를 참조하세요.