刚才在shell中敲代码的时候,习惯性地用tab键去补全,然后就一直报错,所以以后记得不要在vim编写代码的时候去用tab补全。
然后现在是总结一下在生成两个接口数据时使用到的一些辅助函数,因为我自己是先开发微信支付接口使用的,所以先总结微信支付的函数,首先是生成随机字符串,我自己是先生成一个26个小写字母和0到9的数字的字符串,然后从中随机挑选32个字符加入一个list,然后用join联合函数直接组成随机字符串,代码如下:
def nonce_str(self):
# 生成随机字符
chars = 'abcdefghigklmnopqrstuvwxyz0123456789'
strs = []
for x in range(32):
strs.append(chars[random.randrange(0, len(chars))])
return "".join(strs)
然后就是微信支付的计算签名,首先是将已有的键值对按照ascii排序,然后生成型如a=b&c=d的形式,接着将微信提供的商户的密钥也以这种键值对的形式加入到组合字符串当中,然后利用hashlib中的MD5摘要算法对字符串进行加密,然后将生成的签名大写,返回就可以了。
def sign(self, params):
# 计算签名
params_str = "&".join("{0}={1}".format(k, params[k]) for k in sorted(params) if k != 'sign' and params[k])
params_str = '{0}&key={1}'.format(params_str, self.key)
params_str = hashlib.md5(params_str.encode('utf-8')).hexdigest()
signvalue = params_str.upper()
return signvalue
因为微信支付只接收xml字符串,所以还需要自己生成xml信息,我采用数组的方式将其对应值生成了数组中的一个元素,最终使用join函数将数组转换为字符串。
def arrayToXml(self, arr):
"""array转xml,生成订单信息"""
xml = ["<xml>"]
for k, v in arr.items():
xml.append("<{0}>{1}</{0}>".format(k, v))
xml.append("</xml>")
return "".join(xml)
相应的,微信返回的信息是xml格式的,所以为了查看返回信息,我是需要去转换格式的,然后我用的是python自带的xml.etree.ElementTree,调用函数的fromstring方法,对xml信息进行解析。
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import xml.etree.ElementTree as ET
def xmlToArray(self, xml):
"""将xml转为array"""
array_data = {}
root = ET.fromstring(xml)
for child in root:
value = child.text
array_data[child.tag] = value
return array_data
然后微信支付的退款接口是需要双向证书验证的,所以我使用了pycurl模块,在我的另一篇随笔中有专门的介绍,然后微信验证还有验证签名和处理回传信息乱码两个问题,验证签名的思路就是把回传的信息进行重新签名,然后拿出来与回传信息中的签名作对比,就可以决定时返回True还是False了。修复回传信息乱码我是直接将回传数据写成字节形式,然后再用utf-8解码。
支付宝接口相对来说就有点不一样了,不过大致思路还是一样的,也是按照相应的要求去生成订单信息。首先支付宝除了公共数据外每一个订单biz_content,所以就要先进行排序,对于参数中某些类型是字典的元素,要利用json的dumps方法将其转变为字符串,最终返回一个排序好了的list,其中每个元素为一个元组。
def ordered_data(self, data):
for k, v in data.items():
if isinstance(v, dict):
data[k] = json.dumps(v, separators=(',', ':'))
return sorted([(k, v) for k, v in data.items()])
然后生成订单信息就和微信支付差不多了,不过签名的方式是完全不一样的,生成签名的方法可以查看支付宝开放文档。