Hive 아이템 연동
Hive 아이템은 게임 내의 재화나 아이템의 지급/회수 기능을 통합하여 관리할 목적으로 제공하는 시스템입니다. Hive 아이템 연동은 쿠폰 시스템, 이벤트, 오퍼월, CPI 등과 연동하여 아이템을 지급 또는 회수하는 기능을 제공합니다. 관리자용 백오피스에서는 수동으로 지급/회수하거나 이력을 검색할 수도 있습니다.
Note
- 아이템 지급/회수 요청 API 는 비동기(asynchronous) 방식으로 동작되며, API 요청 시 요청 정보 등록의 성공 및 실패 여부만 판단하여 응답합니다.
- 게임 서버 API 호출과 같은 실제 처리 동작에 대한 응답 은 Hive 콘솔 메뉴의 빌링 > Hive 아이템 > 지급/회수 요청 또는 지급/회수 성공 로그 에서 관련 내용을 검색한 후 검색 결과 목록의 상태 항목 클릭 시 나타나는 팝업 창에서 확인할 수 있습니다.
- Hive 아이템은 대규모 트래픽 처리가 필요하므로 개발사 앱 서버 평균 응답 시간이 0.5초를 초과하면, 메인 Queue가 아닌 별도 Queue로 분리해 동작할 수 있습니다. 이 경우 아이템 지급 처리에 많은 지연이 발생할 수 있습니다. 원활한 아이템 지급 처리를 위해 개발사 앱 서버 평균 응답 시간 0.5초 미만을 유지하는 것을 권장합니다.
연동 준비 사항¶
Hive 아이템과 연동하려면 먼저 Hive 아이템 관리 메뉴에서 게임 서버 URL과 아이템을 등록해야 합니다.
지급/회수 요청 API¶
지급/회수 요청 API의 기본 사항 확인하기¶
API 통신 방식¶
- 지급/회수 요청 API는 HTTP 통신과 socket을 이용한 JSON String 통신 2가지 타입을 제공합니다.
- Hive 아이템에서 게임 서버로 JSON String 형태의 지급 또는 회수를 요청합니다.
- 게임 서버에서 Hive 아이템으로 JSON String 형태의 결과를 반환합니다.
- 응답 결과는 처리 코드와 메시지를 포함합니다.
- JSON String은 모두 UTF8로 인코딩해야 합니다.
게임 적용 방법¶
- 서비스 오픈 전에는 테스트 서버로, 서비스 오픈 후에는 상용 서버로 연동 테스트 결과를 전송합니다.
- 게임이 이미 서비스 중이어도 테스트 서버와 반드시 연동해야 합니다.
- 모든 아이템은 우편함으로 지급됩니다.
- 우편함에서 유저에게 보여줄 지급 문구가 필요한 경우 요청 명세 > 요청 사유를 참고하세요. 게임 서버에서는 표기하는 문구를 각 언어에 맞게 분기 처리해야 합니다.
- 아이템 요청은 유저당 하나씩 전송됩니다. 여러 아이템의 지급/회수 요청이 동시에 전송될 수 있으나 하나의 요청은 한 트랜잭션 내에서 처리되어야 합니다. 아이템 지급/회수 하나가 실패할 경우에는 전체 롤백 후 실패를 응답하도록 구현하세요.
게임 서버 방화벽 해제¶
서버로 통신하려면 게임 서버에서 아래 IP의 방화벽 인바운드 규칙을 해제해야 합니다.
- 52.79.76.25
- 3.37.22.75
- 43.133.238.219 (샌드박스 서버)
게임 서버 헬스 체크¶
Hive 아이템은 게임 서버의 이상 여부를 확인하기 위해 지급/회수 요청 API에 아래 내역을 전송합니다. Hive 아이템 서버에서 게임 서버로, Request Body에 5분 간격으로 2번 전송합니다.
{"transactionId":"","idCategory":"","id":"","detail":[{"action":"","assetCode":"","amount":0}],"reason":""}
위 내용을 전달받은 게임 서버는 Validation 에러가 발생할 수 있으며, 이 때는 Response 값 내 code와 message 필드에 에러 정보를 실어 응답하면 됩니다. Hive 아이템은 code 값만 단독으로 판단하지 않습니다. code, message 필드가 있으면 게임 서버가 정상이라고 판단하고 없으면 게임 서버가 비정상 상태라고 판단합니다.
Apihash 값 검증¶
게임 서버는 Header의 Apihash
값을 통해 Hive 아이템 서버로부터 전달받은 데이터의 유효성을 검증할 수 있습니다. 해시 값 검증에 앞서, 반드시 Hive 아이템 서버로부터 전달받은 Request Body 데이터를 JSON encode 또는 unicode로 변환해야 합니다. (예제 코드 참조)
요청 명세의 접두어와 변환된 JSON String 값을 혼합(접두어+JSON String)하여 SHA1 형식의 해시 값을 생성하고, 이 값과 Apihash
값을 비교하여 검증합니다.
- 예제 코드
// 변환된 JSON String 예시 (가독성을 위해 임의로 개행 및 공백 추가)
{
"transactionId": "123456789",
"idCategory": "vid",
"id": "1004",
"detail": [
{
"action": "p",
"assetCode": "gem",
"amount": 1,
"method": ""
}
],
"reason": "td",
"subReason": "",
"userMessage": "",
"templateMessage": {
"ko": {
"title": "HIVE Item uc9c0uae09 uba54uc138uc9c0 QA ud55cuad6d",
"body": "HIVE Item uc9c0uae09 uba54uc138uc9c0 QA ud55cuad6duc5b4 ub178ucd9c"
}
},
"serverId": "kr",
"additionalinfo": "",
"gameIndex": 539
}
HTTP 통신 방식의 지급/회수 요청 API¶
지급/회수 요청 API는 Hive 콘솔 > 빌링 > 아이템 > 아이템 등록 메뉴에서 설정한 게임 서버(URL)와 HTTP 프로토콜 통신을 하며, 요청 데이터 전송 방식은 POST 방식입니다.
요청 명세 (Hive 아이템 -> 게임 서버)¶
HTTP Header : Apihash
- 데이터 유효성 검증 위해 Apihash라는 키 값으로 해시 값을 전송합니다.
- 해시 값은 SHA1를 사용하세요. (본문 JSON String에 접두어 !@#COM2US!@# 추가)
Request Body (Hive 아이템 -> 게임 서버)
필드명 | 설명 | 타입 | 필수 여부 (필수: M, 옵션: O) |
---|---|---|---|
transactionId | 각 요청을 구별하기 위한 식별자 (중복 요청 확인용) 자세히 | String | M |
idCategory | ID
| String | M |
id | idCategory에 해당하는 ID 값 | String | M |
detail | 아래 세 항목 객체의 배열 | Array | M |
ㄴaction | 지급/회수 여부
| String | M |
ㄴassetCode | 지급할 항목 코드 | String | M |
ㄴamount | 지급 수량 | Integer | M |
reason | 요청 사유 자세히 | String | M |
subReason | 요청 사유 자세히 | String | O |
serverId | 대상 유저가 접속한 서버 (서버 구분값) | String | M |
additionalinfo | 게임 서버로 보내기 위해 클라이언트에서부터 넘어온 추가적인 정보 (모두 소문자) (JSON String 형식) | String | O |
duration | 우편함 보관 기간 (선택 사항) 자세히
| Integer | O |
userMessage | 아이템 지급 메시지 (고정 메시지) templateMessage를 사용하지 않는 구게임 호환용 | String | O |
templateMessage | 아이템 지급 메시지에 설정된 메시지 데이터key는 언어 코드, value는 메시지(title)와 본문(body)으로 구성 (단, 데이터가 존재하는 경우 기본 형식은 Object이며, 빈 값이면 공백 String으로 전달) | Object | O |
gameIndex | Hive 앱센터 게임별 일련번호 | Integer | M |
transactionId¶
- 이미 처리된 요청인지 transactionId로 식별하여 판단합니다. (중복 지급/회수 방지)
- 중복 요청의 경우 응답 값에 해당 사항을 명시합니다. (응답 명세 참고)
reason¶
Note
reason 필드 내역은 추후 추가/변경될 수 있으므로 해당 요청에 대한 발생 사유는 단순 참조용으로만 사용해야 합니다.
필드명 | 설명 |
---|---|
pe | 과금오류 (Payment Error) |
rge | 보상(게임오류) (Reward Game Error) |
rcd | 보상(고객불만) (Reward Consumer Dissatisfaction) |
rce | 보상(쿠폰오류) (Reward Coupon Error) |
ro | 보상(해외) (Reward Overseas) |
ae | 재화변경지급 (Asset Exchange) |
e | 이벤트 (Event) |
ea | 이벤트(자동) (Event Automatic) |
mc | 대량쿠폰 (Massive Coupon) |
uc | 고유쿠폰 (Unique Coupon) |
b | 인게임 빌링 (Billing - HIVE IAP v2) |
lb | 러비웹샵 빌링 (Lebi Billing) |
co | 오퍼월 (Cpi Offerwall) |
p | 프로모션 (Promotion) - 크로스배너, 오퍼월, UA 모두 동일하게 사용 |
sr | 스트리밍 보상 (Streaming Reward) |
tcs | 테스트(CS) (Test CS) |
tgm | 테스트(GM) (Test GM) |
tpm | 테스트(PM) (Test PM) |
tqa | 테스트(QA) (Test QA) |
td | 테스트(개발) (Test Developer) |
tg | 테스트(외부지급) (Test Guest) |
tmb | 테스트(홍보/사업) (Test Market , Business) |
to | 테스트(해외) (Test Overseas) (Test Developer) |
re | 회수(기타) (Retrieve Etc) |
rr | 회수(환불) (Retrieve Refund) |
mr | 대량요청 (Massive Request) |
etc | 기타 (Etc) |
subReason¶
Reason | subReason | 설명 |
---|---|---|
p | 프로모션 하위 요청 상세 | |
1 | 크로스 일반 배너 CPI | |
2 | 크로스 일반 배너 CPA | |
3 | 크로스 전면 배너 CPI | |
4 | 크로스 전면 배너 CPA | |
5 | 오퍼월 일반 CPI | |
6 | 오퍼월 일반 CPA | |
7 | 오퍼월 스페셜 CPI | |
8 | 오퍼월 스페셜 CPA | |
9 | UA CPI | |
10 | UA CPA | |
11 | UC CPI |
프로모션 기능 분류
- 크로스 프로모션: 유저가 플레이하는 현재 게임에서 배너와 오퍼월(무료충전소) 형태로 다른 게임을 광고할 수 있습니다. 일반 배너와 전면 배너로 나뉩니다.
- 오퍼월: 오퍼월에는 유저 기기에 설치 이력이 없는 게임 목록이 배너 형태로 표시됩니다. 유저가 배너를 터치한 후 연결되는 마켓에서 게임을 설치하면 보상을 지급합니다. 오퍼월 일반과 오퍼월 스페셜로 나뉩니다.
- UA/UC: 소셜 미디어와 QR 코드를 활용하는 게임 초대 기능입니다. UA에는 초대하는 유저와 받는 유저가 있는 반면 UC는 초대 받는 유저만 존재합니다. UC는 사전 예약에서 활용할 수 있습니다.
보상 방법
- CPI: 게임 설치 후 실행하면 보상을 지급합니다.
- CPA: 게임 실행 도중 정해진 목표를 달성하면 보상을 지급합니다. 자세한 내용은 프로모션 운영 가이드에서 확인하세요.
duration¶
- 요청 항목을 지급한 후 우편함에 보관하는 기간으로, 백오피스에서 항목마다 개별 설정할 수 있습니다.
- 게임 서버에서는 3가지 경우로 나눠 상황에 맞게 처리합니다.
- 해당 키가 존재하지 않을 경우: 게임 서버에서 설정한 기본값을 사용합니다. (예. 기본 7일 보관)
- 1~9999: 명시된 숫자를 일 단위로 사용합니다. (예. 값이 14이면 14일 보관)
- -1: 게임 서버에서 설정할 수 있는 최대값을 사용합니다. (예. 영구 보관)
응답 명세 (게임 서버 -> Hive 아이템)¶
Response (게임 서버 -> Hive 아이템)
필드명 | 설명 | Type | 필수 여부 (필수: M, 옵션: O) |
---|---|---|---|
code | 처리 결과 코드 자세히 | Integer | M |
message | 처리 결과 메시지 | String | M |
- 에러코드
코드값 | 설명 |
---|---|
2xxxx | 요청 이상 없음. 처리 성공 |
ㄴ 20000 | 요청 이상 없음. 처리 성공 |
ㄴ 20001 | 요청 이상 없음. 이미 성공 처리된 경우 (중복 요청) 이미 정상 처리된 transactionId가 존재할 경우 |
4xxxx | 요청 파라미터 오류 |
ㄴ 40001 | 요청 json 에러 |
ㄴ 40002 | 해쉬 오류 |
ㄴ 40003 | 필수 파라미터 키 누락 |
ㄴ 40004 | 필수 파라미터 키 타입 오류 |
ㄴ 40005 | 필수 파라미터 값 비어있음 |
ㄴ 40006 | 잘못된 필수 파라미터 값 (예. 음수) |
5xxxx | 서버 처리 오류 |
ㄴ 50001 | 존재하지 않는 유저 |
ㄴ 50004 | DB 등록 오류 |
ㄴ 50005 | 파라미터 오류 (예. 존재하지 않는 항목 코드) |
- Call Sample
curl -L -v
-d '{"transactionId":"27905","idCategory":"vid","id":"828292","detail":[{"action":"p","assetCode":"gold","amount":500,"method":""},{"action":"p","assetCode":"gem","amount":200,"method":""}],"reason":"td","subReason":"","userMessage":"","templateMessage":{"ko":{"title":"ud55cuae00 uba54uc138uc9c0","body":"ud55cuae00 ub0b4uc6a9"},"en":{"title":"English Message","body":"English Contents"}},"serverId":"kr","additionalinfo":"","gameIndex":539}'
-H "Content-Type: text/html"
-H "Apihash: e9d7307948ff0134fb59c5f96e68f5ae21e3e47f"
https://sandbox-misample.com2us.net/hive/item
- Request Sample
> POST /hive/item HTTP/2
> Host: sandbox-misample.com2us.net
> user-agent: curl/7.68.0
> accept: */*
> content-type: text/html
> apihash: e9d7307948ff0134fb59c5f96e68f5ae21e3e47f
> content-length: 447
- Response Sample
< HTTP/2 200
< server: nginx
< date: Tue, 12 Jul 2022 11:29:21 GMT
< content-type: application/json; charset=utf-8
<
* Connection #0 to host sandbox-misample.com2us.net left intact
{"status":"200","code":"20001","message":"this request has already been processed"}
Request Sample(PHP)
// 요청 데이터
$data = array(
'transactionId' => '12321',
'idCategory' => 'vid',
'id' => '828292',
'detail' => array(
array(
'action' => 's',
'assetCode' => 'gold',
'amount' => 500,
),
array(
'action' => 's',
'assetCode' => 'gem',
'amount' => 200,
),
),
'reason' => 'p',
'subReason' => '3',
'userMessage' => '',
'templateMessage' => array(
'ko' => array(
'title' => '한글 메세지',
'body' => '한글 내용'
),
'en' => array(
'title' => 'English Message',
'body' => 'English Contents'
),
),
'serverId' => 'GLOBAL',
'additionalinfo' => '{"character":1}',
'gameIndex' => 539
);
$jsonData = json_encode($data); // JSON 으로 변환
/********************************************************************
변환 결과(가독성을 위해 임의로 개행 및 공백 추가) :
{
"transactionId": "12321",
"idCategory": "vid",
"id": "828292",
"detail": [
{
"action": "s",
"assetCode": "gold",
"amount": 500
},
{
"action": "s",
"assetCode": "gem",
"amount": 200
}
],
"reason": "p",
"subReason": "3",
"userMessage": "",
"templateMessage": {
"ko": {
"title": "한글 메세지",
"body": "한글 내용"
},
"en": {
"title": "English Message",
"body": "English Contents"
}
},
"serverId": "GLOBAL",
"additionalinfo": "{"character":1}",
"gameIndex": 539
}
********************************************************************/
// header 를 application/json 으로 설정 & hash 설정
$hash = sha1('!@#COM2US!@#' . $jsonData);
$header = array(
'Content-type: application/json',
'Apihash: ' . $hash
);
$url = 'http://game.com2us.com/gms.php'; // 게임 서버 url
$curl = curl_init();
curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, $jsonData);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
$result = curl_exec( $curl );
curl_close( $curl );
// 결과 데이터 처리
$response = json_decode($result);
Response Sample(PHP)
// php header 선언
header('Content-type: application/json');
// json Data
$rawData = file_get_contents('php://input');
//Hash값 확인
$hash = sha1('!@#COM2US!@#' . $rawData);
$requestHash = $_SERVER['Apihash'];
if ($requestHash != $hash) {
/*****************************************************************
해쉬 값이 다를 경우의 처리 (해쉬 사용 여부는 선택사항)
*****************************************************************/
}
// 요청받은 JSON 데이터를 디코딩
$requestData = json_decode($rawData, TRUE);
foreach ($requestData['detail'] as $item) {
/*****************************************************************
요청에 따른 재화 처리
*****************************************************************/
}
$returnData = array(
'code' => 50001,
'message' => 'user not exists',
);
//UTF8BOM이 붙는 것을 방지하기 위해
ob_clean()
//JSON으로 변환하여 응답 전송
echo json_encode($returnData);
/*****************************************************************
변환 결과(임의로 개행 삽입) :
{
"code" : 50001,
"message" : "user not exists"
}
*****************************************************************/
Socket 통신 방식의 지급/회수 요청 API¶
Socket을 이용한 지급/회수 요청 API TCP/IP는 프로토콜을 이용한 패킷 데이터 통신으로, 기본 포트는 20080입니다. 데이터는 HTTP 통신 때와 동일한 JSON 형식이고 바이트 순서는 Network Byte order (Big-endian)입니다.
요청 패킷 명세 (Hive 아이템 -> 게임 서버)¶
패킷 크기 | 4 바이트 | 4 바이트 | 가변 | 4 바이트 | 가변 |
---|---|---|---|---|---|
설명 | 전체 패킷 길이 | Header 길이 | Header 내용 | Body 길이 | Body 내용 |
- 첫 4 바이트는 해당 4 바이트를 포함한 패킷 전체의 길이를 명시합니다.
예. header가 46 바이트, body가 100 바이트라면 4+4+46+4+100 = 158 바이트 - 다음 4 바이트는 바로 뒤에 이어질 Header 길이를 의미합니다.
- Header는 HTTP 통신에서의 해쉬 값과 동일한 JSON 문자열 형태입니다.
예.{"Apihash":"912ec803b2ce49e4a541068d495ab570"}
- 마지막 4 바이트는 바로 뒤에 이어질 Body 길이를 의미합니다.
- Body는 HTTP 통신에서의 요청 값과 동일한 JSON 문자열 형태입니다.
응답 패킷 명세 (게임 서버 -> Hive 아이템)¶
패킷 크기 | 4 바이트 | 가변 |
---|---|---|
내용 | 전체 패킷 길이 | Body |
- 첫 4 바이트는 해당 4 바이트를 포함한 패킷 전체의 길이를 명시합니다.
- Body는 HTTP 통신에서의 응답 값과 동일한 JSON 문자열 형태입니다.