인앱 결제
앱인토스 유니티 SDK를 사용하면 C# 코드만으로 인앱 결제를 연동할 수 있어요.
Unity SDK의 인앱 결제 API는 앱인토스 WebView SDK IAP 객체와 같은 주문·상품 지급 완료 모델을 사용해요. 함수명만 Unity C# 환경에 맞게 IAP.getPendingOrders() 대신 AIT.IAPGetPendingOrders()처럼 제공돼요.
결제 플로우
정상 플로우
IAPGetProductItemList()— 상품 목록 조회IAPCreateOneTimePurchaseOrder()— 구매 주문 생성ProcessProductGrant콜백에서 상품 지급 또는 권한 부여 후true반환- SDK가 자동으로
IAPCompleteProductGrant를 호출해서 주문을 완료 처리해요
참고하세요
결제 성공 후 30초 내에 ProcessProductGrant 콜백이 호출되지 않거나 해당 콜백의 결과가 true가 아닌 경우, {appName}에 문제가 생겼어요. 환불을 신청해 주세요 페이지가 노출될 수 있어요.
복구 플로우
앱 크래시나 네트워크 끊김 등으로 ProcessProductGrant 콜백이 호출되지 않은 경우에 사용해요.
IAPGetPendingOrders()— 미결 주문 조회- 각 주문에 대해 상품 지급 또는 권한 부여 수행
IAPCompleteProductGrant()— 상품 지급 완료 처리
API
| API | 설명 |
|---|---|
AIT.IAPGetProductItemList() | 등록된 상품 목록을 조회해요 |
AIT.IAPCreateOneTimePurchaseOrder() | 일회성 구매 주문을 생성해요 |
AIT.IAPGetPendingOrders() | 결제는 완료됐지만 상품이 아직 지급되지 않은 미결 주문을 조회해요 |
AIT.IAPGetCompletedOrRefundedOrders() | 상품 지급이 완료됐거나 환불된 주문을 조회해요 |
AIT.IAPCompleteProductGrant() | 미결 주문의 상품 지급 또는 권한 부여 완료를 처리해요 |
주문 조회 API 구분
AIT.IAPGetPendingOrders()와 AIT.IAPGetCompletedOrRefundedOrders()는 용도가 달라요.
| API | 언제 사용하나요 |
|---|---|
AIT.IAPGetPendingOrders() | 결제는 완료됐지만 상품이 아직 지급되지 않은 주문을 복구할 때 사용해요. 앱 시작 시 미결 주문을 확인하고, 상품 지급 후 AIT.IAPCompleteProductGrant()를 호출해 주세요. |
AIT.IAPGetCompletedOrRefundedOrders() | 상품 지급까지 완료된 주문이나 환불된 주문 이력을 확인할 때 사용해요. 미결 주문은 이 결과에 포함되지 않아요. |
결제 완료 이벤트를 받지 못했거나 주문 상태를 서버에서 확인해야 하는 경우에는 주문 상태 조회 API를 함께 사용할 수 있어요. 이 API를 사용하려면 토스 로그인 연동이 필요해요.
샘플 코드
상품 목록 조회
csharp
using AppsInToss;
using UnityEngine;
public class IAPExample : MonoBehaviour
{
async void Start()
{
try
{
var result = await AIT.IAPGetProductItemList();
foreach (var product in result.Products)
{
Debug.Log($"{product.DisplayName} ({product.Sku}) - {product.DisplayAmount}");
}
}
catch (AITException ex)
{
Debug.LogError($"상품 조회 실패: {ex.ErrorCode} - {ex.Message}");
}
}
}구매 주문 생성
csharp
using System;
using AppsInToss;
using UnityEngine;
public class IAPPurchase : MonoBehaviour
{
private Action _purchaseDisposer;
public void Purchase(string sku)
{
_purchaseDisposer?.Invoke();
var options = new IapCreateOneTimePurchaseOrderOptionsOptions
{
Sku = sku,
ProcessProductGrant = (data) =>
{
// 상품 지급 또는 권한 부여 처리
Debug.Log($"상품 지급: {data}");
bool grantSuccess = GrantProduct(data);
// true를 반환하면 SDK가 자동으로 IAPCompleteProductGrant를 호출해요
return grantSuccess;
}
};
_purchaseDisposer = AIT.IAPCreateOneTimePurchaseOrder(
options: options,
onEvent: (result) =>
{
Debug.Log($"구매 완료: orderId={result.Data?.OrderId}, amount={result.Data?.DisplayAmount}");
},
onError: (error) =>
{
Debug.LogError($"구매 실패: {error.ErrorCode} - {error.Message}");
}
);
}
private bool GrantProduct(object data)
{
// 실제 게임 내 상품 지급 로직을 구현해요
return true;
}
private void OnDestroy()
{
_purchaseDisposer?.Invoke();
}
}미결 주문 복구
앱 크래시 등으로 상품 지급이 완료되지 않은 주문을 복구하는 예제예요.
csharp
using AppsInToss;
using UnityEngine;
public class IAPRecovery : MonoBehaviour
{
async void Start()
{
await RecoverPendingOrders();
}
private async System.Threading.Tasks.Task RecoverPendingOrders()
{
try
{
// 미결 주문 조회
var result = await AIT.IAPGetPendingOrders();
if (result.Orders == null || result.Orders.Length == 0)
{
Debug.Log("복구할 주문이 없어요");
return;
}
foreach (var order in result.Orders)
{
// 상품 지급
GrantProduct(order.Sku);
// 지급 완료 처리
var args = new IAPCompleteProductGrantArgs_0
{
Params = new IAPCompleteProductGrantArgs_0Params
{
OrderId = order.OrderId
}
};
bool success = await AIT.IAPCompleteProductGrant(args);
Debug.Log($"주문 {order.OrderId} 복구 {(success ? "성공" : "실패")}");
}
}
catch (AITException ex)
{
Debug.LogError($"주문 복구 실패: {ex.ErrorCode} - {ex.Message}");
}
}
private void GrantProduct(string sku)
{
// SKU에 따른 상품 지급 로직
Debug.Log($"상품 지급: {sku}");
}
}완료·환불 주문 조회
이미 상품 지급이 완료된 주문이나 환불된 주문 이력을 확인하는 예제예요. 미결 주문 복구에는 사용하지 않아요.
csharp
using AppsInToss;
using UnityEngine;
public class IAPOrderHistory : MonoBehaviour
{
async void Start()
{
await FetchCompletedOrRefundedOrders();
}
private async System.Threading.Tasks.Task FetchCompletedOrRefundedOrders()
{
try
{
var result = await AIT.IAPGetCompletedOrRefundedOrders();
if (result.Orders == null || result.Orders.Length == 0)
{
Debug.Log("조회된 완료·환불 주문이 없어요");
return;
}
foreach (var order in result.Orders)
{
Debug.Log($"주문 상태: orderId={order.OrderId}, sku={order.Sku}, status={order.Status}");
}
}
catch (AITException ex)
{
Debug.LogError($"완료·환불 주문 조회 실패: {ex.ErrorCode} - {ex.Message}");
}
}
}주의사항
TIP
- 인앱 결제 상품은 반드시
ProcessProductGrant콜백에서 상품 지급 또는 권한 부여를 처리하고true를 반환해야 해요. false를 반환하거나 콜백이 호출되지 않으면 주문이 미결 상태로 남아요.- 앱 시작 시
IAPGetPendingOrders()로 미결 주문을 확인하는 것을 권장해요. - 실제 결제는 샌드박스 앱에서 테스트할 수 없어요. 토스 앱에서 QR 코드를 통해 테스트해 주세요.

