# 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="https://1837360763-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fot0z57AnnXZ02C5qyePV%2Fuploads%2FrewUDEKtBdLoX8gRJs9L%2Fimage.png?alt=media&#x26;token=86dc5393-c873-48cb-af6a-1488ff07b0dd" 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>

{% hint style="warning" %}
**원스토어 대한민국 상품에 한하여 지원되는 API입니다.**&#x20;

* 글로벌 상품의 경우, 2026.04 업데이트 예정입니다.
  {% endhint %}

* **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          | 전체 상품  | 관리형 상품 + 월정액 상품 |
