这两天在调试一个交易所Aofex的API认证时,发现利用说明文档获得签名认证后,
def sign(Token,secret_key,Nonce,data=dict()):
tmp =list()
tmp.append(Token)
tmp.append(secret_key)
tmp.append(Nonce)
for d, x in data.items():
tmp.append(str(d) +"="+str(x))
tmp = (''.join(sorted(tmp)))
tmp = tmp.encode("utf8")
return hashlib.sha1(tmp).hexdigest()
再来获取用户资产
AF_URL ='https://openapi.aofex.com’
timestamp =int(time.time())
Nonce =str(timestamp)+'_'+str(int(random.uniform(10000,99999)))# 随机数,客户端每次请求随机生成字符。生成规则,时间戳_5位随机字母或数字
url = AF_URL +'/openApi/wallet/list'
data = {'currency':'ETH','show_all':'1'}
signature = sign(Token,secret_key,Nonce,data)
header = {'Nonce': Nonce,
'Token': Token,
'Signature': signature}
balance = request.get(url,data= data,headers=header)
print(balance)
无论如何都不成功,一直报错'api signature not valid’,根据这个提示,那就是认证不成功了,就从第一段程序中找各种原因。
来回试,反复试不行,找交易所客服咨询,他们给我一个验证签名是否正确的POST网址请求,我去验证后发现我自己与他们提供的方式计算的也不一样。
这时我更加怀疑我的认证有问题,但反复调试后还是不行。后来我就用他们直接验证过的签名signature直接调用,发现还是无法获取资产,这里我就开始怀疑其它问题了。
后来从他们网站提供认证的Nodejs示例中找到这么一条:url: 'https://openapi.aofex.com' + path + "?" + postMan,其中postMan是请求参数。
那意味着需要在url中添加请求参数了,按照这个思路我在请求资产中把参数设为空data={},然后把url后面加个问号?,一试果然成功了。
那问题就变成需要把请求参数data传到url中。传递的要求是在原始url中加?后再加请求参数,并以&作为分隔符。就是要把data = {'currency': 'ETH','show_all':'1'}变成currency=ETH&show_all=1,然后组成这样的url,https://openapi.aofex.com?currency=ETH&show_all=1
那么问题已经清楚了,怎么样把这个字典{'currency': 'ETH','show_all':'1’}中的元素变成currency=ETH&show_all=1?注意这里还需要排序。
Python中list,dict中元素排序拼接问题挺糊涂,这次要统一学习整理下,直接上例子吧,解释也在例子中
问题列表:
如何对列表中元素排序
如何对列表中元素拼接,如何加字符比如&
如何把字典中元素转换为列表元素
'''列表中元素排序,拼接'''
tmp = ['a','b','123','currency=ETH','show_all=1']
tmp =sorted(tmp)# 每个元素进行排序,结果['123', 'a', 'b', 'currency=ETH', 'show_all=1']
# tmp = (''.join(tmp)) # 排序后的元素连接到一起,什么都不加,结果123abcurrency=ETHshow_all=1
# print(tmp)
tmp = ('&'.join(tmp))# 排序后的元素连接到一起,加&,结果123&a&b¤cy=ETH&show_all=1
print(tmp)
'''字典中元素转换为列表元素'''
data = {'currency':'ETH',
'show_all':'1'}
ford,xindata.items():# 对字典中key:value取值
print(str(d) +"="+str(x))# 这里用字符=连接,结果 currency=ETH show_all=1
# tmp.append(str(d) + "=" + str(x))
'''列表,字典混合排序,拼接等操作’''
tmp = ['a','b','123']
data = {'currency':'ETH',
'show_all':'1'}
ford,xindata.items():
# print(str(d) + "=" + str(x)) # 结果 currency=ETH show_all=1
tmp.append(str(d) +"="+str(x))# 字典元素转换为列表元素,并添加到原来的列表中
print(tmp)# ['a', 'b', '123', 'currency=ETH', 'show_all=1']
# tmp = (''.join(sorted(tmp))) # 123abcurrency=ETHshow_all=1
tmp = ('&'.join(sorted(tmp)))# 123&a&b¤cy=ETH&show_all=1
print(tmp)
'''如何从data = {'currency': 'ETH','show_all':'1'}变成currency=ETH&show_all=1'''
tmp = []
data = {'currency':'ETH',
'show_all':'1'}
ford,xindata.items():
# print(str(d) + "=" + str(x)) # 结果 currency=ETH show_all=1
tmp.append(str(d) +"="+str(x))
print(tmp)# ['currency=ETH', 'show_all=1']
tmp = ('&'.join(sorted(tmp))) # 拼接
print(tmp)
通过上面的例子,前面的问题也清楚了,那我只要在AOFEX获取资产的函数中更新下url就行了
AF_URL ='https://openapi.aofex.com’
timestamp =int(time.time())
Nonce =str(timestamp)+'_'+str(int(random.uniform(10000,99999)))# 随机数,客户端每次请求随机生成字符。生成规则,时间戳_5位随机字母或数字
url = AF_URL +'/openApi/wallet/list'
data = {'currency':'ETH','show_all':'1'}
signature = sign(Token,secret_key,Nonce,data)
'''如何从data = {'currency': 'ETH','show_all':'1'}变成currency=ETH&show_all=1'''
tmp = []
ford,xindata.items():
# print(str(d) + "=" + str(x)) # 结果 currency=ETH show_all=1
tmp.append(str(d) +"="+str(x))
# print(tmp) # ['currency=ETH', 'show_all=1']
tmp = ('&'.join(sorted(tmp)))
url = url +'?'+ tmp
header = {'Nonce': Nonce,
'Token': Token,
'Signature': signature}
balance =request.get(url,data= data,headers=header)
print(balance)
到这里似乎问题已经解决了,但感觉哪里不对,balance =request.get(url,data= data,headers=header)中data传到了url,那data不就没用了吗?
于是继续查get(url, params=None, **kwargs)发现原始函数中是params而不是data,原来我用错了,于是把data=data改成params=data运行下没有返回错误,但也没有返回余额,这这这?
到底params=与data=啥区别?
继续搜索发现:
当发起一次GET请求时,params参数会以url string的形式进行传递。即?后的字符串则为其请求参数,并以&作为分隔符。
而data, json不会以url string的形式进行传递
我的天,原来是这样,我前面搞的字典中元素转化为列表再拼接白搞了,这其实就是params干的事,于是我把更新url那一段去掉,把最开始的data=data改成params=data,一切万事大吉了。
AF_URL ='https://openapi.aofex.com’
timestamp =int(time.time())
Nonce =str(timestamp)+'_'+str(int(random.uniform(10000,99999)))# 随机数,客户端每次请求随机生成字符。生成规则,时间戳_5位随机字母或数字
url = AF_URL +'/openApi/wallet/list'
data = {'currency':'ETH','show_all':'1'}
signature = sign(Token,secret_key,Nonce,data)
header = {'Nonce': Nonce,
'Token': Token,
'Signature': signature}
balance = request.get(url,params= data,headers=header)
print(balance)