콘텐츠로 이동

5단계. 상품 지급

Steam에서는 앱 서버의 영수증 검증 단계에서 실제 청구가 완료됩니다. 검증에 성공하면 앱 서버가 사용자에게 상품을 지급하고, 앱 클라이언트가 구매 완료 처리로 주문을 마감한 뒤 상품 지급 결과를 저장합니다. 앱 클라이언트가 이 단계에서 사용하는 hiveAxylTransactionId는 앱 서버가 영수증 검증 응답에서 받아 전달한 값입니다.

1. 상품 지급

앱 서버가 영수증 검증 결과를 확인한 뒤 결제한 사용자에게 상품을 지급합니다. 상품 지급은 앱에서 구현하며, 지급 방식은 앱별로 다를 수 있습니다.

구매 완료 처리는 앱 서버의 상품 지급이 끝난 뒤에 진행하세요. 미지급 주문 조회는 마감되지 않은 주문만 찾으므로, 지급보다 먼저 구매 완료 처리로 주문을 마감하면 지급 도중 앱이 중단됐을 때 그 주문을 다시 찾을 수 없습니다.

2. 구매 완료 처리

Steam 결제에서 최종 구매 완료 처리를 수행합니다. 이 단계는 결제 상태를 종료 처리하고 관련 데이터를 업데이트하며, 추가 청구를 수행하지 않습니다.

Method

FinalizePurchaseAsync

구매 완료 처리를 구현하려면 Hive Axyl SDK가 제공하는 FinalizePurchaseAsync()를 호출하세요. Steam 결제의 최종 구매 완료 처리를 수행하여 결제 상태를 종료 처리하고 관련 데이터를 갱신합니다. 실제 청구는 앞선 영수증 검증 단계에서 완료됩니다.

호출 파라미터

필드명 타입 필수 여부 설명
request PurchaseFinalizeRequest Required 구매 완료 요청 데이터입니다.
context ApiCallContext Optional 호출 단위 설정 객체입니다. 멱등키·취소 토큰·요청 정책을 지정하며, 생략하면 기본값이 사용됩니다.

PurchaseFinalizeRequest

필드명 타입 필수 여부 설명
AxylReceipt string Required 결제 세션 초기화 응답의 Data.AxylReceipt를 값 그대로 전달합니다. 구매 복구로 되찾은 구매라면 그 응답의 AxylReceipt를 전달합니다. 앱 서버에 영수증 검증을 요청할 때 전달한 봉인 영수증과 같은 값입니다. 서버가 이 값을 복호화해 완료 처리할 주문을 찾으므로, 값을 가공하면 요청이 거절됩니다.
ProviderId PurchaseFinalizeRequestProviderId Required 마켓 식별자입니다. Steam 구매 완료 처리 전용 요청이므로 Steam만 지정합니다.

호출 예시

PaymentsFinalizePurchaseResult의 성공 결과와 이 메서드에서 정의한 도메인별 결과(Outcome)는 아래 예시와 응답 상태에서 확인합니다. 요청 수행이 불가능한 공통 실패(Failure)의 결과 모델과 처리 원칙은 공통 오류 처리를 참조하세요.

using Hive.Axyl.Payments;
using Hive.Axyl.Core;

// payments: 초기화 시 등록된 IPaymentsService (자세한 획득은 [모듈 설치 및 초기화](../init.md) 참고)
IPaymentsService payments = HiveCore.Resolve<IPaymentsService>();

var request = new PurchaseFinalizeRequest
{
    AxylReceipt = axylReceipt, // 결제 세션 초기화 응답의 AxylReceipt. 앱 서버에 검증을 요청할 때 전달한 값과 같은 값
    ProviderId = PurchaseFinalizeRequestProviderId.Steam
};

PaymentsFinalizePurchaseResult result = await payments.FinalizePurchaseAsync(request);

switch (result)
{
    case PaymentsFinalizePurchaseResult.Success success:
        // 구매 완료 처리 성공. 주문번호와 스토어 거래 ID 확인
        Debug.Log($"orderId: {success.Data.OrderId}, storeTransactionId: {success.Data.StoreTransactionId}");
        break;

    case PaymentsFinalizePurchaseResult.PaymentBadRequest:
        // 요청을 처리할 수 없습니다. 요청 값과 호출 조건 확인
        break;

    case PaymentsFinalizePurchaseResult.PaymentInvalidParameter:
        // 유효하지 않은 파라미터입니다. 요청 값 확인
        break;

    // 공통 Failure 처리
    case PaymentsFinalizePurchaseResult.Failure failure:
        HiveError err = failure.Problem;
        Debug.LogError($"[{err.Code}] {err.Message} (trace: {err.TraceId})");
        break;

    // 안전망: 처리하지 않은 결과 및 알 수 없는 신규 결과(UnknownOutcome)
    default:
        Debug.LogWarning($"처리되지 않은 결과: {result.GetType().Name}");
        break;
}

응답 데이터

성공 시 PaymentsFinalizePurchaseResult.Success의 Data(PurchaseFinalizeResponseData)에 결과가 담깁니다.

필드명 타입 필수 여부 설명
Data.OrderId string Optional Steam 주문 번호입니다.
Data.StoreTransactionId string Optional Steam 거래 ID(transid)입니다.
Data.Meta string? Optional 응답 메타 정보입니다.

응답 예시

// Success 분기에서 success.Data 예시
// success.Data.OrderId = "2026010100001"
// success.Data.StoreTransactionId = "3390549843"

응답 상태

아래 표에는 PaymentsFinalizePurchaseResult의 성공 결과와 이 메서드에서 정의한 도메인별 결과(Outcome)를 정리했습니다. 요청 수행이 불가능한 공통 실패(Failure)의 결과 모델과 처리 원칙은 공통 오류 처리를 참조하세요.

응답 케이스 설명 앱 클라이언트 대응
Success 결제 상태가 완료로 변경되었습니다. 주문번호·거래 ID 확인 후 다음 단계 진행
PaymentBadRequest 요청을 처리할 수 없습니다. 요청 값과 호출 조건을 점검
PaymentInvalidParameter 유효하지 않은 파라미터입니다(예: 필수값 누락). 필수 필드 값 확인 후 수정
PaymentResourceNotFound 결제 정보를 찾을 수 없습니다. 영수증·주문 번호·결제 상태를 확인
UnknownOutcome SDK가 알 수 없는 도메인별 결과입니다. 실패로 처리하고 결과 코드를 기록
Failure 공통 Failure입니다. 공통 오류 처리를 참조하세요. 공통 오류 처리 기준에 따라 처리

3. 상품 지급 결과 저장

앱 서버에서 상품 지급을 완료한 후, 성공 또는 취소 등 지급 결과를 Hive Axyl 서버에 기록합니다.

Method

ItemResultAsync

소모성 상품 지급 결과 저장을 구현하려면 Hive Axyl SDK가 제공하는 ItemResultAsync()를 호출하세요. 상품 지급이 완료된 뒤 그 결과를 Hive Axyl 서버에 기록합니다. 이 메서드는 결제를 확정하거나 상품 지급 여부를 결정하지 않습니다.

호출 파라미터

필드명 타입 필수 여부 설명
request ItemResultBody Required 소모성 상품 지급 결과 저장 요청 데이터 객체입니다.
context ApiCallContext Optional 호출 단위 설정 객체입니다. 멱등키·취소 토큰·요청 정책을 지정하며, 생략하면 기본값이 사용됩니다.

ItemResultBody

필드명 타입 필수 여부 설명
AxylTransactionId string Required Hive Axyl 결제 트랜잭션 ID (접두사로 마켓 구분). 앱 서버가 영수증 검증 응답에서 받아 전달한 hiveAxylTransactionId 값을 사용합니다.
Status int Required 지급 결과 상태입니다. 1: 지급 성공, 2: 취소 후 상품 회수 없음, 3: 취소 후 상품 회수이며, 그 외 값은 유효하지 않습니다.
Assets IReadOnlyList<ItemResultAsset> Optional 실제 지급된 상품 목록입니다. 기록할 항목이 없으면 이 필드를 생략하세요.
ProjectPayloadInfo string Optional 앱별 자유 형식 JSON 데이터 (JSON 문자열)

ItemResultAsset

필드명 타입 필수 여부 설명
AssetId string Optional 앱 내 상품 고유 ID
AssetName string Optional 앱 내 상품 이름
Quantity int Optional 지급 수량입니다. 지정하는 경우 1 이상이어야 합니다.

호출 예시

PaymentsItemResultResult의 성공 결과와 이 메서드에서 정의한 도메인별 결과(Outcome)는 아래 예시와 응답 상태에서 확인합니다. 요청 수행이 불가능한 공통 실패(Failure)의 결과 모델과 처리 원칙은 공통 오류 처리를 참조하세요.

using Hive.Axyl.Payments;
using Hive.Axyl.Core;

// payments: 초기화 시 등록된 IPaymentsService (자세한 획득은 [모듈 설치 및 초기화](../init.md) 참고)
IPaymentsService payments = HiveCore.Resolve<IPaymentsService>();

// 상품 지급 완료 후, 지급 결과로 요청 객체 생성
var request = new ItemResultBody
{
    AxylTransactionId = axylTransactionId, // 앱 서버가 전달한 영수증 검증 응답의 hiveAxylTransactionId
    Status = 1, // 1: 지급 성공
    Assets = new[]
    {
        new ItemResultAsset { AssetId = "item_gold_100", AssetName = "골드 100개", Quantity = 1 }
    },
    ProjectPayloadInfo = "{\"serverId\":\"server01\"}" // (선택) 앱별 자유 형식 JSON 데이터
};

PaymentsItemResultResult result = await payments.ItemResultAsync(request);

switch (result)
{
    case PaymentsItemResultResult.Success success:
        // 지급 결과 기록 성공. success.Data.Meta를 확인할 수 있습니다.
        break;

    // 요청 값 문제 — 필수값·수량·상태값 확인
    case PaymentsItemResultResult.PaymentInvalidParameter:
    case PaymentsItemResultResult.PaymentBadRequest:
        Debug.LogError("요청 파라미터를 확인하세요.");
        break;

    // 공통 Failure 처리
    case PaymentsItemResultResult.Failure failure:
        HiveError err = failure.Problem;
        Debug.LogError($"[{err.Code}] {err.Message} (trace: {err.TraceId})");
        break;

    // 안전망: 처리하지 않은 결과 및 알 수 없는 신규 결과(UnknownOutcome)
    default:
        Debug.LogWarning($"처리되지 않은 결과: {result.GetType().Name}");
        break;
}

응답 데이터

성공 시 PaymentsItemResultResult.Success의 Data(SuccessResponseData)에 응답 메타 정보가 담깁니다.

필드명 타입 필수 여부 설명
Data.Meta string? Optional 응답 메타 정보입니다.

응답 예시

// Success 분기에서 success.Data.Meta를 확인할 수 있습니다.

응답 상태

아래 표에는 PaymentsItemResultResult의 성공 결과와 이 메서드에서 정의한 도메인별 결과(Outcome)를 정리했습니다. 요청 수행이 불가능한 공통 실패(Failure)의 결과 모델과 처리 원칙은 공통 오류 처리를 참조하세요.

응답 케이스 설명 앱 클라이언트 대응
Success 지급 결과 기록 성공 다음 결제 처리 진행
InvalidQuantity 지급 수량이 유효하지 않습니다. 지급 수량을 확인
InvalidStatus 지급 결과 상태 값이 유효하지 않습니다. Status 값을 확인
PaymentBadRequest 요청을 처리할 수 없습니다. 요청 값과 호출 조건을 점검
PaymentInvalidParameter 유효하지 않은 파라미터인 경우 (예: AxylTransactionId 누락) 필수 파라미터 설정 확인
PaymentResourceNotFound 결제 정보를 찾을 수 없습니다. 영수증·주문 번호·결제 상태를 확인
UnknownOutcome SDK가 알 수 없는 도메인별 결과입니다. 실패로 처리하고 결과 코드를 기록
Failure 공통 Failure입니다. 공통 오류 처리를 참조하세요. 공통 오류 처리 기준에 따라 처리

4. 선택: Steam 콜백 수신 해제

결제 플로우가 완전히 종료되어 더 이상 Steam 결제 승인 콜백을 수신할 필요가 없으면, StopCallbackListenerAsync()를 호출해 콜백 리스너를 해제합니다.

using Hive.Axyl.Core;
using Hive.Axyl.Payments.Addon.Steam;

if (HiveCore.TryResolve<ISteamMicrotransactionsPlugin>(out var steamPlugin))
{
    var stopResult = await steamPlugin.StopCallbackListenerAsync();
    switch (stopResult)
    {
        case SteamMicrotransactionsServiceStopCallbackListenerResult.Success:
            // 콜백 수신 해제 완료
            break;

        default:
            Debug.LogWarning($"콜백 수신 해제 실패: {stopResult.GetType().Name}");
            break;
    }
}
Note

StopCallbackListenerAsync()는 멱등성을 가집니다. 이미 해제된 상태에서 다시 호출해도 오류가 발생하지 않습니다.

더 알아보기

결제 과정에서 네트워크 오류 등으로 상품을 지급하지 못한 경우 구매 복구를 구현하세요.