# 06. 원스토어 인앱결제 서버 API (API V7)

## **개요**  <a href="#id-06.-api-apiv7" id="id-06.-api-apiv7"></a>

원스토어 인앱결제 서버 API란 원스토어에서 결제된 인앱 상품의 데이터를 조회하거나 결제 상태를 변경하기 위한 Open API를 말합니다.

해당 API를 사용하기 위해서는 OAuth 인증이 필요합니다.

### **HOST URL**  <a href="#id-06.-api-apiv7-hosturl" id="id-06.-api-apiv7-hosturl"></a>

본 문서에서 사용되는 Host Domain은 아래와 같습니다.

| 원스토어 환경 | Host Domain                                                      |
| ------- | ---------------------------------------------------------------- |
| 검증(개발)  | <mark style="color:blue;"><https://sbpp.onestore.net></mark>     |
| 상용      | <mark style="color:blue;"><https://iap-apis.onestore.net></mark> |

{% hint style="info" %}
본 문서에서 사용하는 도메인은 모든 국가에서 공용으로 사용할 수 있는 도메인입니다.&#x20;

대한민국에서만 서비스 중인 기존 앱/게임의 도메인은 과거 도메인을 그대로 사용하시면 됩니다.&#x20;

(apis.onestore.co.kr)
{% endhint %}

### 마켓 구분 코드&#x20;

* Request header에 마켓 구분 코드 (x-market-code)가 추가 되었습니다.&#x20;
* 원스토어 글로벌 플랫폼에 서비스 되는 경우 마켓 구분 코드를 헤더에 추가하여 요청해야 합니다.&#x20;
* 마켓 구분 코드가 없는 경우에는 원스토어(기본 값)로 호출됩니다.&#x20;

| 마켓 구분 코드 | 서비스 대상      |
| -------- | ----------- |
| MKT\_ONE | 원스토어 (기본 값) |
| MKT\_GLB | 원스토어 글로벌    |

{% hint style="danger" %}
마켓 구분 코드에 따라 서버 API 응답으로 제공되는 시간의 기준이 다릅니다.&#x20;

MKT\_ONE : UTC+09

MKT\_GLB : UTC+00 &#x20;
{% endhint %}

## **원스토어 OAuth**  <a href="#id-06.-api-apiv7-oauth" id="id-06.-api-apiv7-oauth"></a>

### **OAuth 개요** <a href="#id-06.-api-apiv7-oauth" id="id-06.-api-apiv7-oauth"></a>

원스토어 서버 Open API를 연동하기 위해서는 OAuth 인증이 필요합니다.

* 원스토어 OAuth v2의 이해
  * AccessToken은 원스토어의 Server Open API를 통하여 발급받을 수 있는 값으로 원스토어에서 제공하는 Server Open API 호출시 인증값으로 사용됩니다.
  * AccessToken은 기본적으로 3600초의 유효기간이 있으며, 유효기간이 만료 되거나 600초 미만으로 남은 경우에 getAccessToken()을 호출하면 새로운 AccessToken이 발급됩니다.
    * 기존의 AccessToken도 유효기간이 끝날 때까지는 사용이 가능합니다.
    * 다수의 AccessToken이 발행되는 방식이므로 개발사의 서비스 인스턴스 별로 서로 다른 AccessToken을 취득하고 사용할 수 있는 형태가 됩니다. \ <br>
* 일반적인 연동 흐름은 다음과 같습니다.<br>

  <figure><img src="/files/m0kpOVp7juDApcT0g9Ay" alt=""><figcaption></figcaption></figure>
* AccessToken을 얻는 과정(1번)은 API 호출 시 인증 오류가 발생했을 때 호출하면 됩니다. <br>

원스토어의 인앱결제 서버 API의 호출을 위해서는 Authorization Bearer 스킴을 사용하며 호출 샘플은 아래와 같습니다.

```
GET /v7/apps/com.onestore.game.goindol/purchases/inapp/products/product01/SANDBOXT000120004476 HTTP/1.1
Host: sbpp.onestore.net
Authorization: Bearer 680b3621-1234-1234-1234-8adfaef561b4
```

Authorization 헤더에는 위 예제와 같이 Bearer + 공백 + AccessToken이 대소문자 구분하여 정확히 입력되어야 합니다.\
Bearer의 값은 getAccessToken()을 호출하여 발급받은 AccessToken 값입니다.

잘못된 예&#x20;

```
Authorization: 680b3621-1234-1234-1234-8adfaef561b4
Authorization: bearer 680b3621-1234-1234-1234-8adfaef561b4
Authorization: Bearer <680b3621-1234-1234-1234-8adfaef561b4>
Authorization:Bearer680b3621-1234-1234-1234-8adfaef561b4
```

<br>

### **OAuth API 상세** <a href="#id-06.-api-apiv7-oauthapi" id="id-06.-api-apiv7-oauthapi"></a>

**client\_id 및 client\_secret 확인**

Client\_id와 Client\_secret 값은 "라이선스 관리" 메뉴에서 확인할 수 있습니다.

### **AccessToken 발급**

* **URI :** /v7/oauth/token

* **Method:** POST

* **Request Parameter:** Form 형식

  | Parameter Name | Description                        | Example                                      |
  | -------------- | ---------------------------------- | -------------------------------------------- |
  | client\_id     | 개발자센터에서 앱 등록 시 발급된 Client id 값     | 0000042301                                   |
  | client\_secret | 개발자센터에서 앱 등록 시 발급된 client secret 값 | vxIMAGcVz3DAx20uDBr/IDWNJAPNHFl7YruF4uxB6BI= |
  | grant\_type    | 고정값                                | client\_credentials                          |

* **Request Header** :&#x20;

  | Parameter Name | Description                                                             | Example                                         |
  | -------------- | ----------------------------------------------------------------------- | ----------------------------------------------- |
  | Content-Type   | Http 요청시 Content Type으로 반드시 application/x-www-form-urlencoded 로 설정되어야 함 | Content-Type: application/x-www-form-urlencoded |
  | x-market-code  | 마켓 구분 코드                                                                | x-market-code: MKT\_GLB                         |

* **Example**&#x20;

  ```
  POST /v7/oauth/token HTTP/1.1
  Host: apis.onestore.com
  Content-Type: application/x-www-form-urlencoded;charset=UTF-8
  x-market-code: MKT_GLB

  grant_type=client_credentials&client_id=com.onestore.game.goindol&client_secret=vxIMAGcVz3DAx20uDBr/IDWNJAPNHFl7YruF4uxB6BI=
  ```

* **Response Body** : JSON 형식

  | Element Name  | Data Type | Data Size | Description                |
  | ------------- | --------- | --------- | -------------------------- |
  | client\_id    | String    | 255       | OAuth 인증 client\_id        |
  | access\_token | String    | 36        | AccessToken                |
  | token\_type   | String    | 6         | bearer 방식만 제공              |
  | expires\_in   | Integer   | 10        | token 만료기한, 단위 : 초(second) |
  | scope         | String    | 1024      | token 사용 범위                |

* **Example :**&#x20;

  ```json
  {
      "client_id":"0000000001",
      "access_token":"680b3621-1234-1234-1234-8adfaef561b4",
      "token_type":"bearer",
      "expires_in":3010,
      "scope":"DEFAULT"
  }
  ```

* **발급 예시** :&#x20;

  <pre class="language-bash" data-overflow="wrap"><code class="lang-bash">curl -v -X POST https://sbpp.onestore.net/v7/oauth/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -H "x-market-code: MKT_GLB" \
  -d "grant_type=client_credentials" \
  -d "client_id=0000000001" \
  -d "client_secret=vxIMAGcVz3DAx20uDBr/IDWNJAPNHFl7YruF4uxB6BI="
  > POST /v7/oauth/token HTTP/1.1
  > Host: sbpp.onestore.net
  > User-Agent: curl/7.43.0
  > Accept: */*
  > Content-Type: application/x-www-form-urlencoded;charset=UTF-8
  > Content-Length: 35
  >
  * upload completely sent off: 35 out of 35 bytes
  &#x3C; HTTP/1.1 200 200
  &#x3C; Date: Wed, 02 May 2018 02:52:42 GMT
  &#x3C; Server: Apache
  &#x3C; Connection: close
  &#x3C; Transfer-Encoding: chunked
  &#x3C; Content-Type: application/json;charset=UTF-8
  &#x3C;
  * Closing connection 0
  {"client_id":"0000000001","access_token":"680b3621-1234-1234-1234-8adfaef561b4","token_type":"bearer","expires_in":3600,"scope":"DEFAULT"}
  </code></pre>

검증(개발) 환경과 상용환경의 AccessToken은 독립적으로 관리되므로, 환경 별로 AccessToken을 분리하여 관리하셔야 합니다.

## **서버 API 상세**  <a href="#id-06.-api-apiv7-api" id="id-06.-api-apiv7-api"></a>

{% hint style="info" %}
2025년 3월 20일 개발자센터 개편의 영향으로 서버 API 요청 시 이용되던 packageName은 clientId로 변경되었습니다.&#x20;

* 3월 20일 이전 등록된 앱의 경우 클라이언트 ID 와 패키지명이 동일하므로, 변경에 대한 영향도가 없습니다.&#x20;
* 3월 20일 이후 등록된 앱의 경우 클라이언트 ID 가 PID와 동일하므로 참고 부탁 드립니다.&#x20;
  {% endhint %}

### getPurchaseDetails (구매상품 상세조회) <a href="#id-06.-api-apiv7-getpurchasedetails" id="id-06.-api-apiv7-getpurchasedetails"></a>

* **Desc :** 구매한 원스토어 관리형 상품의 상세정보를 조회합니다. 구매완료 시 전달받은 원스토어 purchaseToken(구매 토큰)을 이용하여 조회하여야 합니다. 월정액 상품의 purchaseToken으로 조회 시, 조회 실패(NoSuchData) 응답이 전달됩니다.
* **URI :** /v7/apps/{clientId}/purchases/inapp/products/{productId}/{purchaseToken}
* **Method :** GET
* **Request Parameter :** Path Variable 형식
  * String clientId : API를 호출하는 앱의 클라이언트 ID (Data Size : 128)
  * String productId : 상품 ID (Data Size : 150)
  * String purchaseToken : 구매 토큰 (Data Size : 20)
* **Request Header:**&#x20;

  | Parameter Name | Data Type | Required | Description                             |
  | -------------- | --------- | -------- | --------------------------------------- |
  | Authorization  | String    | true     | Access Token API를 통해 발급받은 access\_token |
  | Content-Type   | String    | true     | application/json                        |
  | x-market-code  | String    | false    | 마켓 구분 코드                                |
* **Example**&#x20;

  ```java
  Request.setHeader("Authorization", "Bearer 680b3621-1234-1234-1234-8adfaef561b4");
  Request.setHeader("Content-Type", "application/json");
  Request.setHeader("x-market-code", "MKT_GLB");
  ```
* **Request Body :** 없음
* **Response Body** : JSON 형식

  | Element Name     | Data Type | Data Size | Description                                    |
  | ---------------- | --------- | --------- | ---------------------------------------------- |
  | consumptionState | Integer   | 1         | 구매한 상품의 소비상태 (0: 미소비, 1: 소비)                   |
  | developerPayload | String    | 200       | 개발사가 제공한 결제 고유 식별자                             |
  | purchaseState    | Integer   | 1         | 구매상태 ( 0: 구매완료, 1: 취소완료)                       |
  | purchaseTime     | Long      | 13        | 구매시간 (ms)                                      |
  | purchaseId       | String    | 20        | 구매 ID                                          |
  | acknowledgeState | Integer   | 1         | 구매확인 상태( 0: Not Acknowledged, 1: Acknowledged) |
  | quantity         | Integer   | 2         | 구매 수량                                          |
* **Example:**

  ```
  HTTP/1.1 200 OK
  Content-type: application/json;charset=UTF-8
  {
      "consumptionState": 0,
      "developerPayload": "developerPayload",
      "purchaseState": 0,
      "purchaseTime": 1345678900000,
      "purchaseId": "17070421461015116878",
      "acknowledgeState": 0,
  	"quantity": 2
  }
  ```

### getRecurringPurchaseDetails (월정액 상품 구매 상세조회)  <a href="#id-06.-api-apiv7-getrecurringpurchasedetails" id="id-06.-api-apiv7-getrecurringpurchasedetails"></a>

* **Desc :** 구매한 원스토어 월정액 상품의 자동결제 상태와 마지막 구매상태의 상세정보를 조회합니다. 구매완료 시 전달받은 원스토어 purchaseToken(구매 토큰)을 이용하여 조회하여야 합니다. 관리형 상품의 purchaseToken으로 조회 시, 조회 실패(NoSuchData) 응답이 전달됩니다.
* **URI :** /v7/apps/{clientId}/purchases/auto/products/{productId}/{purchaseToken}
* **Method :** GET
* **Request Parameter :** Path Variable 형식
  * String clientId : API를 호출하는 앱의 클라이언트 ID (Data Size : 128)
  * String productId : 상품 ID (Data Size : 150)
  * String purchaseToken : 구매 토큰 (Data Size : 20)
* **Request Header:**&#x20;

  | Parameter Name | Data Type | Required | Description                             |
  | -------------- | --------- | -------- | --------------------------------------- |
  | Authorization  | String    | true     | Access Token API를 통해 발급받은 access\_token |
  | Content-Type   | String    | true     | application/json                        |
  | x-market-code  | String    | false    | 마켓 구분 코드                                |
* **Example**&#x20;

  ```java
  Request.setHeader("Authorization", "Bearer 680b3621-1234-1234-1234-8adfaef561b4");
  Request.setHeader("Content-Type", "application/json");
  Request.setHeader("x-market-code", "MKT_GLB");
  ```
* **Request Body :** 없음
* **Response Body** : JSON 형식

  | Element Name      | Data Type | Data Size | Description                                            |
  | ----------------- | --------- | --------- | ------------------------------------------------------ |
  | startTime         | Long      | 13        | 구매한 상품의 이용시작시간(ms)                                     |
  | expiryTime        | Long      | 13        | 구매한 상품의 이용종료시간(ms)                                     |
  | nextPaymentTime   | Long      | 13        | 다음 자동결제시간                                              |
  | autoRenewing      | boolean   | -         | 이용종료시간(expiryTime)가 지난 후 자동결제 여부                       |
  | cancelReason      | Integer   | 1         | 해지사유 (0 : 고객요청에 의한 해지, 1 : 기타 시스템 처리로 인한 해지 )          |
  | cancelledTime     | Long      | 13        | 해지시간(ms)                                               |
  | acknowledgeState  | Integer   | 1         | 월정액 상품의 구매확인 상태( 0: Not Acknowledged, 1: Acknowledged) |
  | lastPurchaseId    | String    | 20        | 마지막에 자동결제된 구매ID                                        |
  | lastPurchaseState | Integer   | 1         | 마지막에 자동결제된 구매상태 (0 : 구매완료, 1 : 취소완료)                   |
* **Example :**&#x20;

  ```json
  HTTP/1.1 200 OK
  Content-type: application/json;charset=UTF-8
  {
      "startTime": 1345678900000,
      "expiryTime": 1345678999999,
      "nextPaymentTime": 1345688000000,
      "autoRenewing": true,
      "cancelReason": 1,
      "cancelledTime": 1345679000000,
      "acknowledgeState": 0,
      "lastPurchaseId":"15081718460701027851",
      "lastPurchaseState": 0
  }
  ```

  고객이 월정액 상품에 대하여 컨텐츠 사용 권한이 있는지 아래의 조건으로 판단이 가능합니다.

  * 현재시간이 expiryTime(구매한 상품의 이용종료시간)보다 작거나 같고, lastPurchaseState(마지막에 자동결제된 구매상태)가 0(구매완료) 상태인경우\
    Ex) expiryTime >= 현재시간 AND lastPurchaseState == 0

### acknowledgePurchase (구매상품 확인)  <a href="#id-06.-api-apiv7-acknowledgepurchase" id="id-06.-api-apiv7-acknowledgepurchase"></a>

* **Desc :** 구매한 관리형 또는 월정액 상품을 구매확인 상태로 변경한다.
* **URI :** /v7/apps/{clientId}/purchases/all/products/{productId}/{purchaseToken}/acknowledge
* **Method :** POST
* **Request Parameter :** Path Variable 형식
  * String clientId : API를 호출하는 앱의 클라이언트 ID (Data Size : 128)
  * String productId : 상품 ID (Data Size : 150)
  * String purchaseToken : 구매 토큰 (Data Size : 20)
* **Request Header:**&#x20;

  | Parameter Name | Data Type | Required | Description                             |
  | -------------- | --------- | -------- | --------------------------------------- |
  | Authorization  | String    | true     | Access Token API를 통해 발급받은 access\_token |
  | Content-Type   | String    | true     | application/json                        |
  | x-market-code  | String    | false    | 마켓 구분 코드                                |
* **Example**&#x20;

  ```java
  Request.setHeader("Authorization", "Bearer 680b3621-1234-1234-1234-8adfaef561b4");
  Request.setHeader("Content-Type", "application/json");
  Request.setHeader("x-market-code", "MKT_GLB");
  ```
* **Request Body** : JSON 형식

  | Element Name     | Data Type | Required | Description |
  | ---------------- | --------- | -------- | ----------- |
  | developerPayload | String    | false    | <p><br></p> |
* **Example :**

  ```json
  {
      "developerPayload": "your payload"
  }
  ```
* **Response Body :** JSON 형식

  API 처리 성공 시 처리완료를 보다 직관적으로 판단할 수 있도록 아래 형식의 응답를 리턴합니다. 단, API 처리 실패 시에는 표준오류응답을 리턴합니다.

  | Element Name | Data Type | Data Size | Description |
  | ------------ | --------- | --------- | ----------- |
  | code         | String    | -         | 응답 코드       |
  | message      | String    | -         | 응답 메시지      |
  | result       | Object    | -         | <p><br></p> |
* **Example :**&#x20;

  ```json
  HTTP/1.1 200 OK
  Content-type: application/json;charset=UTF-8
  {
      "result" : {
          "code" : "Success",
          "message" : "Request has been completed successfully."
      }
  }
  ```

원스토어는 3일 이내에 acknowledgePurchase API가 호출되지 않은 구매 건을 자동으로 취소합니다.

이에 따라 개발사는 반드시 해당 API를 호출해야 하며, SDK API 또는 서버 API를 통해 처리할 수 있습니다.

단, consumePurchase API가 호출된 구매 건은 acknowledge가 되었다고 판단하고 구매 취소를 하지 않습니다.

### consumePurchase (구매상품 소비) <a href="#id-06.-api-apiv7-consumepurchase" id="id-06.-api-apiv7-consumepurchase"></a>

* **Desc :** 구매한 관리형 인앱 상품을 소비 상태로 변경한다.
* **URI :** /v7/apps/{clientId}/purchases/inapp/products/{productId}/{purchaseToken}/consume
* **Method :** POST
* **Request Parameter :** Path Variable 형식
  * String clientId : API를 호출하는 앱의 클라이언트 ID (Data Size : 128)
  * String productId : 상품 ID (Data Size : 150)
  * String purchaseToken : 구매 토큰 (Data Size : 20)
* **Request Header:**&#x20;

  | Parameter Name | Data Type | Required | Description                             |
  | -------------- | --------- | -------- | --------------------------------------- |
  | Authorization  | String    | true     | Access Token API를 통해 발급받은 access\_token |
  | Content-Type   | String    | true     | application/json                        |
  | x-market-code  | String    | false    | 마켓 구분 코드                                |
* **Example**&#x20;

  ```java
  Request.setHeader("Authorization", "Bearer 680b3621-1234-1234-1234-8adfaef561b4");
  Request.setHeader("Content-Type", "application/json");
  Request.setHeader("x-market-code", "MKT_GLB");
  ```
* **Request Body** : JSON 형식

  | Element Name     | Data Type | Required | Description |
  | ---------------- | --------- | -------- | ----------- |
  | developerPayload | String    | false    | <p><br></p> |
* **Example :**

  ```json
  {
      "developerPayload": "your payload"
  }
  ```
* **Response Body :** JSON 형식

  API 처리 성공 시 처리완료를 보다 직관적으로 판단할 수 있도록 아래 형식의 응답를 리턴합니다. 단, API 처리 실패 시에는 표준오류응답을 리턴합니다.

  | Element Name | Data Type | Data Size | Description |
  | ------------ | --------- | --------- | ----------- |
  | code         | String    | -         | 응답 코드       |
  | message      | String    | -         | 응답 메시지      |
  | result       | Object    | -         | <p><br></p> |
* **Example :**&#x20;

  ```json
  HTTP/1.1 200 OK
  Content-type: application/json;charset=UTF-8
  {
      "result" : {
          "code" : "Success",
          "message" : "Request has been completed successfully."
      }
  }
  ```

### cancelRecurringPurchase (자동결제 해지요청)  <a href="#id-06.-api-apiv7-cancelrecurringpurchase" id="id-06.-api-apiv7-cancelrecurringpurchase"></a>

* **Desc :** 월정액 상품의 자동결제 해지를 요청한다. 구독형 상품의 purchaseToken이용 시, 조회 실패(NoSuchData) 응답이 전달됩니다.
* **URI :** /v7/apps/{clientId}/purchases/auto/products/{productId}/{purchaseToken}/cancel
* **Method :** POST
* **Request Parameter :** Path Variable 형식
  * String clientId : API를 호출하는 앱의 클라이언트 ID (Data Size : 128)
  * String productId : 상품 ID (Data Size : 150)
  * String purchaseToken : 구매 토큰 (Data Size : 20)
* **Request Header:**&#x20;

  | Parameter Name | Data Type | Required | Description                             |
  | -------------- | --------- | -------- | --------------------------------------- |
  | Authorization  | String    | true     | Access Token API를 통해 발급받은 access\_token |
  | Content-Type   | String    | true     | application/json                        |
  | x-market-code  | String    | false    | 마켓 구분 코드                                |
* **Example**&#x20;

  ```java
  Request.setHeader("Authorization", "Bearer 680b3621-1234-1234-1234-8adfaef561b4");
  Request.setHeader("Content-Type", "application/json");
  Request.setHeader("x-market-code", "MKT_GLB");
  ```
* **Request Body :** 없음
* **Response Body :** JSON 형식

  API 처리 성공 시 처리완료를 보다 직관적으로 판단할 수 있도록 아래 형식의 응답를 리턴합니다. 단, API 처리 실패 시에는 표준오류응답을 리턴합니다.

  | Element Name | Data Type | Data Size | Description |
  | ------------ | --------- | --------- | ----------- |
  | code         | String    | -         | 응답 코드       |
  | message      | String    | -         | 응답 메시지      |
  | result       | Object    | -         | <p><br></p> |
* **Example :**&#x20;

  ```json
  HTTP/1.1 200 OK
  Content-type: application/json;charset=UTF-8
  {
      "result" : {
          "code" : "Success",
          "message" : "Request has been completed successfully."
      }
  }
  ```

### reactiveRecurringPurchase (자동결제 해지 취소요청)  <a href="#id-06.-api-apiv7-reactiverecurringpurchase" id="id-06.-api-apiv7-reactiverecurringpurchase"></a>

* **Desc :** 월정액 상품의 자동결제 해지요청을 취소한다. 구독형 상품의 purchaseToken이용 시, 조회 실패(NoSuchData) 응답이 전달됩니다.
* **URI :** /v7/apps/{clientId}/purchases/auto/products/{productId}/{purchaseToken}/reactivate
* **Method :** POST
* **Request Parameter :** Path Variable 형식
  * String clientId : API를 호출하는 앱의 클라이언트 ID (Data Size : 128)
  * String productId : 상품 ID (Data Size : 150)
  * String purchaseToken : 구매 토큰 (Data Size : 20)
* **Request Header:**&#x20;

  | Parameter Name | Data Type | Required | Description                             |
  | -------------- | --------- | -------- | --------------------------------------- |
  | Authorization  | String    | true     | Access Token API를 통해 발급받은 access\_token |
  | Content-Type   | String    | true     | application/json                        |
  | x-market-code  | String    | false    | 마켓 구분 코드                                |
* **Example**&#x20;

  ```java
  Request.setHeader("Authorization", "Bearer 680b3621-1234-1234-1234-8adfaef561b4");
  Request.setHeader("Content-Type", "application/json");
  Request.setHeader("x-market-code", "MKT_GLB");
  ```
* **Request Body :** 없음
* **Response Body :** JSON 형식

  API 처리 성공 시 처리완료를 보다 직관적으로 판단할 수 있도록 아래 형식의 응답를 리턴합니다. 단, API 처리 실패 시에는 표준오류응답을 리턴합니다.

  | Element Name | Data Type | Data Size | Description |
  | ------------ | --------- | --------- | ----------- |
  | code         | String    | -         | 응답 코드       |
  | message      | String    | -         | 응답 메시지      |
  | result       | Object    | -         | <p><br></p> |
* **Example :**&#x20;

  ```json
  HTTP/1.1 200 OK
  Content-type: application/json;charset=UTF-8
  {
      "result" : {
          "code" : "Success",
          "message" : "Request has been completed successfully."
      }
  }
  ```

### getVoidedPurchases (구매취소내역 조회)  <a href="#id-06.-api-apiv7-getvoidedpurchases" id="id-06.-api-apiv7-getvoidedpurchases"></a>

* **Desc :** 구매취소내역을 조회한다.
* **URI :** /v7/apps/{clientId}/voided-purchases
* **Method :** GET
* **Request Parameter :** Path Variable 형식
  * String clientId : API를 호출하는 앱의 클라이언트 ID (Data Size : 128)
* **Request Parameter (Optional) :** Query String 형식<br>
  * String continuationKey : 구매취소 건이 많을 경우 원스토어 서버에서 이 값을 반환합니다. \
    응답에 continuationKey가 있을 경우, getVoidedPurchases를 다시 호출하면서 continuationKey를 전달하면 추가 구매취소 내역을 전달받을 수 있습니다. (Data Size : 41)
  * String startTime : 구매취소일시 검색 시작시간 (milliseconds). \
    현재시간기준 과거 1개월까지만 설정가능하며 startTime 단독으로 사용할 경우 endTime은 startTime기준 미래 1개월로 설정됩니다. (Data Size : 13)
  * String endTime :  구매취소일시 검색 종료시간 (milliseconds). \
    현재시간보다 클 수 없으며 endTime 단독으로 사용할 경우 startTime은 endTime기준 과거 1개월로 설정됩니다. (Data Size : 13)
  * unsigned integer maxResults : 최대조회건수 default 100 (Data Size : 3)
* **Request Header:**&#x20;

  | Parameter Name | Data Type | Required | Description                             |
  | -------------- | --------- | -------- | --------------------------------------- |
  | Authorization  | String    | true     | Access Token API를 통해 발급받은 access\_token |
  | Content-Type   | String    | true     | application/json                        |
  | x-market-code  | String    | false    | 마켓 구분 코드                                |
* **Example**&#x20;

  ```java
  Request.setHeader("Authorization", "Bearer 680b3621-1234-1234-1234-8adfaef561b4");
  Request.setHeader("Content-Type", "application/json");
  Request.setHeader("x-market-code", "MKT_GLB");
  ```
* **Request Body :** 없음
* **Response Body :**

  | Element Name       | Data Type   | Data Size | Description                                                                         |
  | ------------------ | ----------- | --------- | ----------------------------------------------------------------------------------- |
  | continuationKey    | String      | 41        | 구매취소 건이 최대조회건수보다 많을 경우 반환. 이후 요청시 전달받은 continuationKey 를 셋팅하여 호출하면 이후 내역을 조회 할 수 있음 |
  | voidedPurchaseList | <p><br></p> | -         | <p><br></p>                                                                         |
  | purchaseId         | String      | 20        | 구매 ID                                                                               |
  | purchaseTime       | Long        | 13        | 구매시간(ms)                                                                            |
  | voidedTime         | Long        | 13        | 구매취소시간(ms)                                                                          |
  | purchaseToken      | String      | 20        | 구매 토큰                                                                               |
  | marketCode         | String      | -         | 마켓 구분 코드                                                                            |
* **Example :**&#x20;

  ```json
  HTTP/1.1 200 OK
  Content-type: application/json;charset=UTF-8
  {
      "continuationKey": "continuationKey",
      "voidedPurchaseList ": [
          {
              "purchaseId": "19062709124410111299",
              "purchaseTime": 1345678900000,
              "voidedTime": 1345688900000,
              "purchaseToken": "19062709124410111299",
              "marketCode": "MKT_ONE"
          },
          {
              "purchaseId": "19062709124410111300",
              "purchaseTime": 1345679900000,
              "voidedTime": 1345878900000,
              "purchaseToken": "19062709124410111299",
              "marketCode": "MKT_ONE"
          }
      ]
  }
  ```

### getUnconfirmedPurchases (구매확인 미처리 내역 조회) <a href="#getunconfirmedpurchases" id="getunconfirmedpurchases"></a>

* **Desc :** 구매확인(consume 또는 acknowledge) 처리되지 않은 구매목록을 반환합니다.
* **URI :** /v7/apps/{clientId}/unconfirmed-purchases
* **Method :** GET
* **Request Parameter :** Path Variable 형식
  * String clientId : API를 호출하는 앱의 클라이언트 ID (Data Size : 128)
* **Request Parameter (Optional) :** Query String 형식

  | Parameter Name  | Data Type | Required | Description                                                                                                                                     |
  | --------------- | --------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
  | continuationKey | String    | false    | <p>구매 목록이 최대 조회 건수보다 많을 경우 반환  </p><ul><li>이후 요청시 전달받은 continuationKey 를 셋팅하여 호출하면 이후 내역을 조회 할 수 있습니다.</li></ul>                                |
  | startTime       | Long      | false    | <p>조회하고자 하는 구매 목록 검색 시작일(milliseconds)</p><ul><li>현재시간 기준 과거 1개월까지만 설정가능하며 startTime 단독으로 사용할 경우 endTime은 startTime 기준 미래 1개월로 설정합니다.</li></ul> |
  | endTime         | Long      | false    | <p>조회하고자 하는 구매 목록 검색 종료일(milliseconds)</p><ul><li>현재시간보다 클 수 없으며 endTime 단독으로 사용할 경우 startTime은 endTime 기준 과거 1개월로 설정합니다.</li></ul>             |
  | maxResults      | Integer   | false    | <p>최대조회건수 (default : 100)</p><ul><li>1 \~ 100</li></ul>                                                                                         |
* **Request Header:**&#x20;

  | Parameter Name | Data Type | Required | Description                             |
  | -------------- | --------- | -------- | --------------------------------------- |
  | Authorization  | String    | true     | Access Token API를 통해 발급받은 access\_token |
  | Content-Type   | String    | true     | application/json                        |
  | x-market-code  | String    | false    | 마켓 구분 코드                                |
* **Example**&#x20;

  ```java
  Request.setHeader("Authorization", "Bearer 680b3512-1253-5642-1263-8adjbf651nb");
  Request.setHeader("Content-Type", "application/json");
  ```
* **Request Body : N/A**
* **Response Body**: <br>

  | <mark style="color:$info;">**Element Name**</mark> | <mark style="color:$info;">**Data Type**</mark> | <mark style="color:$info;">**Data Size**</mark> | <mark style="color:$info;">**Description**</mark>                                                                |
  | -------------------------------------------------- | ----------------------------------------------- | ----------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- |
  | continuationKey                                    | String                                          | <p><br></p>                                     | <p>구매 목록이 최대 조회 건수보다 많을 경우 반환  </p><ul><li>이후 요청시 전달받은 continuationKey 를 셋팅하여 호출하면 이후 내역을 조회 할 수 있습니다.</li></ul> |
  | unconfirmedPurchaseList \[                         | <p><br></p>                                     | <p><br></p>                                     | <p><br></p>                                                                                                      |
  | {                                                  | <p><br></p>                                     | <p><br></p>                                     | <p><br></p>                                                                                                      |
  | type                                               | String                                          | -                                               | 상품 타입                                                                                                            |
  | orderId                                            | String                                          | 40                                              | 결제 ID                                                                                                            |
  | productId                                          | <p>String<br></p>                               | 150                                             | 개발자센터에 상품 등록 시 지정한 인앱상품 ID                                                                                       |
  | purchaseToken                                      | String                                          | 20                                              | 구매 토큰                                                                                                            |
  | purchaseId                                         | String                                          | 20                                              | 구매 ID                                                                                                            |
  | purchaseTime                                       | Long                                            | 13                                              | 구매시간 (ms)                                                                                                        |
  | purchaseState                                      | Integer                                         | 1                                               | 구매상태 (0: 구매완료, 1: 취소완료)                                                                                          |
  | developerPayload                                   | String                                          | 200                                             | 구매건을 식별하기 위해 개발사에서 관리하는 식별자                                                                                      |
  | quantity                                           | Integer                                         | <p><br></p>                                     | 구매한 상품의 수량                                                                                                       |
  | marketCode                                         | String                                          | -                                               | <p>마켓 구분 코드</p><ul><li>MKT\_ONE: 국내 구매 건</li><li>MKT\_GLB: 해외 구매 건</li></ul>                                     |
  | }                                                  | <p><br></p>                                     | <p><br></p>                                     | <p><br></p>                                                                                                      |
  | ]                                                  | <p><br></p>                                     | <p><br></p>                                     | <p><br></p>                                                                                                      |
* **Example**&#x20;

  ```java
  HTTP/1.1 200 OK
  Content-type: application/json;charset=UTF-8
  {
  	"continuationKey": "continuationKey",
  	"unconfirmedPurchaseList ": [
  		{
              "type": "inapp",
              "orderId": "01239349082349823489342",
              "productId": "다이아100_20170818000000",
   			"purchaseToken": "19062709124410111299",
  			"purchaseId": "19062709124410111299",
  			"purchaseTime": 1345678900000,
   			"purchaseState": 0,
              "developerPayload": "E23DEFB029F84F4383ECB0E53B46B6A2",
              "quantity": 1,
  			"marketCode": "MKT_ONE"
  		},
   		{
              "type": "inapp",
              "orderId": "01239349082349823489343",
              "productId": "루비300_20170818000000",
   			"purchaseToken": "19062709124410111299",
  			"purchaseId": "19062709124410111300",
  			"purchaseTime": 1345679900000,
   			"purchaseState": 0,
              "developerPayload": "T_RPAY_27_201707120110880",
              "quantity": 2,
  			"marketCode": "MKT_ONE"
  		}
  	]
  }
  ```

### getSubscriptionDetail (구독 상세 조회)  <a href="#id-06.-api-apiv7-getsubscriptiondetail" id="id-06.-api-apiv7-getsubscriptiondetail"></a>

* **Desc :** 구독 상세 내역을 조회한다.
* **URI :** /v7/apps/{clientId}/purchases/subscription/products/{productId}/{purchaseToken}
* **Method :** GET
* **Request Parameter :** Path Variable 형식
  * String clientId : API를 호출하는 앱의 클라이언트 ID (Data Size : 128)
  * String productId : 상품 ID (Data Size : 150)
  * String purchaseToken : 구매 토큰 (Data Size : 20)
* **Request Header:**&#x20;

  | Parameter Name | Data Type | Required | Description                             |
  | -------------- | --------- | -------- | --------------------------------------- |
  | Authorization  | String    | true     | Access Token API를 통해 발급받은 access\_token |
  | Content-Type   | String    | true     | application/json                        |
  | x-market-code  | String    | false    | 마켓 구분 코드                                |
* **Example**&#x20;

  <pre class="language-java"><code class="lang-java"><strong>Request.setHeader("Authorization", "Bearer 680b3621-1234-1234-1234-8adfaef561b4");
  </strong>Request.setHeader("Content-Type", "application/json");
  Request.setHeader("x-market-code", "MKT_GLB");
  </code></pre>
* **Request Body :** 없음
* **Response Body :**

  <table data-header-hidden><thead><tr><th width="205"></th><th></th><th></th><th></th></tr></thead><tbody><tr><td>Element Name</td><td>Data Type</td><td>Data Size</td><td>Description</td></tr><tr><td>acknowledgementState</td><td>Integer</td><td>1</td><td>구매확인 상태( 0: Not Acknowledged, 1: Acknowledged)</td></tr><tr><td>developerPayload</td><td>String</td><td>200</td><td>개발사가 제공한 결제 고유 식별자</td></tr><tr><td>autoRenewing</td><td>boolean</td><td>-</td><td><p>다음결제 갱신여부<br></p><ul><li>구독해지예약,해지,만료 : false</li><li>나머지 : true</li></ul></td></tr><tr><td>paymentState</td><td>Integer</td><td>1</td><td><p>구독결제 수신여부</p><ul><li>null: 만료 상태</li><li>0: 결제가 완료 되지 않은 상태</li><li>1: 결제요청 후 결제완료가 된 상태</li><li>2: 무료기간으로 처리된 상태</li><li>3: 상품 업/다운그레이드 시 DEFERRED옵션으로 처리된 상태</li></ul></td></tr><tr><td>priceAmount</td><td>String</td><td>-</td><td>구매금액</td></tr><tr><td>priceAmountMicros</td><td>Long</td><td>-</td><td>구매금액 * 100만</td></tr><tr><td>nextPriceAmount</td><td>String</td><td>-</td><td>다음구매금액</td></tr><tr><td>nextPriceAmountMicros</td><td>Long</td><td>-</td><td>다음구매금액 * 100만</td></tr><tr><td>nextPaymentTimeMillis</td><td>Long</td><td>13</td><td>다음구매시간(ms)</td></tr><tr><td>priceCurrencyCode</td><td>String</td><td>-</td><td>통화코드</td></tr><tr><td>countryCode</td><td>String</td><td>-</td><td>국가코드(KR 고정)</td></tr><tr><td>startTimeMillis</td><td>Long</td><td>13</td><td>구독 시작(첫 결제)시간(ms)</td></tr><tr><td>expiryTimeMillis</td><td>Long</td><td>13</td><td>구독 만료시간(ms)</td></tr><tr><td>pauseStartTimeMillis</td><td>Long</td><td>13</td><td>일시정지 시작일시(ms)-일시정지예약/일시정지 시에만 존재</td></tr><tr><td>pauseEndTimeMillis</td><td>Long</td><td>13</td><td>일시정지 시작일시(ms)-일시정지예약/일시정지 시에만 존재</td></tr><tr><td>autoResumeTimeMillis</td><td>Long</td><td>13</td><td><p>일시정지 후 재구독 시간</p><ul><li>정상 구독 중: null</li><li>일시정지 예약/확정/일시정지중: 다음결제일 + 일시정지일자 </li></ul></td></tr><tr><td>linkedPurchaseToken</td><td>String</td><td>20</td><td>구독상품 변경 시 이전 purchaseToken, 변경한 적이 없으면 null</td></tr><tr><td>lastPurchaseId</td><td>String</td><td>20</td><td>마지막 구매ID</td></tr><tr><td>cancelledTimeMillis<br></td><td>Long</td><td>13</td><td>구독 해지시간(ms)</td></tr><tr><td>cancelReason</td><td>Integer</td><td>1</td><td><p>구독 해지사유 </p><ul><li>0 : 고객요청</li><li>1 : 기타</li></ul></td></tr><tr><td>promotionPrice</td><td>Object</td><td>-</td><td>프로모션 금액 정보</td></tr><tr><td>promotionPrice.promotionPrice</td><td>String</td><td>-</td><td>프로모션 금액</td></tr><tr><td>promotionPrice.promotionPriceMicros</td><td>Long</td><td>-</td><td>프로모션 금액 정보 * 100만</td></tr><tr><td>promotionPrice.promotionPeriod</td><td>Int</td><td>-</td><td>프로모션 적용 회차</td></tr><tr><td>priceChange</td><td>Object</td><td>-</td><td>가격변동정보</td></tr><tr><td>priceChange.seq</td><td>Integer</td><td>-</td><td>가격변동 시퀀스 </td></tr><tr><td>priceChange.previousPrice</td><td>String</td><td>-</td><td>이전 가격 </td></tr><tr><td>priceChange.previousPriceMicros</td><td>Long</td><td>-</td><td>이전 가격 * 100만</td></tr><tr><td>priceChange.newPrice</td><td>String</td><td>-</td><td>신규 가격</td></tr><tr><td>priceChange.newPriceMicros</td><td>Long</td><td>-</td><td>신규 가격 * 100만</td></tr><tr><td>priceChange.applyTimeMillis</td><td>Long</td><td>13</td><td>적용일자(ms)</td></tr><tr><td>priceChange.agreement</td><td>Boolean</td><td>-</td><td>가격 변동 동의 여부</td></tr><tr><td>priceChange.agreementDueDateTimeMillis</td><td>Long</td><td>13</td><td><p>가격 변동 동의 만료 시간(ms)</p><p>(정책 부연 설명)</p><p>Value = 가격변경일 +7+30일<br>사용자는 동의만료일 이후 첫 자동결제 시점까지 동의가능함.</p></td></tr></tbody></table>
* **Example :**&#x20;

  ```json
  HTTP/1.1 200 OK
  Content-type: application/json;charset=UTF-8
  {
      "acknowledgementState":1,
      "autoRenewing":true,
      "paymentState":1,
      "lastPurchaseId": "20202394820938409234"
      "linkedPurchaseToken":null,
      "priceAmount":"100",
      "priceAmountMicros":100000000,
      "nextPriceAmount":"150",
      "nextPriceAmountMicros":150000000,
      "nextPaymentTimeMillis": 1623337199000,
      "priceCurrencyCode":"KRW",
      "countryCode":"KR",
      "startTimeMillis":1623337199000,
      "expiryTimeMillis":1625929199000,
      "pauseStartTimeMillis":1625929199000,
      "pauseEndTimeMillis":1625929199000,
      "autoResumeTimeMillis":1625878800000,
      "cancelledTimeMillis":1625929199000,
      "cancelReason":0,
      "promotionPrice":{
          "promotionPrice":"100",
          "promotionPriceMicros":100000000,
          "promotionPeriod":30
      },
      "priceChange":{
          "seq": 1,
          "previousPrice":"100",
          "previousPriceMicros":100000000,
          "newPrice":"500",
          "newPriceMicros":500000000,
          "applyTimeMillis":1625670000000,
          "agreement":false,
          "agreementDueDateTimeMillis": 1345678920000
      }
  }
  ```

### cancelSubscription (구독결제 해지요청)  <a href="#id-06.-api-apiv7-cancelsubscription" id="id-06.-api-apiv7-cancelsubscription"></a>

* **Desc :** 구독형 상품의 자동결제 해지를 요청한다. 단, 요청 시점에 구독상태가 일시중지, 결제유예, 계정보류일 경우 즉시 해지를 요청한다.
* **URI :** /v7/apps/{clientId}/purchases/subscription/products/{productId}/{purchaseToken}/cancel
* **Method :** POST
* **Request Parameter :** Path Variable 형식
  * String clientId : API를 호출하는 앱의 클라이언트 ID (Data Size : 128)
  * String productId : 상품 ID (Data Size : 150)
  * String purchaseToken : 구매 토큰 (Data Size : 20)
* **Request Header:**&#x20;

  | Parameter Name | Data Type | Required | Description                             |
  | -------------- | --------- | -------- | --------------------------------------- |
  | Authorization  | String    | true     | Access Token API를 통해 발급받은 access\_token |
  | Content-Type   | String    | true     | application/json                        |
  | x-market-code  | String    | false    | 마켓 구분 코드                                |
* **Example**&#x20;

  ```java
  Request.setHeader("Authorization", "Bearer 680b3621-1234-1234-1234-8adfaef561b4");
  Request.setHeader("Content-Type", "application/json");
  Request.setHeader("x-market-code", "MKT_GLB");
  ```
* **Request Body :** 없음
* **Response Body :** JSON 형식

  API 처리 성공 시 처리완료를 보다 직관적으로 판단할 수 있도록 아래 형식의 응답를 리턴합니다. 단, API 처리 실패 시에는 표준오류응답을 리턴합니다.

  | Element Name | Data Type | Data Size | Description |
  | ------------ | --------- | --------- | ----------- |
  | code         | String    | -         | 응답 코드       |
  | message      | String    | -         | 응답 메시지      |
  | result       | Object    | -         | <p><br></p> |
* **Example :**&#x20;

  ```json
  HTTP/1.1 200 OK
  Content-type: application/json;charset=UTF-8
  {
      "result" : {
          "code" : "Success",
          "message" : "Request has been completed successfully."
      }
  }
  ```

### reactivateSubscription (구독결제 해지 취소요청)  <a href="#id-06.-api-apiv7-reactivatesubscription" id="id-06.-api-apiv7-reactivatesubscription"></a>

* **Desc :** 구독형 상품의 자동결제 해지요청을 취소한다. 단, 즉시해지된 경우 해지요청을 취소할 수 없다.
* **URI :** /v7/apps/{clientId}/purchases/subscription/products/{productId}/{purchaseToken}/reactivate
* **Method :** POST
* **Request Parameter :** Path Variable 형식
  * String clientId : API를 호출하는 앱의 클라이언트 ID (Data Size : 128)
  * String productId : 상품 ID (Data Size : 150)
  * String purchaseToken : 구매 토큰 (Data Size : 20)
* **Request Header:**&#x20;

  | Parameter Name | Data Type | Required | Description                             |
  | -------------- | --------- | -------- | --------------------------------------- |
  | Authorization  | String    | true     | Access Token API를 통해 발급받은 access\_token |
  | Content-Type   | String    | true     | application/json                        |
  | x-market-code  | String    | false    | 마켓 구분 코드                                |
* **Example**&#x20;

  ```java
  Request.setHeader("Authorization", "Bearer 680b3621-1234-1234-1234-8adfaef561b4");
  Request.setHeader("Content-Type", "application/json");
  Request.setHeader("x-market-code", "MKT_GLB");
  ```
* **Request Body :** 없음
* **Response Body :** JSON 형식

  API 처리 성공 시 처리완료를 보다 직관적으로 판단할 수 있도록 아래 형식의 응답를 리턴합니다. 단, API 처리 실패 시에는 표준오류응답을 리턴합니다.

  | Element Name | Data Type | Data Size | Description |
  | ------------ | --------- | --------- | ----------- |
  | code         | String    | -         | 응답 코드       |
  | message      | String    | -         | 응답 메시지      |
  | result       | Object    | -         | <p><br></p> |
* **Example :**&#x20;

  ```json
  HTTP/1.1 200 OK
  Content-type: application/json;charset=UTF-8
  {
      "result" : {
          "code" : "Success",
          "message" : "Request has been completed successfully."
      }
  }
  ```

### deferSubscription (구독결제 연기요청)  <a href="#id-06.-api-apiv7-defersubscription" id="id-06.-api-apiv7-defersubscription"></a>

* **Desc :** 구독형 상품의 다음 결제일을 연기한다.
* **URI :** /v7/apps/{clientId}/purchases/subscription/products/{productId}/{purchaseToken}/defer
* **Method :** POST
* **Request Parameter :** Path Variable 형식
  * String clientId : API를 호출하는 앱의 클라이언트 ID (Data Size : 128)
  * String productId : 상품 ID (Data Size : 150)
  * String purchaseToken : 구매 토큰 (Data Size : 20)
* **Request Header:**&#x20;

  | Parameter Name | Data Type | Required | Description                             |
  | -------------- | --------- | -------- | --------------------------------------- |
  | Authorization  | String    | true     | Access Token API를 통해 발급받은 access\_token |
  | Content-Type   | String    | true     | application/json                        |
  | x-market-code  | String    | false    | 마켓 구분 코드                                |
* **Example**&#x20;

  ```java
  Request.setHeader("Authorization", "Bearer 680b3621-1234-1234-1234-8adfaef561b4");
  Request.setHeader("Content-Type", "application/json");
  Request.setHeader("x-market-code", "MKT_GLB");
  ```
* **Request Body :** JSON 형식

  | Parameter Name | Data Type | Required | Description                                                        |
  | -------------- | --------- | -------- | ------------------------------------------------------------------ |
  | deferPeriod    | Integer   | true     | <p>연기 기간</p><ul><li>상용: 일 단위(1\~365일)</li><li>샌드박스: 분 단위</li></ul> |
* **Example :**&#x20;

  ```json
  Content-type: application/json;charset=UTF-8
  {
  	"deferPeriod" : 3
  }
  ```
* **Response Body :** JSON 형식

  API 처리 성공 시 처리완료를 보다 직관적으로 판단할 수 있도록 아래 형식의 응답를 리턴합니다. 단, API 처리 실패 시에는 표준오류응답을 리턴합니다.

  | Element Name | Data Type | Data Size | Description |
  | ------------ | --------- | --------- | ----------- |
  | code         | String    | -         | 응답 코드       |
  | message      | String    | -         | 응답 메시지      |
  | result       | Object    | -         | <p><br></p> |
* **Example :**&#x20;

  ```json
  HTTP/1.1 200 OK
  Content-type: application/json;charset=UTF-8
  {
      "result" : {
          "code" : "Success",
          "message" : "Request has been completed successfully."
      }
  }
  ```

## 표준응답규격 <a href="#id-06.-api-apiv7" id="id-06.-api-apiv7"></a>

### 표준응답코드 <a href="#id-06.-api-apiv7" id="id-06.-api-apiv7"></a>

| Code                       | Message                                                                               | Description                              | HTTP Status Code                      | 대상 API                                                                                                  |
| -------------------------- | ------------------------------------------------------------------------------------- | ---------------------------------------- | ------------------------------------- | ------------------------------------------------------------------------------------------------------- |
| AccessBlocked              | The request was blocked.                                                              | 요청이 차단되었습니다.                             | 403 - Fobidden                        | 공통                                                                                                      |
| AccessTokenExpired         | Access token has expired.                                                             | Access 토큰이 만료되었습니다.                      | 401 - Unauthorized                    | 공통                                                                                                      |
| BadRequest                 | The request are invalid.                                                              | 잘못된 요청입니다.                               | 400 - Bad Request                     | 공통                                                                                                      |
| DeveloperPayloadNotMatch   | The request developerPayload does not match the value passed in the purchase request. | 구매요청 시 전달된 developerPayload값과 일치하지 않습니다. | 400 - Bad Request                     | <p>acknowledgePurchase<br>consumePurchase</p>                                                           |
| InternalError              | An undefined error has occurred.                                                      | 정의되지 않은 오류가 발생하였습니다.                     | 500 - Internal Server Error           | 공통                                                                                                      |
| InvalidAccessToken         | Access token is invalid.                                                              | Access 토큰이 유효하지 않습니다.                    | 401 - Unauthorized                    | 공통                                                                                                      |
| InvalidAuthorizationHeader | Authorization header is invalid.                                                      | Authorization 헤더의 값이 유효하지 않습니다.          | 400 - Bad Request                     | 공통                                                                                                      |
| InvalidConsumeState        | The purchase consumption status cannot be changed or has already been changed.        | 소비상태 변경이 불가하거나, 이미 변경완료 되었습니다.           | 409 - Conflict                        | consumePurchase                                                                                         |
| InvalidContentType         | The request content-type is invalid.                                                  | 잘못된 Content Type 입니다.                    | 415 - Unsupported Media Type          | 공통                                                                                                      |
| InvalidPurchaseState       | Purchase history does not exist or is not completed.                                  | 구매내역이 존재하지 않거나, 구매완료 상태가 아닙니다.           | 409 - Conflict                        | <p>acknowledgePurchase<br>consumePurchase</p>                                                           |
| InvalidRequest             | Request parameters are invalid. \[ field1, field2, ... ]                              | 입력값이 유효하지 않습니다. \[ field1, field2, ... ] | 400 - Bad Request                     | 공통                                                                                                      |
| MethodNotAllowed           | HTTP method not supported.                                                            | 지원하지 않는 HTTP Method 입니다.                 | 405 - Method Not Allowed              | 공통                                                                                                      |
| NoSuchData                 | The requested data could not be found.                                                | 조회된 결과값이 존재하지 않습니다.                      | 404 - Not Found                       | <p>getPurchaseDetails<br>getRecurringPurchaseDetails</p>                                                |
| RequiredValueNotExist      | Request parameters are required. \[ field1, field2, ... ]                             | 필수값이 존재하지 않습니다. \[ field1, field2, ... ] | 400 - Bad Request                     | 공통                                                                                                      |
| ResourceNotFound           | The requested resource could not be found.                                            | 요청한 자원이 존재하지 않습니다.                       | 404 - Not Found                       | 공통                                                                                                      |
| ServiceMaintenance         | System maintenance is in progress.                                                    | 서비스 점검중입니다.                              | 503 - Service Temporarily Unavailable | 공통                                                                                                      |
| Success                    | The request has been completed successfully.                                          | 정상처리 되었습니다.                              | 200 - Success                         | <p>acknowledgePurchase<br>consumePurchase<br>cancelRecurringPurchase<br>reactivateRecurringPurchase</p> |
| UnauthorizedAccess         | Not authorized to this API.                                                           | 해당 API에 접근권한이 없습니다.                      | 403 - Fobidden                        | 공통                                                                                                      |

### 표준오류 응답규격 <a href="#id-06.-api-apiv7" id="id-06.-api-apiv7"></a>

서버 API에서는 정상적인 응답 외에 오류발생 시, 아래의 Example과 같은 형식의 표준오류응답을 리턴합니다. 아래 내용을 참고하시기 바랍니다.

* **Response Body :** JSON 형식

  | Element Name | Data Type | Data Size | Description |
  | ------------ | --------- | --------- | ----------- |
  | code         | String    | -         | 응답 코드       |
  | message      | String    | -         | 응답 메시지      |
  | error        | Object    | -         | <p><br></p> |
* **Example**

  ```json
  HTTP/1.1 400 Bad Request
  Content-type: application/json;charset=UTF-8
  {
      "error" : {
          "code" : "NoSuchData",
          "message" : "The requested data could not be found."
      }
  }
  ```

## **공통 코드**  <a href="#id-06.-api-apiv7" id="id-06.-api-apiv7"></a>

### **상품타입 코드**  <a href="#id-06.-api-apiv7" id="id-06.-api-apiv7"></a>

| Code         | Name   | Description     |
| ------------ | ------ | --------------- |
| inapp        | 관리형 상품 | 소비성/영구성/기간제 상품  |
| auto         | 월정액 상품 | 월 자동결제 상품       |
| subscription | 구독형 상품 | 구독형(자동결제) 상품    |
| all          | 전체 상품  | 관리형 상품 + 월정액 상품 |


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://onestore-dev.gitbook.io/dev/tools/billing/v21/serverapi.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
