--- title: "결제" slug: "game-gamepot3-purchase" updated: 2026-09-17T09:07:47Z published: 2026-09-17T09:07:47Z canonical: "guide.ncloud-docs.com/game-gamepot3-purchase" stale: true --- > ## Documentation Index > Fetch the complete documentation index at: https://guide.ncloud-docs.com/llms.txt > Use this file to discover all available pages before exploring further. # 결제 Classic/VPC 환경에서 이용 가능합니다. ## 결제 GAMEPOT SDK에서 제공하는 인앱 결제 기능을 사용하여 게임 내 아이템을 판매할 수 있습니다. 결제 전에 [스토어별 환경 설정](/docs/game-gamepot3-google-play-store)에 해당 스토어에 맞도록 설정해야 합니다. 또한, **대시보드** > **결제** > **인앱**에 아이템이 추가되지 않았을 경우 'ProductID not found' 라는 오류가 발생됩니다. ### Android Android에서 상품 정보를 조회하고 결제를 요청하며 미처리 결제를 복구하는 방법을 안내합니다. #### (AOS) 인앱 정보 가져오기 결제하실 때에 화면에 결제 정보와 현지 통화 정보를 표시해야 합니다. 아래 함수를 통해서 현재 결제 통화나 이름 등을 가져올 수 있습니다. 만일 정상적으로 가져오지 못하는 경우 콘솔 세팅을 확인해 주십시오. Kotlin: ``` import com.nbase.sdk.Store NBase.getProductItems() {products, e -> if (e != null) { Log.e("NBase", e.message) } else { // 인앱 아이템 정보 Log.e("NBase", products) } } ``` Java: ``` NBase nBase = NBase.INSTANCE; nBase.getProductItems((products, e) -> { if (e != null) { Log.e("NBase", "getProductItems fail: " + e.getMessage()); } else { if (products != null) { Log.e("NBase", "getProductItems success: " + products.toString()); } } return null; }); ``` 다음 표는 상품 정보 조회 콜백으로 전달되는 값을 설명합니다. - **Callback** | Key | Type | Description | | --- | --- | --- | | id | String | productId | | productName | String | 제품 이름 | | title | String | 제품 타이틀 | | price | Float | 제품 가격 | | localizedPrice | Float | 현지화된 가격 | | productId | String | 제품 고유 ID | | productType | String | 제품 타입 | | productDescription | String | 제품 설명 | | currency | String | 통화 단위 | #### (AOS) 결제 요청 가져온 인앱 정보에 productId로 결제를 요청할 수 있습니다. Kotlin: ``` import com.nbase.sdk.Store NBase.purchase(activity, Store.GOOGLE, productId, 메타데이터, options) { purchase, e -> if (e != null) { Log.e("NBase", e.message) } else { Log.e("NBase", purchase) } } ``` Java: ``` import com.nbase.sdk.Store; NBase nBase = NBase.INSTANCE; nBase.purchase(activity, storeId, productId, 메타데이터, options, (purchase, e) -> { if (e != null) { Log.e("NBase", "purchase fail: " + e.getMessage()); } else { if (purchase != null) { Log.e("NBase", "purchase success: " + purchase.toString()); } } return null; }); ``` 다음 표는 결제 요청 시 전달하는 매개변수를 설명합니다. - **Parameter** | Key | Type | Description | Required | | --- | --- | --- | --- | | activity | Activity | 현재 액티비티 | O | | storeId | Store | 스토어 ID (아래 표 참고) | O | | productId | String | productId (대시보드 → 결제 → 인앱 아이템) | O | | 메타데이터 | String | 메타데이터 | X | | options | String | 결제 옵션 기능 | X | 다음 표는 `storeId`에 전달할 수 있는 스토어 값을 설명합니다. | Key | Description | | --- | --- | | Store.GOOGLE | 구글 스토어 | | Store.ONE | 원 스토어 | | Store.GALAXY | 갤럭시 스토어 | | Store.AMAZON | 아마존 스토어 | | Store.HUAWEI | 화웨이 스토어 | 다음 표는 결제 요청 콜백으로 전달되는 값을 설명합니다. - **Callback** | Key | Type | Description | | --- | --- | --- | | id | String | ID | | orderId | String | 주문 ID | | storeId | String | 스토어 ID | | productId | String | 상품 ID | | billingKey | String | 결제 키 | | signature | String | 서명 | | originalJson | String | 원본 JSON | | developerPayload | String | 개발자 페이로드 | | packageName | String | 패키지명 | | isAcknowledged | bool | 확인 여부 | | purchaseState | String | 구매 상태 | | purchaseTime | String | 구매 시간 | | quantity | String | 수량 | | recurringState | String | 반복 결제 상태 | | currency | String | 통화 | | country | String | 국가 | | paymentId | String | 결제 ID | | price | Float | 가격 | | iapVersion | String | 인앱 결제 버전 | | playerId | String | 플레이어 ID | | serverId | String | 서버 ID | | level | Int | 레벨 | | userdata | String | 사용자 데이터 | | 메타데이터 | String | 메타데이터 | | options | String | 옵션 | | authCode | String | 인증 코드 | #### (AOS) 미처리 결제 복구 결제는 완료됐지만 게임에 결과가 전달되지 않은 결제 건을 복구합니다. `restorePurchase`로 복구를 요청하면 복구된 결제 정보가 `setPurchaseRestoreListener`로 등록한 리스너에 1건씩 전달됩니다. 참고 nbasesdk 3.0.98 이상에서 사용할 수 있습니다. - **복구 리스너 등록** 로그인이 완료되면 SDK가 바로 복구를 시작하므로 로그인을 호출하기 전에 한 번 등록해 주십시오. 로그인 시와 앱 복귀 시 SDK가 자동으로 수행하는 복구 결과도 같은 리스너로 전달되며, 같은 결제 건의 성공은 한 번만 전달됩니다. Kotlin: ``` NBase.setPurchaseRestoreListener { purchase, e -> if (e != null) { // 복구 실패 Log.e("NBase", "restore Failed: ${e.message}") } else { // 복구 성공: orderId, productId 로 아이템을 지급합니다. Log.d("NBase", "restore Success: ${purchase?.get("orderId")} / ${purchase?.get("productId")}") } } ``` Java: ``` NBase nBase = NBase.INSTANCE; nBase.setPurchaseRestoreListener((purchase, e) -> { if (e != null) { // 복구 실패 Log.e("NBase", "restore Failed: " + e.getMessage()); } else if (purchase != null) { // 복구 성공: orderId, productId 로 아이템을 지급합니다. Log.d("NBase", "restore Success: " + purchase.get("orderId") + " / " + purchase.get("productId")); } return null; }); ``` 다음 표는 복구 리스너 콜백으로 전달되는 값을 설명합니다. - **Callback** | Key | Type | Description | | --- | --- | --- | | purchase | Map? | 복구된 결제 정보. [결제 요청](/docs/game-gamepot3-purchase#AOS%EA%B2%B0%EC%A0%9C%EC%9A%94%EC%B2%AD)의 Callback 과 같은 키로 전달 | | e | CoreException? | 복구 실패 시 오류 정보. 성공 시 `null` | - **복구 요청** 초기화와 로그인 이후에 호출해 주십시오. Kotlin: ``` NBase.restorePurchase(activity) { success, e -> if (e != null) { Log.e("NBase", "restorePurchase Failed: ${e.message}") } else { Log.d("NBase", "restorePurchase Success") } } ``` Java: ``` NBase nBase = NBase.INSTANCE; nBase.restorePurchase(activity, (success, e) -> { if (e != null) { Log.e("NBase", "restorePurchase Failed: " + e.getMessage()); } else { Log.d("NBase", "restorePurchase Success"); } return null; }); ``` 다음 표는 복구 요청 시 전달하는 매개변수를 설명합니다. - **Parameter** | Key | Type | Description | Required | | --- | --- | --- | --- | | activity | Activity | 현재 액티비티 | O | | storeId | Store | 복구할 스토어. 생략 시 초기화에 설정한 스토어 | X | 다음 표는 복구 요청 콜백으로 전달되는 값을 설명합니다. - **Callback** | Key | Type | Description | | --- | --- | --- | | success | Boolean | 복구 요청 시작 여부. 복구된 결제 정보는 리스너로 전달됩니다. | | e | CoreException? | 요청 실패 시 오류 정보. 성공 시 `null` | - **복구 리스너 해제** 등록한 리스너를 해제합니다. Kotlin: ``` NBase.setPurchaseRestoreListener(null) ``` Java: ``` NBase.INSTANCE.setPurchaseRestoreListener(null); ``` ### iOS iOS에서 상품 정보를 조회하고 결제를 요청하는 방법을 안내합니다. #### (iOS) 인앱 정보 가져오기 결제하실 때에 화면에 결제 정보와 현지 통화 정보를 표시해야 합니다. 아래 함수를 통해서 현재 결제 통화나 이름 등을 가져올 수 있습니다. 만일 정상적으로 가져오지 못하는 경우 콘솔 세팅을 확인해 주십시오. Swift: ``` let products = NBase.getProductItems() ``` Objective-C: ``` [NBaseBridge.shared getProductItems:^(NSString * _Nullable result) { NSLog(@"getProductItems result: %@", result); }]; ``` 다음 표는 상품 정보 조회 콜백으로 전달되는 값을 설명합니다. - **Callback** | Key | Type | Description | | --- | --- | --- | | id | String | productId | | productId | String | 제품 고유 ID | | productName | String | 제품 이름 | | productType | String | 제품 타입 | | currency | String | 통화 | | price | Float64 | 제품 가격 | | localizedPrice | String | 현지화된 가격 | | productDescription | String | 제품 설명 | #### (iOS) 결제 요청 가져온 인앱 정보에 productId로 결제를 요청할 수 있습니다. Swift: ``` NBase.purchase(productId: productId, 메타데이터: 메타데이터, options: options) { result in switch result { case .success(let data): NBase.showToast(message: data?.encodeToJson() ?? "") case .failure(let error): NBase.showToast(message: error.errorDescription ?? "") } } ``` Objective-C: ``` [NBaseBridge.shared purchase:productId 메타데이터:메타데이터 options:options :^(NSDictionary * _Nullable result, NSError * _Nullable error) { if (error) { NSLog(@"purchase Error: %@", error.localizedDescription); } else { NSLog(@"purchase succeeded with result: %@", result); } }]; ``` 다음 표는 결제 요청 시 전달하는 매개변수를 설명합니다. - **Parameter** | Key | Type | Description | Required | | --- | --- | --- | --- | | productId | String | 상품 ID (대시보드 > 결제 > 인앱 아이템) | O | | 메타데이터 | String | 메타데이터 | X | | options | String | 결제 옵션 기능 | X | 다음 표는 결제 요청 콜백으로 전달되는 값을 설명합니다. - **Callback** | Key | Type | Description | | --- | --- | --- | | orderId | String | 주문 ID | | receipt | String | 영수증 | | signature | String | 서명 | | productId | String | 상품 ID | | storeId | String | 스토어 ID | | country | String | 국가 | | quantity | Int | 수량 | | paymentId | String | 결제 ID | | currency | String | 통화 | | serverId | String | 서버 ID | | playerId | String | 플레이어 ID | | userdata | String | 사용자 데이터 | | 메타데이터 | String | 메타데이터 | | options | String | 결제 옵션 | | authCode | String | 인증 코드 | | level | Int | 레벨 | | price | Float64 | 가격 | ### Unity Unity에서 상품 정보를 조회하고 결제를 요청하며 Android 미처리 결제를 복구하는 방법을 안내합니다. #### (Unity) 인앱 정보 가져오기 결제하실 때에 화면에 결제 정보와 현지 통화 정보를 표시해야 합니다. 아래 함수를 통해서 현재 결제 통화나 이름 등을 가져올 수 있습니다. 만일 정상적으로 가져오지 못하는 경우 콘솔 세팅을 확인해 주십시오. ``` NBaseSDK.NBase.getProductItems((products, error) => { if (products != null && products.Count > 0) { // 제품 목록을 순회합니다. foreach (var product in products) { // 각 제품의 정보를 토스트 메시지로 보여줍니다. // 예시에서는 product.ToString()을 호출하고 있지만, // 실제로는 product의 구체적인 속성(예: 이름, 가격 등)을 표시할 수 있습니다. NBaseSDK.NBase.showToast(product.ToString()); } } else { // 제품 목록이 비어있는 경우, 사용자에게 알립니다. NBaseSDK.NBase.showToast("제품 목록이 비어있습니다."); } }); ``` 다음 표는 상품 정보 조회 콜백으로 전달되는 값을 설명합니다. - **Callback** | Key | Type | Description | | --- | --- | --- | | Products[].id | string | productId | | Products[].title | string | 제품 타이틀 | | Products[].productId | string | 제품 고유 ID | | Products[].productType | string | 제품 타입 | | Products[].productName | string | 제품 이름 | | Products[].productDescription | string | 제품 설명 | | Products[].currency | string | 통화 단위 | | Products[].price | float | 제품 가격 | #### (Unity) 결제 요청 가져온 인앱 정보에 productId 로 결제를 요청할 수 있습니다. ``` NBaseSDK.NBase.purchase(Store.google.ToString(), productId, 메타데이터, options, (purchase, error) => { if (error != null) { Debug.Log(error.Message.ToString()); return; } // 결제 성공 }); ``` 다음 표는 결제 요청 시 전달하는 매개변수를 설명합니다. - **Parameter** | Key | Type | Description | Required | | --- | --- | --- | --- | | storeId | string | 스토어 ID (아래 표 참고) | O | | productId | string | productId (대시보드 → 결제 → 인앱 아이템) | O | | 메타데이터 | string | 메타데이터 | X | | options | string | 결제 옵션 기능 | X | 다음 표는 `storeId`에 전달할 수 있는 스토어 값을 설명합니다. | Key | Description | | --- | --- | | Store.google.ToString() | 구글 스토어 | | Store.one.ToString() | 원 스토어 | | Store.galaxy.ToString() | 갤럭시 스토어 | | Store.amazon.ToString() | 아마존 스토어 | | Store.huawei.ToString() | 화웨이 스토어 | 다음 표는 결제 요청 콜백으로 전달되는 값을 설명합니다. - **Callback** | Key | Type | Description | | --- | --- | --- | | storeId | string | 상점의 고유 ID | | paymentId | string | 결제 ID | | iapVersion | string | 인앱 결제 버전 | | productId | string | productId | | billingKey | string | 청구 키 | | signature | string | 서명 | | originalJson | string | 원본 JSON | | orderId | string | 주문 ID | | developerPayload | string | 개발자 페이로드 | | packageName | string | 패키지 이름 | | isAcknowledged | bool | 확인 여부 | | purchaseState | int | 구매 상태 | | purchaseTime | long | 구매 시간 | | price | float | 가격 | | quantity | int | 수량 | | currency | string | 통화 단위 | #### (Unity) 미처리 결제 복구 결제는 완료됐지만 게임에 결과가 전달되지 않은 결제 건을 복구합니다. `restorePurchase`로 복구를 요청하면 복구된 결제 정보가 `setPurchaseRestoreListener`로 등록한 리스너에 1건씩 전달됩니다. 참고 nbasesdk-unity-plugin 3.0.18 이상의 Android에서 사용할 수 있습니다. - **복구 리스너 등록** 로그인이 완료되면 SDK가 바로 복구를 시작하므로 로그인을 호출하기 전에 한 번 등록해 주십시오. 로그인 시와 앱 복귀 시 SDK가 자동으로 수행하는 복구 결과도 같은 리스너로 전달되며, 같은 결제 건의 성공은 한 번만 전달됩니다. ``` NBaseSDK.NBase.setPurchaseRestoreListener((purchase, error) => { if (error != null) { // 복구 실패 Debug.Log("restore Failed: " + error.Message); return; } // 복구 성공: orderId, productId 로 아이템을 지급합니다. Debug.Log("restore Success: " + purchase.orderId + " / " + purchase.productId); }); ``` 다음 표는 복구 리스너 콜백으로 전달되는 값을 설명합니다. - **Callback** | Key | Type | Description | | --- | --- | --- | | purchase | Purchase | 복구된 결제 정보. [결제 요청](/docs/game-gamepot3-purchase#Unity%EA%B2%B0%EC%A0%9C%EC%9A%94%EC%B2%AD)의 Callback과 같은 형태 | | error | Error | 복구 실패 시 오류 정보. 성공 시 `null` | - **복구 요청** 초기화와 로그인 이후에 호출해 주십시오. ``` NBaseSDK.NBase.restorePurchase((success, error) => { if (error != null) { Debug.Log("restorePurchase Failed: " + error.Message); return; } Debug.Log("restorePurchase Success"); }); ``` 다음 표는 복구 요청 콜백으로 전달되는 값을 설명합니다. - **Callback** | Key | Type | Description | | --- | --- | --- | | success | bool | 복구 요청 시작 여부. 복구된 결제 정보는 리스너로 전달 | | error | Error | 요청 실패 시 오류 정보. 성공 시 `null` | - **복구 리스너 해제** 등록한 리스너를 해제합니다. ``` NBaseSDK.NBase.removePurchaseRestoreListener(); ``` ## 문제 해결 결제 연동 중 자주 발생하는 오류와 확인 사항을 안내합니다. **Q. ProductID not found 오류가 발생합니다.** A. **대시보드** > **결제** > **인앱**에 해당 상품 ID가 등록되어 있는지 확인해 주십시오. **Q. 결제가 진행되지 않습니다.** A. [스토어별 환경 설정](/docs/game-gamepot3-google-play-store)을 참고하여 해당 스토어에 맞는 설정이 완료되었는지 확인해 주십시오. **Q. (Android) java.lang.NoClassDefFoundError: Failed resolution of: Lcom/android/billingclient/api/BillingClient;** A. 아래 코드를 추가해 주십시오. ``` ``` **Q. (iOS) 인앱 정보를 가져올 수 없습니다.** A. Apple Connect에 등록된 인앱 상품 정보와 앱 환경(Production/Sandbox)이 일치하는지 확인해 주십시오.