본문 바로가기
업비트 자동매매 만들기

[#2-2][업비트 자동매매 C# winform] [API 소스]

by 코코코인 2021. 12. 14.
728x90

이전글:

2021.12.14 - [업비트 자동매매 만들기] - [업비트 자동매매 C# winform] [프로젝트 생성][#2-1]

 

[2. API 요청]

업비트 Rest API요청시

1)인증이 필요하고 파라미터가 있는 경우

2)인증이 필요하고 파라미터가 없는 경우

3)인증이 필요없고 파라미터가 있는 경우

4)인증이 필요없고 파라미터가 없는 경우

위 4가지의 경우로 나눌 수 있습니다.

(인증 = 로그인이라고 생각하면 편함)

 

여기서 위 4가지를 전부 코딩하려면 번거롭더군요,,

인증이 필요없는 경우에도 인증하는 소스를 넣었더니 잘 동작하는 것을 확인할 수 있었습니다.

그러므로

1)인증이 필요하고 파라미터가 있는 경우

2)인증이 필요하고 파라미터가 없는 경우

이 두가지 경우만 놓고 코드를 작성했습니다.

 

1. NoParam, Param 클래스파일을 생성

 

2. NoParam.cs (파라미터가 없는 경우)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using System.IdentityModel.Tokens.Jwt;
using RestSharp;

namespace upbit.UpbitAPI {
    public class NoParam {

        private string upbitAccessKey;
        private string upbitSecretKey;

        private DateTime dt_1970_01_01 ;   //timestamp를 계산하기 위한 변수
        private const string baseUrl = "https://api.upbit.com";


        public NoParam(string upbitAccessKey, string upbitSecretKey) {
            //APIClass에서 받은 키를 입력
            this.upbitAccessKey = upbitAccessKey;  
            this.upbitSecretKey = upbitSecretKey;

            this.dt_1970_01_01 = new DateTime(1970,01,01);
        }

        public string Get(string path, Method method) {

            var tokenSb = JWT_NoParam();
            var token = tokenSb.ToString();

            tokenSb.Clear();
            tokenSb = null;

            var client = new RestClient(baseUrl);       // RestSharp 클라이언트 생성
            var request = new RestRequest(path, method); 
            request.AddHeader( "Content-Type", "application/json"); // 컨텐츠 타입이 json이라고 서버측에 알려줌
            request.AddHeader("Authorization", token); // 인증을 위해 JWT토큰을 넘겨줌

            token = null;

            var response = client.Execute(request); // 요청을 서버측에 보내 응답을 받음

            try {
                if (response.IsSuccessful) { // 응답을 받는데 성공한 경우
                    return response.Content;  // 응답받은 요청정보를 string형태로 넘겨준다.
                }
                else {
                    return null; // 응답을 받는데 실패시 null값을 반환
                }
            }
            catch {
                return null; // 오류시 null값을 반환
            }
        }


        public StringBuilder JWT_NoParam() {
            // 이 소스는 
            // https://docs.upbit.com/docs
            // 위 링크의 TABLE OF CONTENTS 에서
            // 가져왔습니다.
            TimeSpan diff = DateTime.Now - dt_1970_01_01;
            var nonce = Convert.ToInt64(diff.TotalMilliseconds);
            var payload = new JwtPayload {
                { "access_key", this.upbitAccessKey },
                { "nonce",  nonce  }
            };

            byte[] keyBytes = Encoding.Default.GetBytes(this.upbitSecretKey);
            var securityKey = new Microsoft.IdentityModel.Tokens.SymmetricSecurityKey(keyBytes);
            var credentials = new Microsoft.IdentityModel.Tokens.SigningCredentials(securityKey, "HS256"); // HMAC SHA256 방식의 줄임말
            var header = new JwtHeader(credentials);
            var secToken = new JwtSecurityToken(header, payload);

            var jwtToken = new JwtSecurityTokenHandler().WriteToken(secToken);

            StringBuilder returnStr = new StringBuilder();
            returnStr.Append("Bearer "); // 띄어쓰기 한칸 있어야함 주의!
            returnStr.Append(jwtToken);

            return returnStr;
        }
    }
}

 

 

 

 

 

 

 

3. Param.cs (파라미터가 있는 경우)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using System.Security.Cryptography;
using System.IdentityModel.Tokens.Jwt;
using RestSharp;

namespace upbit.UpbitAPI {
    public class Param {
        private string upbitAccessKey;
        private string upbitSecretKey;

        private DateTime dt_1970_01_01;   //timestamp를 계산하기 위한 변수
        private const string baseUrl = "https://api.upbit.com";


        public Param(string upbitAccessKey, string upbitSecretKey) {
            //APIClass에서 받은 키를 입력
            this.upbitAccessKey = upbitAccessKey;
            this.upbitSecretKey = upbitSecretKey;

            this.dt_1970_01_01 = new DateTime(1970, 01, 01);
        }

        public string Get(string path, Dictionary<string, string> parameters, Method method) {

            StringBuilder queryStringSb = GetQueryString(parameters);

            var tokenSb = JWT_param(queryStringSb.ToString()); // 입력받은 변수를 JWT토큰으로 변환
            var token = tokenSb.ToString();                            

            queryStringSb.Insert(0, "?");      // 링크에 ?를 붙임으로 파라미터를 사용한다는 의미
            queryStringSb.Insert(0, path);

            // 여기까지오면 queryString는
            // '/path?key1=value1&key2=value2 ....' 이러한 형태가 된다. 이것을 RestRequest에 넣어주면 된다.

            var client = new RestClient(baseUrl);       // RestSharp 클라이언트 생성
            var request = new RestRequest(queryStringSb.ToString(), method);
            request.AddHeader("Content-Type", "application/json");
            request.AddHeader("Authorization", token);

            queryStringSb.Clear(); queryStringSb = null;
            tokenSb.Clear(); tokenSb = null;
            parameters.Clear(); parameters = null;

            var response = client.Execute(request);

            try {
                if (response.IsSuccessful) {
                    return response.Content;
                }
                else {
                    return null;
                }
            }
            catch {
                return null;
            }

        }
        public StringBuilder GetQueryString(Dictionary<string, string> parameters) {
            // Dictionary 형태로 받은 key = value 형태를 
            // ?key1=value1&key2=value2 ... 형태로 만들어줌
            StringBuilder builder = new StringBuilder();
            foreach (KeyValuePair<string, string> pair in parameters) {
                builder.Append(pair.Key).Append("=").Append(pair.Value).Append("&");
            }

            if (builder.Length > 0) {
                builder.Length = builder.Length - 1; // 마지막 &를 제거하기 위함.
            }
            return builder;
        }
        public StringBuilder JWT_param(string queryString) {

            SHA512 sha512 = SHA512.Create();
            byte[] queryHashByteArray = sha512.ComputeHash(Encoding.UTF8.GetBytes(queryString));
            string queryHash = BitConverter.ToString(queryHashByteArray).Replace("-", "").ToLower();

            TimeSpan diff = DateTime.Now - dt_1970_01_01;
            var nonce = Convert.ToInt64(diff.TotalMilliseconds);

            var payload = new JwtPayload
                    {
                        { "access_key", this.upbitAccessKey },
                        { "nonce", nonce  },
                        { "query_hash", queryHash },
                        { "query_hash_alg", "SHA512" }
                    };

            byte[] keyBytes = Encoding.Default.GetBytes(this.upbitSecretKey);
            var securityKey = new Microsoft.IdentityModel.Tokens.SymmetricSecurityKey(keyBytes);
            var credentials = new Microsoft.IdentityModel.Tokens.SigningCredentials(securityKey, "HS256");
            var header = new JwtHeader(credentials);
            var secToken = new JwtSecurityToken(header, payload);

            var jwtToken = new JwtSecurityTokenHandler().WriteToken(secToken);

            StringBuilder returnStr = new StringBuilder();
            returnStr.Append("Bearer "); // 띄어쓰기 한칸 있어야함 주의!
            returnStr.Append(jwtToken);

            return returnStr;
        }


    }
}

 

4. APIClass.cs 에서

Param, NoParam Class를 선언해주면 RestAPI를 받아올 준비는 끝난다.

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace upbit.UpbitAPI {

    public class APIClass {

        private Param param;
        private NoParam noparam;

        public APIClass(string upbitAccessKey, string upbitSecretKey) {
            param = new Param(upbitAccessKey, upbitSecretKey);
            noparam = new NoParam(upbitAccessKey, upbitSecretKey);
        }

    }
}

 

 

 

다음글:

2021.12.14 - [업비트 자동매매 만들기] - [업비트 자동매매 C# winform] [API 요청하기][#2-3]

댓글