인증 헤더 만들기

인증 헤더 만들기

Private API 요청 시 발급받은 Connect Key와 Secret Key를 이용하여 4개의 파라미터를 헤더에 추가하여 전송합니다.

요청 변수

설명

타입

api-client-type

Api-Sign 생성 시 사용하는 구분자 유형
"0" : Ascii Code 0 (기본값)
"1" : Ascii Code 1
"2" : ";" (semicolon)

String/선택

Api-Key

사용자 API Key

String/필수

Api-Nonce

현재의 시간을 밀리초(millisecond, ms)로 표현한 값
(예 : "1655280216476")

String/필수

Api-Sign

End Point + Request Parameter + Api-Nonce + 사용자 Secret Key를
조합하여 인코딩한 값

String/필수

생성된 인증 헤더의 페이로드 예시입니다.

{
    "api-client-type" : "2",
    "Api-Sign" : "OGU1NWYxYjRmYmJjMzRmZWIyM2FkMGFkghhvbDGVSDgweY2ZkYzE2MzIwY2I2OGZlZmViOGY2OWE1MDFlZmNiZWMyNTBjOWY5NWRhMTQyZDdkOTFlNzQzZGUwNTM1MjJjMDdjNTEGgvdw2EyOTMwMzVkNzc=",
    "Api-Nonce" : "1655282125050",
    "Api-Key" : "3095809fgv90t4hnf82fls9023rlasf023nl"
}

Api-Sign 생성 안내

  1. Request Parameter 조합

    • endpoint 파라미터 추가
      endpoint=/info/balance&order_currency=BTC&payment_currency=KRW
      
    • URL 인코딩
      endpoint=%2Finfo%2Fbalance&order_currency=BTC&payment_currency=KRW
      
  2. End Point + Request Parameter + Api-Nonce 조합

    • api-client-type에서 지정한 구분자를 이용해 3개의 값을 조합합니다.
      /info/balance;endpoint=%2Finfo%2Fbalance&order_currency=BTC&payment_currency=KRW;1655283111604
      
  3. HmacSha512 알고리즘으로 인코딩

    • 2번에서 조합한 값을 사용자의 Secret Key를 이용하여 인코딩합니다.
  4. Base64 인코딩

    • HmacSha512로 인코딩한 값을 다시 Base64로 인코딩합니다.
private String usecTime() {
  return String.valueOf(System.currentTimeMillis());
}

public static String encodeURIComponent(String s) {
  String result = null;

  try {
    result = URLEncoder.encode(s, "UTF-8")
        .replaceAll("\\+", "%20")
        .replaceAll("\\%21", "!")
        .replaceAll("\\%27", "'")
        .replaceAll("\\%28", "(")
        .replaceAll("\\%29", ")")
        .replaceAll("\\%26", "&")
        .replaceAll("\\%3D", "=")
        .replaceAll("\\%7E", "~");
  } catch (UnsupportedEncodingException e) {
    result = s;
  }

  return result;
}

private static final String DEFAULT_ENCODING = "UTF-8";
private static final String HMAC_SHA512 = "HmacSHA512";

public static byte[] hmacSha512(String value, String key){
  try {
    SecretKeySpec keySpec = new SecretKeySpec(
        key.getBytes(DEFAULT_ENCODING),
        HMAC_SHA512);

    Mac mac = Mac.getInstance(HMAC_SHA512);
    mac.init(keySpec);

    final byte[] macData = mac.doFinal( value.getBytes( ) );
    byte[] hex = new Hex().encode( macData );

    return hex;
  } catch (NoSuchAlgorithmException e) {
    throw new RuntimeException(e);
  } catch (InvalidKeyException e) {
    throw new RuntimeException(e);
  } catch (UnsupportedEncodingException e) {
    throw new RuntimeException(e);
  }
}

public static String asHex(byte[] bytes){
  return new String(Base64.encodeBase64(bytes));
}

private HashMap<String, String> getHttpHeaders(String endpoint, HashMap<String, String> rgData, String apiKey, String apiSecret) {

  String strData = Util.mapToQueryString(rgData).replace("?", "");
  String nNonce = usecTime();

  strData = strData.substring(0, strData.length()-1);

  strData = encodeURIComponent(strData);

  HashMap<String, String> array = new HashMap<String, String>();

  String str = endpoint + ";"   + strData + ";" + nNonce;

  String encoded = asHex(hmacSha512(str, apiSecret));

  array.put("api-client-type", "2");
  array.put("Api-Key", apiKey);
  array.put("Api-Sign", encoded);
  array.put("Api-Nonce", String.valueOf(nNonce));

  return array;
}
def microtime(self, get_as_float = False):
        if get_as_float:
            return time.time()
        else:
            return '%f %d' % math.modf(time.time())

def usecTime(self) :
        mt = self.microtime(False)
        mt_array = mt.split(" ")[:2];
        return mt_array[1] + mt_array[0][2:5];
  
def xcoinApiCall(self, endpoint, rgParams):
        # 1. Api-Sign and Api-Nonce information generation.
        # 2. Request related information from the Bithumb API server.
        #
        # - nonce: it is an arbitrary number that may only be used once.
        # - api_sign: API signature information created in various combinations values.

        endpoint_item_array = {
            "endpoint" : endpoint
        };

        uri_array = dict(endpoint_item_array, **rgParams); # Concatenate the two arrays.

        str_data = urllib.parse.urlencode(uri_array);

        nonce = self.usecTime();

        data = endpoint + chr(0) + str_data + chr(0) + nonce;
        utf8_data = data.encode('utf-8');

        key = self.api_secret;
        utf8_key = key.encode('utf-8');

        h = hmac.new(bytes(utf8_key), utf8_data, hashlib.sha512);
        hex_output = h.hexdigest();
        utf8_hex_output = hex_output.encode('utf-8');

        api_sign = base64.b64encode(utf8_hex_output);
        utf8_api_sign = api_sign.decode('utf-8');


        curl_handle = pycurl.Curl();
        curl_handle.setopt(pycurl.POST, 1);
        #curl_handle.setopt(pycurl.VERBOSE, 1); # vervose mode :: 1 => True, 0 => False
        curl_handle.setopt(pycurl.POSTFIELDS, str_data);

        url = self.api_url + endpoint;
        curl_handle.setopt(curl_handle.URL, url);
        curl_handle.setopt(curl_handle.HTTPHEADER, ['Api-Key: ' + self.api_key, 'Api-Sign: ' + utf8_api_sign, 'Api-Nonce: ' + nonce]);
        curl_handle.setopt(curl_handle.WRITEFUNCTION, self.body_callback);
        curl_handle.perform();

        #response_code = curl_handle.getinfo(pycurl.RESPONSE_CODE); # Get http response status code.

        curl_handle.close();

        return (json.loads(self.contents));
XCoinAPI.prototype._getHttpHeaders = function(endPoint, rgParams, api_key, api_secret) {
    var strData = http_build_query(rgParams);
    var nNonce = this.usecTime();
    return {
        'Api-Key' : api_key,
        'Api-Sign' : (base64_encode(CryptoJS.HmacSHA512(endPoint + chr(0) + strData + chr(0) + nNonce, api_secret).toString())),
        'Api-Nonce' : nNonce
    };
}

XCoinAPI.prototype.usecTime = function(){
    var rgMicrotime = microtime().split(' '),
        usec = rgMicrotime[0],
        sec = rgMicrotime[1];

    usec = usec.substr(2, 3);
    return Number(String(sec) + String(usec));
}

function microtime(get_as_float) {
    var now = new Date()
            .getTime() / 1000;
    var s = parseInt(now, 10);

    return (get_as_float) ? now : (Math.round((now - s) * 1000) / 1000) + ' ' + s;
}

function http_build_query(obj) { 
    var output_string = [] 
    Object.keys(obj).forEach(function (val) {
        var key = val;  
        key = encodeURIComponent(key.replace(/[!'()*]/g, escape));

        if (typeof obj[val] === 'object') {
            var query = build_query(obj[val], null, key)
            output_string.push(query)
        }
        else {
            var value = encodeURIComponent(obj[val].replace(/[!'()*]/g, escape));
            output_string.push(key + '=' + value)
        } 
    })

    return output_string.join('&');
}

샘플 소스 전체 다운로드


Did this page help you?