# 원스토어 인앱결제 서버 API (API V6)

### **개요**  <a href="#id-api-apiv6" id="id-api-apiv6"></a>

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

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

#### **HOST URL**  <a href="#id-api-apiv6-hosturl" id="id-api-apiv6-hosturl"></a>

본 문서에서 사용되는 {host}의 URL은 아래와 같습니다.

| 원스토어 환경 | Host URL                                            |
| ------- | --------------------------------------------------- |
| 검증(개발)  | [sbpp.onestore.co.kr](https://sbpp.onestore.co.kr/) |
| 상용      | [apis.onestore.co.kr](https://apis.onestore.co.kr/) |

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

#### **OAuth 개요** <a href="#id-api-apiv6-oauth" id="id-api-apiv6-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%2FQ8oVUDBsOVT2m553qTB5%2Fimage.png?alt=media&#x26;token=94c573cc-2318-4455-9d9e-c889aa43fdd0" alt=""><figcaption></figcaption></figure>
* AccessToken을 얻는 과정(1번)은 API 호출 시 인증 오류가 발생했을 때 호출하면 됩니다.&#x20;

  <br>

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

| `GET /v6/apps/com.onestore.game.goindol/purchases/inapp/products/product01/SANDBOXT000120004476 HTTP/1.1Host: sbpp.onestore.co.krAuthorization: Bearer 680b3621-1234-1234-1234-8adfaef561b4` |
| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

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

잘못된 예&#x20;

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

<br>

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

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

client\_id와 client\_secret 값은 원스토어 개발자센터에 등록된 App의 In-App 정보 > '인증 및 라이선스' 버튼을 통하여 확인할 수 있습니다.&#x20;

![](https://1837360763-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fot0z57AnnXZ02C5qyePV%2Fuploads%2FdOiTn5AuKRpYQdOindhY%2Fimage.png?alt=media\&token=c7b1a73d-e40c-4993-a931-bf3ed55e3d9e)

<figure><img src="https://1837360763-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fot0z57AnnXZ02C5qyePV%2Fuploads%2FsBfJKdsE3gbf3Qt4FnKa%2Fimage.png?alt=media&#x26;token=0280c9b4-58f7-4dd0-ad67-cda8f3dc8c7f" alt=""><figcaption></figcaption></figure>

**AccessToken 발급**

* **URI :** https\://{host}/v6/oauth/token
* **Method:** POST, PUT
* **Request Parameter:** Form 형식

  | Parameter Name | Description                        | Example                                      |
  | -------------- | ---------------------------------- | -------------------------------------------- |
  | client\_id     | 일반적으로 packageName과 동일              | com.onestore.game.goindol                    |
  | 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 |
* **Example**&#x20;

  | `POST /v6/oauth/token HTTP/1.1Host: apis.onestore.comContent-Type: application/x-www-form-urlencoded;charset=UTF-8` `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;

  <br>

  | `{    "client_id":"com.onestore.game.goindol",    "access_token":"680b3621-1234-1234-1234-8adfaef561b4",    "token_type":"bearer",    "expires_in":3010,    "scope":"DEFAULT"}` |
  | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

  <br>

  <br>
* **발급 예시** :&#x20;

  | `curl -v -X POST -H "Content-Type: application/x-www-form-urlencoded"` `https://sbpp.onestore.co.kr/v6/oauth/token -d "grant_type=client_credentials" -d "client_id=com.onestore.game.goindol" -d "client_secret=vxIMAGcVz3DAx20uDBr/IDWNJAPNHFl7YruF4uxB6BI="> POST /v6/oauth/token HTTP/1.1> Host: sbpp.onestore.co.kr> 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< HTTP/1.1` `200` `200< Date: Wed, 02` `May 2018` `02:52:42` `GMT< Server: Apache< Connection: close< Transfer-Encoding: chunked< Content-Type: application/json;charset=UTF-8<* Closing connection 0{"client_id":"com.onestore.game.goindol","access_token":"680b3621-1234-1234-1234-8adfaef561b4","token_type":"bearer","expires_in":3600,"scope":"DEFAULT"}` |
  | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

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

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

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

* **Desc :** 구매한 원스토어 관리형 상품의 상세정보를 조회합니다. 구매완료 시 전달받은 원스토어 purchaseToken(구매 토큰)을 이용하여 조회하여야 합니다. 월정액 상품의 purchaseToken으로 조회 시, 조회 실패(NoSuchData) 응답이 전달됩니다.
* **URI :** https\://{host}/v6/apps/{packageName}/purchases/inapp/products/{productId}/{purchaseToken}
* **Method :** GET
* **Request Parameter :** Path Variable 형식
  * String packageName : API를 호출하는 앱의 패키지 네임 (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                        |
* **Example**&#x20;

  | `Request.setHeader("Authorization", "Bearer 680b3621-1234-1234-1234-8adfaef561b4");Request.setHeader("Content-Type", "application/json");` |
  | ------------------------------------------------------------------------------------------------------------------------------------------ |
* **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) |
* **Example:**

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

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

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

  | Parameter Name | Data Type | Required | Description                             |
  | -------------- | --------- | -------- | --------------------------------------- |
  | Authorization  | String    | true     | Access Token API를 통해 발급받은 access\_token |
  | Content-Type   | String    | true     | application/json                        |
* **Example :**&#x20;

  | `Request.setHeader("Authorization", "Bearer 680b3621-1234-1234-1234-8adfaef561b4");Request.setHeader("Content-Type", "application/json");` |
  | ------------------------------------------------------------------------------------------------------------------------------------------ |
* **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;

  | `HTTP/1.1` `200` `OKContent-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-api-apiv6-acknowledgepurchase" id="id-api-apiv6-acknowledgepurchase"></a>

* **Desc :** 구매한 관리형 또는 월정액 상품을 구매확인 상태로 변경한다.
* **URI :** https\://{host}/v6/apps/{packageName}/purchases/all/products/{productId}/{purchaseToken}/acknowledge
* **Method :** POST
* **Request Parameter :** Path Variable 형식
  * String packageName : API를 호출하는 앱의 패키지 네임 (Data Size : 128)
  * String productId : 상품 ID (Data Size : 150)
  * String purchaseToken : 구매 토큰 (Data Size : 20)
* **Request Header :**

  | Parameter Name | Data Type | Required | Description                             |
  | -------------- | --------- | -------- | --------------------------------------- |
  | Authorization  | String    | true     | Access Token API를 통해 발급받은 access\_token |
  | Content-Type   | String    | true     | application/json                        |
* **Example**

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

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

  | `{    "developerPayload": "your payload"}` |
  | ------------------------------------------ |

  \ <br>
* **Response Body :** JSON 형식

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

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

  | `HTTP/1.1` `200` `OKContent-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-api-apiv6-consumepurchase" id="id-api-apiv6-consumepurchase"></a>

* **Desc :** 구매한 관리형 인앱 상품을 소비 상태로 변경한다.
* **URI :** https\://{host}/v6/apps/{packageName}/purchases/inapp/products/{productId}/{purchaseToken}/consume
* **Method :** POST
* **Request Parameter :** Path Variable 형식
  * String packageName : API를 호출하는 앱의 패키지 네임 (Data Size : 128)
  * String productId : 상품 ID (Data Size : 150)
  * String purchaseToken : 구매 토큰 (Data Size : 20)
* **Request Header :**

  | Parameter Name | Data Type | Required | Description                             |
  | -------------- | --------- | -------- | --------------------------------------- |
  | Authorization  | String    | true     | Access Token API를 통해 발급받은 access\_token |
  | Content-Type   | String    | true     | application/json                        |
* **Example**

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

  | Element Name     | Data Type | Required | Description |
  | ---------------- | --------- | -------- | ----------- |
  | developerPayload | String    | false    | <p><br></p> |
* **Response Body :** JSON 형식

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

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

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

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

* **Desc :** 월정액 상품의 자동결제 해지를 요청한다.
* **URI :** https\://{host}/v6/apps/{packageName}/purchases/auto/products/{productId}/{purchaseToken}/cancel
* **Method :** POST
* **Request Parameter :** Path Variable 형식
  * String packageName : API를 호출하는 앱의 패키지 네임 (Data Size : 128)
  * String productId : 상품 ID (Data Size : 150)
  * String purchaseToken : 구매 토큰 (Data Size : 20)
* **Request Header :**

  | Parameter Name | Data Type | Required | Description                             |
  | -------------- | --------- | -------- | --------------------------------------- |
  | Authorization  | String    | true     | Access Token API를 통해 발급받은 access\_token |
  | Content-Type   | String    | true     | application/json                        |
* **Example**

  | `Request.setHeader("Authorization", "Bearer 680b3621-1234-1234-1234-8adfaef561b4");Request.setHeader("Content-Type", "application/json");` |
  | ------------------------------------------------------------------------------------------------------------------------------------------ |
* **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;

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

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

* **Desc :** 월정액 상품의 자동결제 해지요청을 취소한다.
* **URI :** https\://{host}/v6/apps/{packageName}/purchases/auto/products/{productId}/{purchaseToken}/reactivate
* **Method :** POST
* **Request Parameter :** Path Variable 형식
  * String packageName : API를 호출하는 앱의 패키지 네임 (Data Size : 128)
  * String productId : 상품 ID (Data Size : 150)
  * String purchaseToken : 구매 토큰 (Data Size : 20)
* **Request Header :**

  | Parameter Name | Data Type | Required | Description                             |
  | -------------- | --------- | -------- | --------------------------------------- |
  | Authorization  | String    | true     | Access Token API를 통해 발급받은 access\_token |
  | Content-Type   | String    | true     | application/json                        |
* **Example**

  | `Request.setHeader("Authorization", "Bearer 680b3621-1234-1234-1234-8adfaef561b4");Request.setHeader("Content-Type", "application/json");` |
  | ------------------------------------------------------------------------------------------------------------------------------------------ |
* **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;

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

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

* **Desc :** 구매취소내역을 조회한다.
* **URI :** https\://{host}/v6/apps/{packageName}/voided-purchases
* **Method :** GET
* **Request Parameter :** Path Variable 형식
  * String packageName : API를 호출하는 앱의 패키지 네임 (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 :**

  | Parameter Name | Data Type | Required | Description                             |
  | -------------- | --------- | -------- | --------------------------------------- |
  | Authorization  | String    | true     | Access Token API를 통해 발급받은 access\_token |
  | Content-Type   | String    | true     | application/json                        |
* **Example**

  | `Request.setHeader("Authorization", "Bearer 680b3621-1234-1234-1234-8adfaef561b4");Request.setHeader("Content-Type", "application/json");` |
  | ------------------------------------------------------------------------------------------------------------------------------------------ |
* **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;

  | `HTTP/1.1` `200` `OKContent-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"        }    ]}` |
  | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

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

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

| Code                       | Message                                                                               | Description                              | HTTP Status Code                      | 대상 API                                                                                                  |
| -------------------------- | ------------------------------------------------------------------------------------- | ---------------------------------------- | ------------------------------------- | ------------------------------------------------------------------------------------------------------- |
| AccessBlocked              | The request was blocked.                                                              | 요청이 차단되었습니다.                             | 403 - Fobidden                        | 공통                                                                                                      |
| AccessTokenExpired         | Access token has expired.                                                             | Access 토큰이 만료되었습니다.                      | 401 - Unauthorized                    | 공통                                                                                                      |
| 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-api-apiv6" id="id-api-apiv6"></a>

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

* **Response Body :** JSON 형식

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

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

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

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

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

#### 마켓 구분 코드  <a href="#id-api-apiv6" id="id-api-apiv6"></a>

| Code     | Name | Description   |
| -------- | ---- | ------------- |
| MKT\_ONE | 원스토어 | 원스토어 마켓 구분 코드 |
