Hive 아이템은 게임 내의 재화나 아이템의 지급/회수 기능을 통합하여 관리할 목적으로 제공하는 시스템입니다. Hive 아이템 연동은 쿠폰 시스템, 이벤트, 오퍼월, CPI 등과 연동하여 아이템을 지급 또는 회수하는 기능을 제공합니다. 관리자용 백오피스에서는 수동으로 지급/회수하거나 이력을 검색할 수도 있습니다.
- 아이템 지급/회수 요청 API는 비동기(asynchronous) 방식으로 동작되며, API 요청 시 요청 정보 등록의 성공 및 실패 여부만 판단하여 응답합니다.
- 게임 서버 API 호출과 같은 실제 처리 동작에 대한 응답은 Hive 콘솔 메뉴의 빌링 > Hive 아이템 > 지급/회수 요청 또는 지급/회수 성공 로그에서 관련 내용을 검색한 후 검색 결과 목록의 상태 항목 클릭 시 나타나는 팝업 창에서 확인할 수 있습니다.
연동 준비 사항
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.202.181.123 (샌드박스 서버)
게임 서버 헬스 체크
Hive 아이템은 게임 서버의 이상 여부를 확인하기 위해 지급/회수 요청 API에 아래 내역을 전송합니다. Hive 아이템 서버에서 게임 서버로, Request Body에 5분 간격으로 2번 전송합니다.
1 |
{"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
값을 비교하여 검증합니다.
- 예제 코드
1234567891011121314151617181920212223242526// 변환된 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 \uc9c0\uae09 \uba54\uc138\uc9c0 QA \ud55c\uad6d","body": "HIVE Item \uc9c0\uae09 \uba54\uc138\uc9c0 QA \ud55c\uad6d\uc5b4 \ub178\ucd9c"}},"serverId": "kr","additionalinfo": "","gameIndex": 539}
HTTP 통신 방식의 지급/회수 요청 API
HTTP 통신 방식의 지급/회수 요청 API에서 기본 포트는 80이며 기타 다른 포트를 사용하려면 방화벽 해제 신청이 필요합니다. Hive 아이템에서 게임 서버로 보내는 요청은 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
필드명 | 설명 |
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
123456curl -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":"\ud55c\uae00 \uba54\uc138\uc9c0","body":"\ud55c\uae00 \ub0b4\uc6a9"},"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
1234567> 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
1234567< 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)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 |
// 요청 데이터 $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)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
// 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 문자열 형태입니다.