채팅 로그 수집 시스템(CLCS)
send-chat-log
채팅 로그 수집 시스템에 채팅 로그를 전송하기 위한 API입니다.
- Request URL
상용 URL https://clcs.qpyou.cn/chat/api/v1/send-chat-log Sandbox URL https://sandbox-clcs.qpyou.cn/chat/api/v1/send-chat-log HTTP Method POST Content-Type application/json - Request Body
필드명 타입 필수 설명 game_key String Y 회사 id와 게임 id로 정의한 키 값(16글자)입니다. Hive 콘솔 AI 서비스 > 채팅 어뷰징 탐지 > 게임 관리 > 암호 키에서 얻을 수 있습니다. 회사 id와 게임 id는 Hive 콘솔 AI 서비스 > 채팅 어뷰징 탐지 > 게임 관리에서 확인 가능합니다.
예) abcdefghijklmnop
chat_log object Y 암호화된 메시지의 배열 혹은 컬렉션 및 채팅 카운트 - chat_log object
필드명 타입 필수 설명 chat_count int Y msg_array에 존재하는 msg 개수입니다.
예) 32 (chat_count값과 암호화한 msg들이 들어있는 msg_array 크기는 동일해야 합니다.)msg_array array Y 1개 이상의 msg object - msg object;
필드명 타입 필수 설명 time_stamp string Y 채팅 발생 시간을 ISO8601 포맷으로 변경하여 전송합니다. ISO8601 포맷으로 변경하면 채팅 전송 유저가 소속된 타임존에 따라 채팅 발생 시간에 ±hh:mm가 붙습니다.
채팅 전송 유저가 소속된 타임존과 채팅 발생 시간에 따른 time_stamp값 예시
- 소속 타임존이 UTC이고 채팅 발생 시간이 2023-03-30 17:13:00
- 2023-03-30T17:13:00+00:00 또는 2023-03-30T17:13:00Z를 사용
- +00:00은 Z로도 표기할 수 있음(YYYY-MM-DDTHH:mm:ss{.mmm}±hh:mm 또는 YYYY-MM-DDTHH:mm:ss{.mmm}Z)
- 소속 타임존이 한국 표준시(KST)이고 채팅 발생 시간이 2023-03-30 17:13:00
- 2023-03-30T17:13:00+09:00를 사용
- 소속 타임존이 중부 표준시(CST)이고 채팅 발생 시간이 2023-03-30 17:13:00
- 2023-03-30T17:13:00-05:00를 사용
msg string Y Hive 콘솔 AI 서비스 > 채팅 어뷰징 탐지 > 게임 관리에서 발급한 암호 키를 이용하여 AES256 방식으로 암호화 된 JSON string (최대 사이즈 2KB) - 소속 타임존이 UTC이고 채팅 발생 시간이 2023-03-30 17:13:00
- msg
필드명 타입 필수 설명 time_stamp string Y 채팅 발생 시간을 ISO8601 포맷으로 변경하여 전송합니다. ISO8601 포맷으로 변경하면 채팅 전송 유저가 소속된 타임존에 따라 채팅 발생 시간에 ±hh:mm가 붙습니다. 채팅 전송 유저가 소속된 타임존과 채팅 발생 시간에 따른 time_stamp값 예시
- 소속 타임존이 UTC이고 채팅 발생 시간이 2023-03-30 17:13:00
- 2023-03-30T17:13:00+00:00 또는 2023-03-30T17:13:00Z를 사용
- +00:00은 Z로도 표기할 수 있음(YYYY-MM-DDTHH:mm:ss{.mmm}±hh:mm 또는 YYYY-MM-DDTHH:mm:ss{.mmm}Z)
- 소속 타임존이 한국 표준시(KST)이고 채팅 발생 시간이 2023-03-30 17:13:00
- 2023-03-30T17:13:00+09:00를 사용
- 소속 타임존이 중부 표준시(CST)이고 채팅 발생 시간이 2023-03-30 17:13:00
- 2023-03-30T17:13:00-05:00를 사용
room_num int Y 채팅방 번호 예) 123342
lang_code int Y 언어 코드 값
한국어(ko) : 1, 영어(en) : 2, 일본어(ja) : 3, 중문 간체 : 4, 중문 번체 : 5, 에스파냐(es) : 6,
러시아(ru) : 7, 독일어(de) : 8, 프랑스어(fr) : 9, 포르투갈어(pt) : 10, 이태리어(it) : 11,
태국어(th) : 12, 인도네시아어(id) : 13, 터키어(tr) : 14, 말레이시아어(ms) : 15, 베트남어(vi) : 16chat_msg string Y 유저 채팅 내용
예) 안녕하세요! 오늘 날씨가 좋네요chat_mode int Y 채팅 형태 구분
예)
100: 일반 채팅
200: 그룹(1:1~N) 채팅
300: 귓속말
4NN: 게임사가 자체적으로 정의한 채팅 타입channel_user_id int Y 게임 상의 유저 ID 번호(playerId) - 소속 타임존이 UTC이고 채팅 발생 시간이 2023-03-30 17:13:00
- Response
필드명 타입 설명 result object 출력 결과 컨테이너 result_code string 결과 코드 result_msg string 결과 메시지 - Result Code
result_code result_msg 조치 방법 200 Success 전송 성공으로 별도의 조치가 필요 없습니다. 500 Incorrect request 요청에 오류가 있습니다. URL , 필요 요청 변수의 값이 정확한지 확인 바랍니다. 501 The number of messages does not match 전달 된 메시지의 카운트가 일치하지 않습니다. chat_count 값과 msg_array의 길이가 일치해야합니다. 502 Incorrect secret key 올바르지 않은 암호 키 값입니다.
게임 관리에서 해당 게임의 옵션 열의 “암호 키 확인”를 눌러 암호 키 값을 확인하시기 바랍니다.503 Unregistered game key 올바르지 않은 게임 키 값입니다.
게임 관리에서 해당 게임의 옵션 열의 “암호 키 확인”를 눌러 게임 키 값을 확인하시기 바랍니다.506 System error 채팅 로그 수집 시스템의 오류에 의한 점검 시 발생합니다. 507 The size of the message is too large 전달한 메시지의 사이즈가 너무 큽니다. msg_array의 최대 크기는 2KB 입니다. - 예시
- Python
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253import requestsimport jsonfrom Crypto.Cipher import AESfrom Crypto.Util.Padding import padimport base64# 어뷰징 탐지 시스템 > 게임 관리에서 획득한 게임키와 암호키game_key = <GAME_KEY>secret_key = <SECRET_KEY>aes = AES.new(secret_key, AES.MODE_ECB)url = "https://clcs.qpyou.cn/chat/api/v1/send-chat-log"# 메시지 암호화def encrypt_msg(room_num:int,lang_code:int,chat_msg:str,chat_mode:int,channel_user_id:int) -> str:json_data = {"time_stamp":"2023-02-20T10:22:10+09:00", # datetime.now().isoformat()"room_num":room_num,"lang_code":lang_code,"chat_msg":chat_msg,"chat_mode":chat_mode,"channel_user_id":channel_user_id}json_str = json.dumps(json_data)padded_str = pad(json_str.encode("utf-8"),AES.block_size)encrypted_data = aes.encrypt(padded_str)encrypted_data_b64 = base64.b64encode(encrypted_data).decode("utf-8")return encrypted_data_b64# Json 정의json_payload = {"game_key": game_key,"chat_log": {"chat_count": N, # msg_array 리스트 사이즈"msg_array": [{"time_stamp":"2023-02-20T10:22:10+09:00","msg":encrypt_msg(room_num,lang_code,.......)},{"time_stamp":"2023-02-20T10:22:10+09:00","msg":encrypt_msg(room_num,lang_code,.......)}, ...]}}def call_curl_post(url, json_payload):headers = {'Content-type': 'application/json'}response = requests.post(url, data=json.dumps(json_payload), headers=headers)# 함수 호출call_curl_post(url=url, json_payload) - Java
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576import java.util.Collections;import java.util.HashMap;import java.util.Map;import javax.crypto.Cipher;import javax.crypto.spec.SecretKeySpec;import org.apache.tomcat.util.codec.binary.Base64;import org.springframework.http.HttpHeaders;import org.springframework.http.MediaType;import net.minidev.json.JSONObject;public class SampleCode {// 어뷰징 탐지 시스템 > 게임 관리에서 획득한 게임키와 암호키private String gameKey = <GAME_KEY>;private String secretKey = <SECRET_KEY>;private String url = "https://clcs.qpyou.cn/chat/api/v1/send-chat-log"public void callCurlPost() {RestTemplate restTemplate = new RestTemplate();HttpHeaders headers = new HttpHeaders();headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON_UTF8));headers.setContentType(MediaType.APPLICATION_JSON);Map<String, Object> parameters = new HashMap<>();parameters.put("game_key", gameKey);parameters.put("chat_log", "{\"chat_count\" : N //msg_array 리스트 사이즈,\"msg_array\":[{\"time_stamp\":\"2023-02-20T10:22:10+09:00\", \"msg\":encrypt_msg(,,....)},{\"time_stamp\":\"2023-02-20T10:22:10+09:00\", \"msg\":encrypt_msg(,,....)}, ...]}");JSONObject jsonParam = getJsonStringFromMap(parameters);HttpEntity<JSONObject> requestEntity = new HttpEntity<>(jsonParam, headers);ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.POST, requestEntity, String.class);System.out.println("Response status code: " + response.getStatusCode());System.out.println("Response body: " + response.getBody());}// 메시지 암호화private String encrypt_msg(int room_num, int lang_code, String chat_msg, int chat_mode, int channel_user_id) throws Exception {Map<String,Object> map = new HashMap<String,Object>();map.put("time_stamp", "2023-02-20T10:22:10+09:00"); //# "%Y-%m-%d %H:%M:%S",map.put("room_num", room_num);map.put("lang_code", lang_code);map.put("chat_msg", chat_msg);map.put("chat_mode", chat_mode);map.put("channel_user_id", channel_user_id);JSONObject encrypt_json = new JSONObject(map);String encrypt_str = encrypt_json.toJSONString();return encrypt(encrypt_str, secret_key);}// 암호화private String encrypt(String plainText, String key) throws Exception {byte[] keyBytes = key.getBytes("UTF-8");SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");cipher.init(Cipher.ENCRYPT_MODE, keySpec);byte[] encryptedBytes = cipher.doFinal(plainText.getBytes("UTF-8"));return Base64.encodeBase64String(encryptedBytes);}private static JSONObject getJsonStringFromMap( Map<String, Object> map ){JSONObject jsonObject = new JSONObject();for( Map.Entry<String, Object> entry : map.entrySet() ) {String key = entry.getKey();Object value = entry.getValue();jsonObject.put(key, value);}return jsonObject;}} - Curl
123456789101112131415161718192021222324252627282930//TEST CALLcurl-d '{"game_key": 회사 키,"chat_log":{"chat_count" : 1,"msg_array":[{"2023-02-20T10:22:10+09:00", "msg":"암호화된 텍스트"}]}}'-H "Content-Type: application/json"-X POST https://test-clcs.qpyou.cn/chat/api/v1/send-chat-log//HEADERPOST https://clcs-qpyou.cn/v1/chat/send-chat-logHost: clcs-qpyou.cnUser-Agent: curl/7.43.0Accept: */*Content-Type: application/json//BODY{"game_key":"abcdefghijklmnop","chat_log":{"chat_count" : 2,"msg_array":[{"time_stamp":"2023-02-20T10:22:10+09:00","msg":"yBDyG1rCthbkXCSpSgGM+ZfHs/B3bZtnxq7f6BOPX2c1Bk8xRAwF6HbkDeN/9prpqeD......"},{"time_stamp":"2023-02-20T10:22:10+09:00","msg":"yBDyG1rCthbkXCSpSgGM+ZfHs/B3bZtnxq7f6BOPX2c1Bk8xRAwF6HbkDeN....."}]}} - 결과
123456{"result":{"result_code":"100","result_msg":"success"}}
- Python