中币交易网api

import hashlib
import struct
import time
import requests

suc_codes = ["1000"]

DEBUG = True

errcode = {
    "1000": "success",
    "1001": "normal error",
    "1002": "internal error",
    "1003": "verify not passed",
    "1004": "fund security password locked",
    "1005": "fund security password not right",
    "1006": "real-name authentication verifying or not passed",
    "1009": "current api not in service",
    "2001": "RMB not sufficient",
    "2002": "BTC not sufficient",
    "2003": "LTC not sufficient",
    "2005": "ETH not sufficient",
    "2006": "ETC not sufficient",
    "2007": "BTS not sufficient",
    "2009": "balance not sufficient",
    "3001": "order not found",
    "3002": "invalid amount of money",
    "3003": "invalid count",
    "3004": "user not exists",
    "3005": "illegal argument",
    "3006": "IP error",
    "3007": "time expired",
    "3008": "trade history not found",
    "4001": "API locked or not opened",
    "4002": "requests too frequently"
}

ORDER_TYPE_BUY = 1
ORDER_TYPE_SELL = 0

ORDER_STATUS_CANCELED = 1
ORDER_STATUS_DONE = 2
ORDER_STATUS_WAITING = 3

# 获取已开启的市场信息,包括价格、数量小数点位数
TPL_MARKETS = 'http://api.zb.com/data/v1/markets'
# 全币种行情
TPL_ALL_MARKET = 'http://api.zb.cn/data/v1/allTicker'
# 行情
TPL_MARKET = 'http://api.zb.com/data/v1/ticker?market={MARKET}'
# 市场深度
TPL_DEPTH = 'http://api.zb.com/data/v1/depth?market={MARKET}&size={SIZE}'
# 历史成交
TPL_TRADES = 'http://api.zb.com/data/v1/trades?market={MARKET}'
# k线
TPL_KLINE = 'http://api.zb.com/data/v1/kline?market={MARKET}'

# 委托下单
URL_ORDER = 'https://trade.zb.com/api/order'
# 取消委托
URL_CANCEL_ORDER = 'https://trade.zb.com/api/cancelOrder'
# 获取委托买单或卖单
URL_GET_ORDER = 'https://trade.zb.com/api/getOrder'
# 获取多个委托买单或卖单,每次请求返回10条记录
URL_GET_ORDERS = 'https://trade.zb.com/api/getOrders'
# (新)获取多个委托买单或卖单,每次请求返回pageSize<100条记录
URL_GET_ORDERS_NEW = 'https://trade.zb.com/api/getOrdersNew'
# 与getOrdersNew的区别是取消tradeType字段过滤,可同时获取买单和卖单,每次请求返回pageSize10条记录
URL_GET_ORDERS_IGNORE_TRADE_TYPE = 'https://trade.zb.com/api/getOrdersIgnoreTradeType'
# 获取未成交或部份成交的买单和卖单,每次请求返回pageSize<=10条记录
URL_GET_UNFINISHED_ORDERS_IGNORE_TRADE_TYPE = 'https://trade.zb.com/api/getUnfinishedOrdersIgnoreTradeType'
# 获取用户信息
URL_GET_ACCOUNT_INFO = 'https://trade.zb.com/api/getAccountInfo'
# 获取用户充值地址
URL_GET_USER_ADDRESS = 'https://trade.zb.com/api/getUserAddress'
# 获取用户认证的提现地址
URL_GET_WITHDRAW_ADDRESS = 'https://trade.zb.com/api/getWithdrawAddress'
# 获取数字资产提现记录
URL_GET_WITHDRAW_RECORD = 'https://trade.zb.com/api/getWithdrawRecord'
# 获取数字资产充值记录
URL_GET_CHARGE_RECORD = 'https://trade.zb.com/api/getChargeRecord'
# 提现
URL_WITHDRAW = 'https://trade.zb.com/api/withdraw'

URL_doTransferFunds = 'https://trade.zb.cn/api/doTransferFunds'


class ZApi:
    def __init__(self, access_key, secret_key):
        """
        opened markets and status, format:
            {
                "btc_usdt": {
                    "amountScale": 4,
                    "priceScale": 2
                },
                "ltc_usdt": {
                    "amountScale": 3,
                    "priceScale": 2
                }
                ...
            }
        """
        self._access_key_ = access_key
        self._secret_key_ = secret_key
        self._markets_ = self.markets()
        if len(self._markets_) < 1:
            raise Exception("Get markets status failed")

    # 提交请求
    def get(self, url):
        while True:
            try:
                r = requests.get(url)
            except Exception:
                time.sleep(0.5)
                continue
            if r.status_code != 200:
                time.sleep(0.5)
                continue
            r_info = r.json()
            r.close()
            return r_info

    # 查看是否有相关market
    def check_market_code(self, market):
        if not market:
            return False
        if market not in self._markets_:
            return False
        else:
            return True

    # 获取已开启的市场信息,包括价格、数量小数点位数
    def markets(self):
        """
        markets data, result format:
            {
                "btc_usdt": {
                    "amountScale": 4,
                    "priceScale": 2
                },
                "ltc_usdt": {
                    "amountScale": 3,
                    "priceScale": 2
                }
                ...
            }
        :return: result data of markets
        """
        url = TPL_MARKETS
        return self.get(url)

    # 全币种行情
    def all_ticker(self):
        """
        ticker data, result format:
            {
                "ticker": {
                    "vol": "40.463",
                    "last": "0.899999",
                    "sell": "0.5",
                    "buy": "0.225",
                    "high": "0.899999",
                    "low": "0.081"
                },
                "date": "1507875747359"
            }
        :param market: market code string
        :return: ticker result
        """
        url = TPL_ALL_MARKET
        return self.get(url)

    # 行情
    def ticker(self, market):
        """
        ticker data, result format:
            {
                "ticker": {
                    "vol": "40.463",
                    "last": "0.899999",
                    "sell": "0.5",
                    "buy": "0.225",
                    "high": "0.899999",
                    "low": "0.081"
                },
                "date": "1507875747359"
            }
        :param market: market code string
        :return: ticker result
        """
        url = TPL_MARKET.format(MARKET=market)
        return self.get(url)

    # 深度
    def depth(self, market, size):
        """
        depth data of specific market, result format:
            {
                "asks": [
                    [
                        83.28,
                        11.8
                    ]...
                ],
                "bids": [
                    [
                        81.91,
                        3.65
                    ]...
                ],
                "timestamp" : timestamp
            }
        :param market: market code string
        :param size: depth size
        :return: result depth data
        """
        url = TPL_DEPTH.format(MARKET=market, SIZE=str(size))
        return self.get(url)

    # 历史成交
    def trades(self, market):
        """
        trade history, result format:
            [
                {
                    "amount": 0.541,
                    "date": 1472711925,
                    "price": 81.87,
                    "tid": 16497097,
                    "trade_type": "ask",
                    "type": "sell"
                }...
            ]
        :return: trade history data
        """
        url = TPL_TRADES.format(MARKET=market)
        return self.get(url)

    # k 线
    def kline(self, market):
        """
        kline data, result format:
            {
                "data": [
                    [
                        1472107500000,
                        3840.46,
                        3843.56,
                        3839.58,
                        3843.3,
                        492.456
                    ]...
                ],
                "moneyType": "btc",
                "symbol": "ltc"
            }
        :param market: market code
        :return: kline data
        """
        url = TPL_KLINE.format(MARKET=market)
        return self.get(url)

    # 委托下单
    def order(self, market, type, amount, price):
        """
        order api, result format:
            {
                "code": "1000",
                "message": "***",
                "id": "20131228361867"
            }
        :param market: currency
        :param type: ORDER_TYPE_BUY or ORDER_TYPE_SELL
        :param amount: order amount
        :param price: order price
        :return: order result
        """
        params = 'accesskey=%s&amount=%s&currency=%s&method=order&price=%s&tradeType=%s' % (
            self._access_key_, amount, market, price, type)
        return self.call_api(url=URL_ORDER, params=params)

    # 取消委托
    def cancel_order(self, market, order_id):
        """
        cancel an order, result format:
            {
                "code": "1000",
                "message": "***"
            }
        :param market: currency
        :param order_id: order id
        :return: result
        """
        params = 'accesskey=%s&currency=%s&id=%s&method=cancelOrder' % (self._access_key_, market, order_id)
        return self.call_api(url=URL_CANCEL_ORDER, params=params)

    # 取消所有订单
    def cancel_allorder(self, market, page_index=1, page_size=5):
        flag = False
        orders = self.get_unfinished_orders_ignore_trade_type(market, page_index, page_size)
        # print('order',orders)
        if isinstance(orders, list) and len(orders) > 0 and 'id' in orders[0].keys():
            flag = True
        while flag:
            time.sleep(0.1)
            for order in orders:
                # print(market,orders)
                self.cancel_order(market, order['id'])
            orders = self.get_unfinished_orders_ignore_trade_type(market, page_index, page_size)
            if isinstance(orders, list) and len(orders) > 0 and 'id' in orders[0].keys():
                flag = True
            else:
                print('%s撤销所有订单完成!返回%s:' % (market, orders))
                flag = False

    # 获取委托买单或卖单
    def get_order(self, market, order_id):
        """
        get order detail, result format:
            {
                "currency": "btc",
                "id": "20150928158614292",
                "price": 1560,
                "status": 3,
                "total_amount": 0.1,
                "trade_amount": 0,
                "trade_price" : 6000,
                "trade_date": 1443410396717,
                "trade_money": 0,
                "type": 0,
            }
        :param market: currency
        :param order_id: order id
        :return: result
        """
        params = 'accesskey=%s&currency=%s&id=%s&method=getOrder' % (self._access_key_, market, order_id)
        return self.call_api(url=URL_GET_ORDER, params=params)

    # 获取多个委托买单或卖单,每次请求返回10条记录
    def get_orders(self, market, page, type):
        """
        get multiple orders, result format:
            [
                {
                    "currency": "btc",
                    "id": "20150928158614292",
                    "price": 1560,
                    "status": 3,
                    "total_amount": 0.1,
                    "trade_amount": 0,
                    "trade_price" : 6000,
                    "trade_date": 1443410396717,
                    "trade_money": 0,
                    "type": 0
                }...
            ]
        :param market: currency
        :param page: page index
        :param type: order type
        :return: result
        """
        params = 'accesskey=%s&currency=%s&method=getOrders&pageIndex=%s&tradeType=%s' % (
            self._access_key_, market, page, type)
        return self.call_api(url=URL_GET_ORDERS, params=params)

    # (新)获取多个委托买单或卖单,每次请求返回pageSize<100条记录
    def get_orders_new(self, market, page_index, page_size, type):
        """
        get multiple orders, result format same as get_orders
        :param market: currency
        :param page_index: page index
        :param page_size: page size
        :param type: order type
        :return: result
        """
        params = 'accesskey=%s&currency=%s&method=getOrdersNew&pageIndex=%s&pageSize=%s&tradeType=%s' % (
            self._access_key_, market, page_index, page_size, type)
        return self.call_api(url=URL_GET_ORDERS_NEW, params=params)

    # 与getOrdersNew的区别是取消tradeType字段过滤,可同时获取买单和卖单,每次请求返回pageSize10条记录
    def get_orders_ignore_tader_type(self, market, page_index, page_size):
        """
        get multiple orders ignore type, result format same as get_orders
        :param market: currency
        :param page_index: page index
        :param page_size: page size
        :return: result
        """
        params = 'accesskey=%s&currency=%s&method=getOrdersIgnoreTradeType&pageIndex=%s&pageSize=%s' % (
            self._access_key_, market, page_index, page_size)
        return self.call_api(url=URL_GET_ORDERS_IGNORE_TRADE_TYPE, params=params)

    # 获取未成交或部份成交的买单和卖单,每次请求返回pageSize<=10条记录
    def get_unfinished_orders_ignore_trade_type(self, market, page_index, page_size):
        """
        get multiple unfinished orders ignore type, result format same as get_orders
        :param market: currency
        :param page_index: page index
        :param page_size: page size
        :return: result
        """
        params = 'accesskey=%s&currency=%s&method=getUnfinishedOrdersIgnoreTradeType&pageIndex=%s&pageSize=%s' % (
            self._access_key_, market, page_index, page_size)
        # print(params)
        return self.call_api(url=URL_GET_UNFINISHED_ORDERS_IGNORE_TRADE_TYPE, params=params)

    # 主子账号内部转账
    def zhuanzhang_zi(self, amount, currency, fromUerName, toUserName):
        """
        get multiple unfinished orders ignore type, result format same as get_orders
        :param market: currency
        :param page_index: page index
        :param page_size: page size
        :return: result
        """
        params = 'accesskey=%s&amount=%s&currency=%s&fromUserName=%s&method=doTransferFunds&toUserName=%s' % (
            self._access_key_, amount, currency, fromUerName, toUserName)
        return self.call_api(url='https://trade.zb.cn/api/doTransferFunds', params=params)

    # 获取子账号列表
    def huoquzizhanghao(self):
        """:
        """
        # params = 'accesskey=%s&method=getAccountInfo' % self._access_key_
        params = 'accesskey=%s&method=getSubUserList' % self._access_key_

        return self.call_api(url='https://trade.zb.cn/api/getSubUserList', params=params)

    # 创建子账号
    def chuangjianzi(self):
        """:
        """
        # params = 'accesskey=%s&method=getAccountInfo' % self._access_key_
        # params = 'accesskey=%s&method=getSubUserList' % self._access_key_
        params = 'accesskey=%s&memo=%s&password=%s&method=addSubUser&subUserName=ceshi11' % (
            self._access_key_, 'ceshi11', '1234qwer')
        return self.call_api(url='https://trade.zb.cn/api/addSubUser', params=params)

    # 获取用户信息
    def get_account_info(self):
        """
        get account information, result format:
            {
                "result": {
                    "coins": [
                        {
                            "freez": "0.00000000",
                            "enName": "BTC",
                            "unitDecimal": 8,
                            "cnName": "BTC",
                            "unitTag": "*",
                            "available": "0.00000000",
                            "key": "btc"
                        },
                        {
                            "freez": "0.00000000",
                            "enName": "LTC",
                            "unitDecimal": 8,
                            "cnName": "LTC",
                            "unitTag": "*",
                            "available": "0.00000000",
                            "key": "ltc"
                        },
                       ...
                    ],
                    "base": {
                        "username": "134150***",
                        "trade_password_enabled": true,
                        "auth_google_enabled": false,
                        "auth_mobile_enabled": true
                    }
                }
            }
        :return: result
        """
        params = 'accesskey=%s&method=getAccountInfo' % self._access_key_
        return self.call_api(url=URL_GET_ACCOUNT_INFO, params=params)

    # 获取用户充值地址
    def get_user_address(self, currency):
        """
        get user address, result format:
            {
                "code": 1000,
                "message": {
                    "des": "success",
                    "isSuc": true,
                    "datas": {
                        "key": "0x0af7f36b8f09410f3df62c81e5846da673d4d9a9"
                    }
                }
            }
        :param currency: currency
        :return: result
        """
        # currency 当前的货币,如btc
        params = 'accesskey=%s&currency=%s&method=getUserAddress' % (self._access_key_, currency)
        return self.call_api(url=URL_GET_USER_ADDRESS, params=params)

    # 获取用户认证的提现地址
    def get_withdraw_address(self, currency):
        """
        get withdraw address, result format:
            {
                "code": 1000,
                "message": {
                    "des": "success",
                    "isSuc": true,
                    "datas": {
                        "key": "0x0af7f36b8f09410f3df62c81e5846da673d4d9a9"
                    }
                }
            }
        :param currency: currency
        :return: result
        """
        params = 'accesskey=%s&currency=%s&method=getWithdrawAddress' % (self._access_key_, currency)
        return self.call_api(url=URL_GET_WITHDRAW_ADDRESS, params=params)

    # 获取数字资产提现记录
    def get_withdraw_record(self, currency, page_index, page_size):
        """
        get withdraw record, result format:
            {
                "code": 1000,
                "message": {
                    "des": "success",
                    "isSuc": true,
                    "datas": {
                        "list": [
                            {
                                "amount": 0.01,
                                "fees": 0.001,
                                "id": 2016042556231,
                                "manageTime": 1461579340000,
                                "status": 3,
                                "submitTime": 1461579288000,
                                "toAddress": "14fxEPirL9fyfw1i9EF439Pq6gQ5xijUmp"
                            }...
                        ],
                        "pageIndex": 1,
                        "pageSize": 10,
                        "totalCount": 4,
                        "totalPage": 1
                    }
                }
            }
        :param currency:
        :param page_index:
        :param page_size:
        :return:
        """
        params = 'accesskey=%s&currency=%s&method=getWithdrawRecord&pageIndex=%s&pageSize=%s' % (
            self._access_key_, currency, page_index, page_size)
        return self.call_api(url=URL_GET_WITHDRAW_RECORD, params=params)

    # 获取数字资产充值记录
    def get_charge_record(self, currency, page_index, page_size):
        """
        get charge record, result format:
            {
                "code": 1000,
                "message": {
                    "des": "success",
                    "isSuc": true,
                    "datas": {
                        "list": [
                            {
                                "address": "1FKN1DZqCm8HaTujDioRL2Aezdh7Qj7xxx",
                                "amount": "1.00000000",
                                "confirmTimes": 1,
                                "currency": "BTC",
                                "description": "***",
                                "hash": "7ce842de187c379abafadd64a5fe66c5c61c8a21fb04edff9532234a1dae6xxx",
                                "id": 558,
                                "itransfer": 1,
                                "status": 2,
                                "submit_time": "2016-12-07 18:51:57"
                            }...
                        ],
                        "pageIndex": 1,
                        "pageSize": 10,
                        "total": 8
                    }
                }
            }
        :param currency: currency
        :param page_index: page index
        :param page_size: page size
        :return: result
        """
        params = 'accesskey=%s&currency=%s&method=getChargeRecord&pageIndex=%s&pageSize=%s' % (
            self._access_key_, currency, page_index, page_size)
        return self.call_api(url=URL_GET_CHARGE_RECORD, params=params)

    # 提现
    def withdraw(self, currency, amount, fees, itransfer, addr, pwd):
        """
        withdraw coins, result format:
            {
                "code": 1000,
                "message": "success",
                "id": "***"
            }
        :param currency: currency
        :param amount: amount
        :param fees: fees
        :param itransfer: itransfer
        :param addr: receive address
        :param pwd: safe password of current account
        :return: result
        """
        # amount:数量 ;fees:手续费; itransfer:; receiveAddr:接收地址;safePwd:资金安全密码
        params = 'accesskey=%s&amount=%s&currency=%s&fees=%s&itransfer=%s&method=withdraw&receiveAddr=%s&safePwd=%s' % (
            self._access_key_, amount, currency, fees, itransfer, addr, pwd)
        return self.call_api(url=URL_WITHDRAW, params=params)

    def call_api(self, url, params=''):
        full_url = url
        if params:
            sha_secret = self.digest(self._secret_key_)
            sign = self.hmac_sign(params, sha_secret)
            req_time = int(round(time.time() * 1000))
            params += '&sign=%s&reqTime=%d' % (sign, req_time)
            full_url += '?' + params
        result = {}
        while True:
            try:
                r = requests.get(full_url, timeout=2)
            except Exception:
                time.sleep(0.5)
                continue
            if r.status_code != 200:
                time.sleep(0.5)
                r.close()
                continue
            else:
                result = r.json()
                r.close()
                break
        return result

    @staticmethod
    def fill(value, lenght, fill_byte):
        # 进行值填充,符合则返回原值,否则填充相应的字节
        if len(value) >= lenght:
            return value
        else:
            fill_size = lenght - len(value)
        return value + chr(fill_byte) * fill_size

    @staticmethod
    def xor(s, value):
        # 与value进行按位异或,得到一个新的字符串
        slist = list(s.decode('utf-8'))
        for index in range(len(slist)):
            slist[index] = chr(ord(slist[index]) ^ value)
        return "".join(slist)

    def hmac_sign(self, arg_value, arg_key):
        # 得到签名
        keyb = struct.pack("%ds" % len(arg_key), arg_key.encode('utf-8'))
        # 获取参数值
        value = struct.pack("%ds" % len(arg_value), arg_value.encode('utf-8'))
        # 根据相应的十六进制按位异或得到新的字符串
        k_ipad = self.xor(keyb, 0x36)
        k_opad = self.xor(keyb, 0x5c)
        # 填充字符
        k_ipad = self.fill(k_ipad, 64, 54)
        k_opad = self.fill(k_opad, 64, 92)
        # 对k_ipad进行hash加密
        m = hashlib.md5()
        m.update(k_ipad.encode('utf-8'))
        m.update(value)
        dg = m.digest()
        # 进行双重hash加密
        m = hashlib.md5()
        m.update(k_opad.encode('utf-8'))
        subStr = dg[0:16]
        m.update(subStr)
        dg = m.hexdigest()
        return dg

    # hash加密,得到秘钥
    def digest(self, arg_value):
        value = struct.pack("%ds" % len(arg_value), arg_value.encode('utf-8'))
        h = hashlib.sha1()
        h.update(value)
        dg = h.hexdigest()
        return dg


猜你喜欢

转载自blog.csdn.net/weixin_43958804/article/details/88745973