구매 복구
통신 오류나 비정상 종료로 결제는 완료됐지만 상품을 받지 못한 미지급 건을 다시 조회해, 누락된 상품을 지급합니다. 이로써 결제 관련 불만을 줄이고 사용자의 구매 자산을 보호합니다.
앱을 실행하거나 결제 실패 후 다시 시도할 때 구매 복구를 실행하세요.
아래 과정을 따라 미지급 구매를 복구합니다.
1. 미지급 영수증 재조회
Apple 결제 플러그인(IAppleStoreKitPlugin)이 제공하는 복구 관련 메서드를 사용하여 Apple App Store에서 미지급 상품의 구매 영수증을 다시 획득합니다.
1.1. 구매 동기화 (Restore Purchases)
SyncAsync
SyncAsync()를 호출하면 Apple의 AppStore.sync를 실행하여 구매 내역을 동기화합니다. 이 호출은 사용자에게 Apple ID 재인증 대화 상자를 표시할 수 있습니다. 앱 실행 시점이나 사용자가 명시적으로 "구매 복원" 버튼을 누를 때 호출하세요.
호출 파라미터
| 필드명 | 타입 | 필수 여부 | 설명 |
|---|---|---|---|
| request | SyncRequest | Required | 동기화 요청 데이터 객체입니다. 별도 파라미터는 없습니다. |
| ct | CancellationToken | Optional | 취소 토큰입니다. |
호출 예시
네트워크·스토어처럼 요청 수행이 불가능한 경우는 공통 실패(Failure)로 처리합니다. Failure에 담긴 HiveError와 사용자 취소 같은 도메인별 결과(Outcome)의 구분은 공통 오류 처리를 참조하세요.
using Hive.Axyl.Core;
using Hive.Axyl.Payments.Addon.Apple;
using System.Threading;
// Apple StoreKit 플러그인 획득
if (!HiveCore.TryResolve<IAppleStoreKitPlugin>(out var applePlugin))
{
Debug.LogError("Apple StoreKit 플러그인이 등록되지 않았습니다.");
return;
}
AppleStoreKitServiceSyncResult result = await applePlugin.SyncAsync(new SyncRequest(), CancellationToken.None);
switch (result)
{
case AppleStoreKitServiceSyncResult.Success:
// 동기화 성공. 미완료 트랜잭션 조회를 진행합니다.
Debug.Log("구매 동기화 성공");
break;
case AppleStoreKitServiceSyncResult.UserCanceled:
// 사용자가 Apple ID 재인증을 취소한 경우
Debug.Log("사용자가 동기화를 취소했습니다.");
break;
case AppleStoreKitServiceSyncResult.UnknownOutcome:
Debug.LogWarning("알 수 없는 동기화 결과입니다.");
break;
case AppleStoreKitServiceSyncResult.Failure failure:
Debug.LogError($"동기화 실패: {failure}");
break;
default:
Debug.LogWarning($"처리되지 않은 결과: {result.GetType().Name}");
break;
}
응답 상태
반환 객체 AppleStoreKitServiceSyncResult는 아래 케이스 중 하나로 분기됩니다.
| 응답 케이스 | 설명 | 앱 클라이언트 대응 |
|---|---|---|
Success | 구매 동기화 성공 | 미완료 트랜잭션 조회 진행 |
UserCanceled | 사용자가 Apple ID 재인증을 취소한 경우 | 취소 안내 UI 표시 |
UnknownOutcome | 알 수 없는 결과 | 재시도 또는 오류 안내 |
Failure | 공통 Failure입니다. 공통 오류 처리를 참조하세요. | 공통 오류 처리 기준에 따라 처리 |
1.2. 미완료 트랜잭션 조회
GetUnfinishedTransactionsAsync
GetUnfinishedTransactionsAsync()를 호출하면 아직 FinishTransactionAsync()로 완료 처리하지 않은 트랜잭션 목록을 조회합니다. 결제는 완료되었으나 상품을 지급하지 못한 건을 찾을 때 사용합니다.
var unfinishedResult = await applePlugin.GetUnfinishedTransactionsAsync(
new GetUnfinishedTransactionsRequest(), CancellationToken.None);
switch (unfinishedResult)
{
case { } success when success is AppleStoreKitServiceGetUnfinishedTransactionsResult.Success s:
foreach (AppleTransaction tx in s.Data.Transactions)
{
// 미완료 트랜잭션별로 영수증 검증 및 상품 지급 처리
Debug.Log($"미완료 거래 — 상품: {tx.ProductId}, 거래 ID: {tx.Id}");
string receipt = tx.JwsRepresentation; // 서버 검증용 JWS 영수증
}
break;
default:
Debug.LogWarning($"미완료 트랜잭션 조회 실패: {unfinishedResult.GetType().Name}");
break;
}
1.3. 선택: 현재 자격(Entitlements) 조회
GetCurrentEntitlementsAsync
GetCurrentEntitlementsAsync()를 호출하면 사용자가 현재 보유 중인 활성 구매 항목(비소모성 상품, 활성 구독 등)의 트랜잭션 목록을 조회합니다. 구독 상태 확인이나 비소모성 상품 복원에 활용합니다.
var entitlementsResult = await applePlugin.GetCurrentEntitlementsAsync(
new GetCurrentEntitlementsRequest(), CancellationToken.None);
switch (entitlementsResult)
{
case { } success when success is AppleStoreKitServiceGetCurrentEntitlementsResult.Success s:
foreach (AppleTransaction tx in s.Data.Transactions)
{
Debug.Log($"활성 자격 — 상품: {tx.ProductId}, 유형: {tx.ProductType}");
}
break;
default:
Debug.LogWarning($"자격 조회 실패: {entitlementsResult.GetType().Name}");
break;
}
2. 영수증 검증 및 상품 지급
재조회로 획득한 미지급 구매의 영수증(JwsRepresentation)은 신규 구매와 동일하게 3단계. 상품 구매의 결제 결과 데이터 저장 요청 AxylReceipt로 전달하되, RequestType을 2(구매 복원)로 설정합니다.
다시 획득한 영수증을 가지고 아래 과정을 다시 진행합니다.
- 영수증 정보를 준비해 앱 서버에 전달합니다. 앱 서버가 보내는 영수증 검증 요청의
requestType도2(구매 복원)로 설정합니다. - 앱 서버가 Hive Axyl Server API로 영수증을 검증합니다.
- 검증이 완료되면 상품을 지급하고 거래 완료 처리를 합니다.