콘텐츠로 이동

채팅 로그 전송

채팅 로그 수집 시스템(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글자)입니다. 하이브 콘솔 AI 서비스 > 채팅 어뷰징 탐지 > 게임 관리 > 암호 키에서 얻을 수 있습니다. 회사 id와 게임 id는 하이브 콘솔 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🇲🇲ss{.mmm}±hh:mm 또는 YYYY-MM-DDTHH🇲🇲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 하이브 콘솔 AI 서비스 > 채팅 어뷰징 탐지 > 게임 관리에서 발급한 암호 키를 이용하여 AES256 방식으로 암호화된 JSON string (최대 사이즈 2KB)
  • 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🇲🇲ss{.mmm}±hh:mm 또는 YYYY-MM-DDTHH🇲🇲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) : 16
chat_msg string Y 유저 채팅 내용 예) 안녕하세요! 오늘 날씨가 좋네요
chat_mode int Y 채팅 형태 구분 예) 100: 일반 채팅 200: 그룹(1:1~N) 채팅 300: 귓속말 4NN: 게임사가 자체적으로 정의한 채팅 타입
channel_user_id int Y 게임 상의 유저 ID 번호(playerId)
  • 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
    import requests
    import json 
    from Crypto.Cipher import AES
    from Crypto.Util.Padding import pad
    import 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
    import 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

    //TEST CALL
    curl 
    -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
    
    //HEADER
    POST https://clcs-qpyou.cn/v1/chat/send-chat-log
    Host: clcs-qpyou.cn
    User-Agent: curl/7.43.0
    Accept: */*
    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....."
                }
            ]
        }
    }
    
    + 결과

    {
        "result":{
            "result_code":"100",
            "result_msg":"success"
        }
    }