구매 복구
통신 오류나 비정상 종료로 결제는 완료됐지만 상품을 받지 못한 미지급 건을 다시 조회해, 누락된 상품을 지급합니다. 이로써 결제 관련 불만을 줄이고 사용자의 구매 자산을 보호합니다.
아래 과정을 따라 미완료 거래를 복구합니다.
1. 미완료 거래 복구
RestorePurchasesAsync
구매 복구를 구현하려면 Hive Axyl SDK가 제공하는 RestorePurchasesAsync()를 호출하세요. 결제는 완료했지만 상품을 아직 지급하지 않은 구매 목록을 반환합니다.
호출 파라미터
| 필드명 | 타입 | 필수 여부 | 설명 |
|---|---|---|---|
| request | PurchaseRestoreRequest | Required | 구매 복구 요청 데이터입니다. |
| context | ApiCallContext | Optional | 호출 단위 설정 객체입니다. 멱등키·취소 토큰·요청 정책을 지정하며, 생략하면 기본값이 사용됩니다. |
PurchaseRestoreRequest
| 필드명 | 타입 | 필수 여부 | 설명 |
|---|---|---|---|
ProviderId | PurchaseRestoreRequestProviderId | Required | 마켓 식별자입니다. Steam 구매 복구 전용 요청이므로 Steam만 지정합니다. |
AppVersion | string | Optional | 앱 버전입니다. |
Country | string | Required | 국가 코드(ISO 3166-1 두 자리)입니다. 예: KR |
Language | string | Required | 언어 코드(ISO 639-1 두 자리)입니다. 예: ko |
ServerId | string | Optional | Hive 콘솔 앱 서버를 따라 앱 정보 > 앱 서버에서 앱 서버를 등록한 뒤 앱 서버 탭에서 확인하는 서버 ID입니다. 지정하면 해당 서버의 주문만 반환하고, 생략하면 모든 주문을 반환합니다. |
호출 예시
PaymentsRestorePurchasesResult의 성공 결과와 이 메서드에서 정의한 도메인별 결과(Outcome)는 아래 예시와 응답 상태에서 확인합니다. 요청 수행이 불가능한 공통 실패(Failure)의 결과 모델과 처리 원칙은 공통 오류 처리를 참조하세요.
using Hive.Axyl.Payments;
using Hive.Axyl.Core;
// payments: 초기화 시 등록된 IPaymentsService (자세한 획득은 [모듈 설치 및 초기화](../init.md) 참고)
IPaymentsService payments = HiveCore.Resolve<IPaymentsService>();
var request = new PurchaseRestoreRequest
{
ProviderId = PurchaseRestoreRequestProviderId.Steam,
Country = "KR",
Language = "ko",
ServerId = "server01"
};
PaymentsRestorePurchasesResult result = await payments.RestorePurchasesAsync(request);
switch (result)
{
case PaymentsRestorePurchasesResult.Success success:
// 복구 가능한 구매 목록 처리
if (success.Data.Restores is { } restores)
{
foreach (var restore in restores)
{
Debug.Log($"orderId: {restore.OrderId}, productId: {restore.ProductId}");
}
}
break;
case PaymentsRestorePurchasesResult.PaymentBadRequest:
// 요청을 처리할 수 없습니다. 요청 값과 호출 조건 확인
break;
case PaymentsRestorePurchasesResult.PaymentInvalidParameter:
// 유효하지 않은 파라미터입니다. 요청 값 확인
break;
// 공통 Failure 처리
case PaymentsRestorePurchasesResult.Failure failure:
HiveError err = failure.Problem;
Debug.LogError($"[{err.Code}] {err.Message} (trace: {err.TraceId})");
break;
// 안전망: 처리하지 않은 결과 및 알 수 없는 신규 결과(UnknownOutcome)
default:
Debug.LogWarning($"처리되지 않은 결과: {result.GetType().Name}");
break;
}
응답 데이터
성공 시 PaymentsRestorePurchasesResult.Success의 Data(PurchaseRestoreResponseData)에 결과가 담깁니다.
| 필드명 | 타입 | 필수 여부 | 설명 |
|---|---|---|---|
Data.Restores | IReadOnlyList<RestorePurchase>? | Optional | 복구 가능한 구매 목록입니다. |
Data.Meta | string? | Optional | 응답 메타 정보입니다. |
RestorePurchase
| 필드명 | 타입 | 필수 여부 | 설명 |
|---|---|---|---|
Currency | string | Optional | 통화 코드입니다. |
GameServerPriceVerifyKey | string | Optional | 앱 서버 결제 금액 검증 키입니다. |
IapPayload | string | Optional | 앱 서버로 전달할 추가 페이로드입니다. |
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(market_pid)입니다. |
ProviderId | RestorePurchaseProviderId | Required | 결제 수단 식별자입니다. 이 응답에서는 Steam이 반환됩니다. |
PurchaseDateTime | long | Optional | 구매 일시입니다(Unix epoch 밀리초 단위). |
Quantity | int | Optional | 구매 수량입니다. |
StartedDateTime | string | Optional | 결제 시작 시각입니다(yyyy-MM-dd HH:mm:ss). |
StartedDateTimeMs | long | Optional | 결제 시작 시각입니다(Unix epoch 밀리초 단위). |
StoreTransactionId | string | Optional | Steam 스토어 거래 ID(transid)입니다. 주문 ID와 다를 수 있습니다. |
AxylReceipt | string | Optional | 서버가 발급한 변조 검증용 봉인 영수증입니다. Steam은 이 값이 항상 내려오므로, 앱 서버에 전달하는 영수증 정보의 axylReceipt와 구매 완료 처리 요청의 AxylReceipt로 그대로 사용합니다. |
응답 예시
// Success 분기에서 success.Data 예시
// success.Data.Restores[0].OrderId = "1000000012345"
// success.Data.Restores[0].ProductId = "com.example.gem.100"
// success.Data.Restores[0].ProviderId = RestorePurchaseProviderId.Steam
// success.Data.Restores[0].Price = 9900.0
// success.Data.Restores[0].Currency = "KRW"
// success.Data.Restores[0].Quantity = 1
// success.Data.Restores[0].PurchaseDateTime = 1717200000000
// success.Data.Restores[0].StoreTransactionId = "421799706624185538"
응답 상태
아래 표에는 PaymentsRestorePurchasesResult의 성공 결과와 이 메서드에서 정의한 도메인별 결과(Outcome)를 정리했습니다. 요청 수행이 불가능한 공통 실패(Failure)의 결과 모델과 처리 원칙은 공통 오류 처리를 참조하세요.
| 응답 케이스 | 설명 | 앱 클라이언트 대응 |
|---|---|---|
Success | 복구 가능한 구매 목록이 반환되었습니다. | 각 구매 건의 AxylReceipt를 앱 서버에 전달해 영수증 검증 진행 후 상품 지급 |
PaymentBadRequest | 요청을 처리할 수 없습니다. | 요청 값과 호출 조건을 점검 |
PaymentInvalidParameter | 유효하지 않은 파라미터입니다(예: 필수값 누락). | 필수 필드 값 확인 후 수정 |
PaymentResourceNotFound | 결제 정보를 찾을 수 없습니다. | 영수증·주문 번호·결제 상태를 확인 |
UnknownOutcome | SDK가 알 수 없는 도메인별 결과입니다. | 실패로 처리하고 결과 코드를 기록 |
Failure | 공통 Failure입니다. 공통 오류 처리를 참조하세요. | 공통 오류 처리 기준에 따라 처리 |
2. 영수증 검증 및 상품 지급
다시 획득한 영수증 AxylReceipt를 가지고 아래 과정을 다시 진행합니다. 복구한 구매는 이미 Steam 승인을 확인한 주문이므로 영수증 정보 준비 단계부터 시작하세요.
- 영수증 정보를 준비해 앱 서버에 전달합니다. 앱 서버가 보내는 영수증 검증 요청의
requestType은2(구매 복원)로 설정합니다. - 앱 서버가 Hive Axyl Server API로 영수증을 검증합니다.
- 검증이 완료되면 상품을 지급하고 구매 완료 처리를 합니다.