iOS 영수증 검증 (StoreKit 2)
Unity IAP 5.0 (StoreKit 2) 의 서명된 거래(Signed Transaction, JWS)를 검증하는 API입니다.
이 API는 service-api.playnanoo.com 도메인을 사용합니다.
이 API는 Unity IAP 5.0 (iOS 15.0 이상) 의 StoreKit 2 서명된 거래(JWS)를 검증합니다. Unity IAP 4.x (StoreKit 1) 의 Base64 영수증을 사용하는 경우 iOS 영수증 검증 을 참고하세요.
API 정보
- URL:
https://service-api.playnanoo.com/iap/v20260401/unity/ios - Method:
PUT - 인증 필요: 예
요청 파라미터
| 파라미터 | 타입 | 필수 | 설명 |
|---|---|---|---|
| jws_transaction | string | 필수 | 서명된 거래 정보 (JWS). Unity IAP 5.0의 jwsRepresentation |
| product_id | string | 필수 | 결제 상품 아이디 |
| duplicate_allow | string | 선택 | 영수증 중복 검증 허용 여부 (Y/N) |
레거시 v20221001 과 달리 currency, price 를 전달하지 않습니다. 통화·금액은 서버가 JWS payload 에서 직접 추출합니다.
응답 데이터
Res 클래스
| 필드 | 타입 | 설명 |
|---|---|---|
| UserID | string | 사용자 ID |
| PackageName | string | 패키지 이름 |
| OrderID | string | 주문 ID (transactionId) |
| ProductID | string | 상품 ID |
| Quantity | string | 수량 |
| Currency | string | 통화 코드 |
| Price | string | 가격 |
| PurchaseState | string | 검증 결과purchase : 정상결제wait : 처리 진행중cancel : 검증실패 |
Unity C# 구현
BaseResponse 클래스
모든 API 응답의 기본 클래스입니다.
public class BaseResponse
{
public string ErrorCode;
public string Message;
public string WithdrawalKey;
public string BlockKey;
}
필드 설명:
ErrorCode: 에러 코드Message: 에러 메시지WithdrawalKey: 탈퇴 유예 상태인 경우 복구에 필요한 키 (탈퇴 유예 중인 계정만 제공)BlockKey: 차단된 계정인 경우 제공되는 키 (차단된 계정만 제공)
iOS IAP 검증 클래스 (StoreKit 2)
using System;
using System.Collections;
using UnityEngine.Networking;
public class IAPUnityIOSJWS
{
static string path = "https://service-api.playnanoo.com/iap/v20260401/unity/ios";
[Serializable]
public class Req
{
public string jws_transaction; // 서명된 거래 정보 (JWS)
public string product_id; // 결제 상품 아이디
public string duplicate_allow; // 영수증 중복 검증 허용 여부
public IEnumerator Send(string jws_transaction, string product_id, bool duplicate_allow, Action<Res> onSuccess, Action<BaseResponse> onError)
{
if (!string.IsNullOrEmpty(jws_transaction)) this.jws_transaction = jws_transaction;
if (!string.IsNullOrEmpty(product_id)) this.product_id = product_id;
this.duplicate_allow = duplicate_allow ? "Y" : "N";
yield return HttpClient.Send<Req, Res>(
UnityWebRequest.kHttpVerbPUT,
path,
requireToken: true,
body: this,
onSuccess: onSuccess,
onError: onError
);
}
}
[Serializable]
public class Res : BaseResponse
{
public string UserID;
public string PackageName;
public string OrderID;
public string ProductID;
public string Quantity;
public string Currency;
public string Price;
public string PurchaseState;
}
}
사용 예제
public void ValidateIOSIAP(PendingOrder pendingOrder)
{
IAPUnityIOSJWS.Req req = new IAPUnityIOSJWS.Req();
// Unity IAP 5.0 (StoreKit 2) 서명된 거래
string jwsTransaction = pendingOrder.Info.Apple?.jwsRepresentation;
string productId = "com.example.game.gold_100";
StartCoroutine(req.Send(
jws_transaction: jwsTransaction,
product_id: productId,
duplicate_allow: false, // 중복 영수증 허용 안 함
onSuccess: res =>
{
Debug.Log($"IAP 검증 성공");
Debug.Log($"사용자 ID: {res.UserID}");
Debug.Log($"주문 ID: {res.OrderID}");
Debug.Log($"상품 ID: {res.ProductID}");
Debug.Log($"가격: {res.Price} {res.Currency}");
Debug.Log($"상태: {res.PurchaseState}");
},
onError: (error) =>
{
Debug.LogError($"IAP 검증 실패: [{error.ErrorCode}] [{error.Message}]");
}
));
}
jws_transaction 은 Unity IAP 5.0의 pendingOrder.Info.Apple?.jwsRepresentation 에서 얻는 서명된 거래(Signed Transaction) 문자열입니다. Unity IAP 5.0은 iOS 15.0 이상 이 필요합니다.
서버는 JWS 내장 x5c 인증서 체인을 Apple Root CA G3 기준으로 검증(ES256)하며, Apple 서버로의 추가 호출이나 키파일(.p8)이 필요하지 않습니다. Sandbox / Xcode 결제는 테스트 모드로 저장되어 매출에 집계되지 않습니다.
App Store Server Notifications(Version 2)를 등록하면 환불(REFUND) 이벤트를 자동으로 수신합니다. 등록 URL은 https://service-api.playnanoo.com/webhook/apple/{gameId} 이며, 자세한 내용은 콘솔의 API 및 플랫폼 설정 > iOS 를 참고하세요.