소비 정보 전송
앱 사용자가 환불 요청을 할 때 사용자 소비 정보를 앱 스토어에 전송하는 API를 제공합니다.
'소비 정보 전송' API는 Hive 서버와 앱 서버 간의 Server-to-Server 통신 방식으로 Hive 서버가 앱 서버로 소비 정보 전송 요청을 보내면, 앱 서버에서 응답값을 Hive 서버로 반환합니다.
Info
소비 정보 전송은 Apple App Store와 Google Play를 지원합니다. 전송을 촉발하는 시점과 응답 데이터 규격이 스토어에 따라 다르므로, 아래 탭에서 연동하려는 스토어를 선택해 참고하세요.
Apple App Store¶
스토어에 전송할 소비 정보에는 앱 서버에만 존재하는 데이터도 있습니다. 따라서 Hive 서버가 이 데이터를 Apple App Store에 전송하려면, 앱 서버에서 Hive 서버에 데이터를 전달해줘야 합니다.
앱 서버 URL은 앱 서버가 Hive 서버에 데이터를 전달하기 위해, 앱 서버에서 열어놓은 API 엔드포인트입니다. 아래 규약에 따라 API 엔드포인트를 구성한 후 이를 앱 서버 URL에 등록하시면, 사용자가 환불 요청을 할 때마다 Hive 서버가 이 API 엔드포인트로 POST 요청을 하고 필요한 데이터를 앱 서버로부터 전달받습니다. Hive 서버는 이 데이터를 취합해 앱 개발사를 대신해 Apple App Store에 소비 정보 전송을 완료합니다.
전체 과정을 요약하면 아래와 같습니다.
- 앱: 아래 규약대로 API 엔드포인트를 구성해 서버 URL을 준비
- 앱: Hive 콘솔의 부가 서비스 설정 > 소비 정보 전송에서 Apple App Store 사용을 선택하고 서버 URL을 등록
- 앱 클라이언트: 앱을 실행한 상태에서 인앱 상품 소비 정보 전송에 동의
- 앱 사용자: 앱에서 환불 요청
- Apple: Hive 서버로 소비 정보 요청(CONSUMPTION_REQUEST) 발송
- Hive 서버: 앱에서 등록한 서버 URL로 POST API 요청, 앱 서버로부터 응답값으로 소비 정보 데이터 수신
- Hive 서버: Apple App Store에 소비 정보 전송(성공 시 Apple이 HTTP 202 응답)
Warning
만약 앱 사용자가 동의 팝업에서 정보 전송에 동의하지 않으면, Hive 서버는 앱 서버로부터 데이터를 받더라도 이를 스토어에 전송하지 않습니다. 사용자 동의 여부(customerConsented)는 앱 서버가 보내지 않으며 Hive 서버가 자체적으로 설정합니다.
방화벽 규칙 해제¶
서버 URL에 등록할 API 엔드포인트는 요청 매개변수의 사용자 정보(player_id)와 거래 정보(transaction_id)로 소비 정보를 조회하고, 아래 규약에 맞는 데이터를 응답으로 전달해야 합니다.
Hive 서버가 앱 서버 API 엔드포인트로 요청을 보낼 수 있도록, 앱 서버에서 아래 IP 주소에 대해 방화벽 인바운드 규칙을 해제해야 합니다.
| Hive 서버 IP |
|---|
| 15.165.223.210 |
| 3.34.158.195 |
| 43.202.20.33 |
| 13.209.91.38 |
| 3.34.235.15 |
| 15.165.134.120 |
API 요청(Hive 서버 → 앱 서버) 구성¶
Hive 서버에서 앱 서버로 보내는 POST 요청 정보입니다.
| API 정보 | 설명 |
|---|---|
| Method | POST |
| Response Format | JSON |
| Content-type | application/json |
Request body¶
요청 본문 정보는 아래와 같습니다.
| 명칭 | 타입 | 필수 여부 (필수: M, 옵션: O) | 설명 |
|---|---|---|---|
| gameindex | Integer | M | 앱 센터 게임 인덱스 |
| appid | String | M | 앱 센터 AppID |
| server_id | String | M | 앱 서버 ID |
| player_id | String | M | 앱 내 사용자 식별자(구매 검증 시 사용하는 사용자 식별 값). V1의 user_seq에 해당 |
| transaction_id | String | M | Apple 원거래 ID(originalTransactionId) |
요청 본문 예시는 아래와 같습니다.
{
"gameindex": 539,
"appid": "com.com2us.hivesdk.normal.freefull.apple.global.ios.universal",
"server_id": "server_01",
"player_id": "222333",
"transaction_id": "2000000123456789"
}
API 응답(앱 서버 → Hive 서버) 구성¶
앱 서버는 처리 결과 코드(code), 결과 메시지(message), 소비 정보(data)를 Hive 서버로 전달합니다.
Response body¶
Hive 서버는 code 값으로 성공 여부를 판별합니다. 200이면 성공으로 보고 data를 사용하며, 그 외 코드는 해당 건을 전송하지 않고 message를 사유로 기록합니다. code는 필수이며, 보내지 않으면 오류로 처리해 해당 건을 전송하지 않습니다.
| 명칭 | 타입 | 필수 여부 (필수: M, 옵션: O) | 설명 |
|---|---|---|---|
| code | Integer | M | 처리 결과 코드(아래 표 참고). 200만 성공이며, 그 외 코드는 오류로 처리 |
| message | String | O | 처리 결과 메시지. 오류 시 사유 설명용 |
| data | Object | M | 응답 데이터(성공 시 필수) |
| ┕ delivery_status | String | M | 소모성 아이템 전달 상태. 아래 전달 상태 표의 값 중 하나 |
| ┕ refund_preference | String | O | 환불 선호도. 아래 환불 선호도 표의 값 중 하나 |
| ┕ consumption_percentage | Integer | O | 소비 비율. millipercent 단위 0~100000 (100000 = 100%) |
| ┕ sample_content_provided | Integer | O | 샘플 콘텐츠 제공 여부. 0 또는 1 |
응답 코드¶
| 값 | 설명 |
|---|---|
| 200 | 성공 |
| 400 | 잘못된 요청값 |
| 500 | 서버 에러 |
전달 상태(delivery_status)¶
소모성 아이템의 전달 상태를 나타내며, 아래 5개 값 중 하나여야 합니다(필수).
| 값 | 의미 |
|---|---|
| DELIVERED | 소모성 아이템을 정상적으로 전달했고 정상 작동 |
| UNDELIVERED_QUALITY_ISSUE | 품질 문제로 전달하지 못함 |
| UNDELIVERED_WRONG_ITEM | 구매한 것과 다른(잘못된) 아이템을 전달함 |
| UNDELIVERED_SERVER_OUTAGE | 서버 장애로 전달하지 못함 |
| UNDELIVERED_OTHER | 그 외 사유로 전달하지 못함 |
환불 선호도(refund_preference)¶
앱에서 선호하는 환불 처리 방향을 Apple에 전달합니다(선택). 값을 보낼 경우 아래 3개 중 하나여야 합니다.
| 값 | 의미 |
|---|---|
| GRANT_FULL | 전액 환불 부여를 선호 |
| DECLINE | 환불하지 않음(거부)을 선호 |
| GRANT_PRORATED | 부분(비례) 환불 부여를 선호(주로 구독) |
Warning
아래 값이 유효하지 않으면 스토어에 전송되지 않고 해당 건이 제외됩니다.
delivery_status는 필수이며, 위 5개 값 중 하나여야 합니다.refund_preference를 보낼 경우 위 3개 값 중 하나여야 합니다consumption_percentage를 보낼 경우 0~100000 범위의 정수여야 합니다.
Note
아래는 Hive 서버가 Apple 규칙에 따라 자동으로 조정하는 동작입니다.
delivery_status가DELIVERED가 아니면consumption_percentage는 0으로 전송됩니다.refund_preference가GRANT_PRORATED(구독)이면consumption_percentage는 생략됩니다.
응답 성공 시 응답 본문 예시는 아래와 같습니다.
Google Play¶
스토어에 전송할 소비 정보에는 앱 서버에만 존재하는 데이터도 있습니다. 따라서 Hive 서버가 이 데이터를 Google Play에 전송하려면, 앱 서버에서 Hive 서버에 데이터를 전달해줘야 합니다.
앱 서버 URL은 앱 서버가 Hive 서버에 데이터를 전달하기 위해, 앱 서버에서 열어놓은 API 엔드포인트입니다. 아래 규약에 따라 API 엔드포인트를 구성한 후 이를 앱 서버 URL에 등록하시면, 환불 심사 알림이 발생할 때마다 Hive 서버가 이 API 엔드포인트로 POST 요청을 하고 필요한 데이터를 앱 서버로부터 전달받습니다. Hive 서버는 이 데이터를 취합해 앱 개발사를 대신해 Google에 환불 심사 정보 전송을 완료합니다.
전체 과정을 요약하면 아래와 같습니다.
- 앱: 아래 규약대로 API 엔드포인트를 구성해 서버 URL을 준비
- 앱: Hive 콘솔의 부가 서비스 설정 > 소비 정보 전송에서 Google Play 사용을 선택하고 서버 URL을 등록
- 앱 사용자: 결제 건에 대해 금융기관(카드사 등)에 직접 환불(차지백) 요청
- Google: Hive 서버로 환불 심사 알림(pendingRefundReviewNotification) 발송
- Hive 서버: 앱이 등록한 서버 URL로 POST API 요청, 응답값으로 데이터 수령
- Hive 서버: Google에 환불 심사 정보 전송(
orders:reviewrefund, 성공 시 HTTP 200 빈 본문)
Note
Google Play 환불 심사는 사용자의 앱 내 동의 절차가 없습니다. 사용자가 금융기관에 직접 환불(차지백)을 요청한 건에 대해 Google이 Hive 서버로 환불 심사 알림을 발송하면 처리됩니다.
방화벽 규칙 해제¶
서버 URL에 등록할 API 엔드포인트는 요청 매개변수의 사용자 정보(player_id)와 거래 정보(order_id)로 소비 정보를 조회하고, 아래 규약에 맞는 데이터를 응답으로 전달해야 합니다.
Hive 서버가 앱 서버 API 엔드포인트로 요청을 보낼 수 있도록, 앱 서버에서 아래 IP 주소에 대해 방화벽 인바운드 규칙을 해제해야 합니다.
| Hive 서버 IP |
|---|
| 15.165.223.210 |
| 3.34.158.195 |
| 43.202.20.33 |
| 13.209.91.38 |
| 3.34.235.15 |
| 15.165.134.120 |
API 요청(Hive 서버 → 앱 서버) 구성¶
Hive 서버에서 앱 서버로 보내는 POST 요청 정보입니다.
| API 정보 | 설명 |
|---|---|
| Method | POST |
| Response Format | JSON |
| Content-type | application/json |
요청 본문 정보는 아래와 같습니다.
| 명칭 | 타입 | 필수 여부 (필수: M, 옵션: O) | 설명 |
|---|---|---|---|
| gameindex | Integer | M | 앱 센터 게임 인덱스 |
| appid | String | M | 앱 센터 AppID |
| server_id | String | M | 앱 서버 ID |
| player_id | String | M | 앱 내 사용자 식별자(구매 검증 시 사용하는 사용자 식별 값). V1의 user_seq에 해당 |
| order_id | String | M | Google 주문 ID(orderId) |
요청 본문 예시는 아래와 같습니다.
{
"gameindex": 539,
"appid": "com.com2us.hivesdk.normal.freefull.google.global.android.universal",
"server_id": "server_01",
"player_id": "222333",
"order_id": "GPA.3300-1234-5678-90123"
}
API 응답(앱 서버 → Hive 서버) 구성¶
앱 서버는 처리 결과 코드(code), 결과 메시지(message), 소비 정보(data)를 Hive 서버로 전달합니다.
Hive 서버는 code 값으로 성공 여부를 판별합니다. 200이면 성공으로 보고 data를 사용하며, 그 외 코드는 해당 건을 전송하지 않고 message를 사유로 기록합니다. code는 필수이며, 보내지 않으면 오류로 처리해 해당 건을 전송하지 않습니다.
| 명칭 | 타입 | 필수 여부 (필수: M, 옵션: O) | 설명 |
|---|---|---|---|
| code | Integer | M | 처리 결과 코드(아래 표 참고). 200만 성공이며, 그 외 코드는 오류로 처리 |
| message | String | O | 처리 결과 메시지. 오류 시 사유 설명용 |
| data | Object | M | 응답 데이터(성공 시 필수) |
| ┕ refund_preference | String | M | 환불 선호도. 아래 환불 선호도 표의 값 중 하나 |
| ┕ sample_content_provided | Integer | M | 샘플 콘텐츠 제공 여부. 0 또는 1 |
| ┕ consumption_percentage_milliunits | Integer | M | 소비 비율. millipercent 단위 0~100000 (100000 = 100%) |
| ┕ consumption_usage_events | Array | O | 소비 이벤트 목록(최대 1000개). 아래 소비 이벤트 표 참고 |
응답 코드¶
| 값 | 설명 |
|---|---|
| 200 | 성공 |
| 400 | 잘못된 요청값 |
| 500 | 서버 에러 |
환불 선호도(refund_preference)¶
앱이 선호하는 환불 처리 방향을 Google에 전달합니다. 아래 4개 값 중 하나여야 합니다(필수).
| 값 | 의미 |
|---|---|
| APPROVE | 환불 승인을 선호 |
| DECLINE | 환불하지 않음(거부)을 선호 |
| NEUTRAL | 선호 없음(중립) |
| REFUND_PREFERENCE_UNSPECIFIED | 선호를 지정하지 않음 |
소비 이벤트(consumption_usage_events)¶
각 소비 이벤트는 아래 필드로 구성합니다. 모든 필드는 선택이나, location을 보낼 경우 location.region_code는 필수입니다.
| 명칭 | 타입 | 필수 여부 | 설명 |
|---|---|---|---|
| obfuscated_account_id | String | O | 난독화된 계정 식별자 |
| obfuscated_profile_id | String | O | 난독화된 프로필 식별자 |
| consumption_time | String | O | 소비 시각(RFC 3339, 예: 2026-07-20T00:00:00Z) |
| ip_address | String | O | 소비 시점의 IP 주소 |
| consumption_item_description | String | O | 소비한 아이템 설명 |
| location | Object | O | 소비 위치 정보 |
| ┕ region_code | String | location 포함 시 M | 지역 코드(CLDR, 예: KR) |
| ┕ administrative_area | String | O | 행정 구역 |
| ┕ locality | String | O | 도시 |
| ┕ sublocality | String | O | 하위 지역 |
Warning
아래 값이 유효하지 않으면 Google에 전송되지 않고 해당 건이 제외됩니다.
refund_preference는 필수이며, 위 4개 값 중 하나여야 합니다.sample_content_provided는 필수이며, 0 또는 1이어야 합니다.consumption_percentage_milliunits는 필수이며, 0~100000 범위의 정수여야 합니다.consumption_usage_events를 보낼 경우 최대 1000개이며, 각 이벤트에location이 있으면location.region_code는 필수입니다.
응답 성공 시 응답 본문 예시는 아래와 같습니다.
{
"code": 200,
"message": "OK",
"data": {
"refund_preference": "APPROVE",
"sample_content_provided": 0,
"consumption_percentage_milliunits": 100000,
"consumption_usage_events": [
{
"consumption_time": "2026-07-20T00:00:00Z",
"ip_address": "203.0.113.10",
"consumption_item_description": "Sample consumed item",
"location": {
"region_code": "KR"
}
}
]
}
}