最近公司项目需要做个支付,首先考虑的就是大众化的支付宝支付和微信支付,其中也遇见了一些坑,在这里就记录下来:
1:微信支付:
settings.py文件:WXKEY这是个坑,该key值为微信商户平台中的API秘钥,该秘钥为32位自己设置的,强烈建议使用md5加密自动生成,
生成地址:http://www.atool.org/hash.php#MD5,如输入abcd就能得到32位的字符,用该字符作为秘钥
WXAPPID='wx****************' WXMCHID='**********' WXKEY='*********************************' WXAPI = 'https://api.mch.weixin.qq.com/pay/unifiedorder'
views.py文件:
import random
import qrcode
import xml.etree.ElementTree as ET
import sys
reload(sys)
sys.setdefaultencoding('utf-8')
# 随机字符串
def createNoncestr(length = 32):
"""产生随机字符串,不长于32位"""
chars = "abcdefghijklmnopqrstuvwxyz0123456789"
strs = []
for x in range(length):
strs.append(chars[random.randrange(0, len(chars))])
return "".join(strs)
def formatBizQueryParaMap( paraMap, urlencode):
"""格式化参数,签名过程需要使用"""
slist = sorted(paraMap)
buff = []
for k in slist:
v = quote(paraMap[k]) if urlencode else paraMap[k]
buff.append("{0}={1}".format(k, v))
return "&".join(buff)
def getSign(obj):
"""生成签名"""
#签名步骤一:按字典序排序参数,formatBizQueryParaMap已做
String = formatBizQueryParaMap(obj, False)
#签名步骤二:在string后加入KEY
String = "{0}&key={1}".format(String,settings.WXKEY)
#签名步骤三:MD5加密
String = hashlib.md5(String).hexdigest()
#签名步骤四:所有字符转为大写
result_ = String.upper()
return result_
# 获取ip
def get_ip(request):
if request.META.has_key('HTTP_X_FORWARDED_FOR'):
ip = request.META['HTTP_X_FORWARDED_FOR']
else:
ip = request.META['REMOTE_ADDR']
return ip
# 返回二维码链接
def request_weixin(request,total_fee):
weixin_url = settings.WXAPI
total_fee = int(total_fee *100) #该数值单位为分;
body = 'XXXXXXXXXXXXXXXXXXXXXX'
nonce_str = createNoncestr()
out_trade_no = createID()
spbill_create_ip = get_ip(request)
parameters = {}
parameters['appid'] = settings.WXAPPID
parameters['mch_id'] = settings.WXMCHID
parameters['spbill_create_ip'] = spbill_create_ip
parameters['out_trade_no'] = out_trade_no
parameters['body'] = body
parameters['total_fee'] = total_fee
parameters['nonce_str'] = nonce_str
parameters['notify_url'] = '*****************************'
parameters['trade_type'] = 'NATIVE'
sign = getSign(parameters) #这里有个大坑,也可能是我太笨了,这个签名中的参数一定需要把所有请求的参数合在一起,也就是说下面这个xml中的标签有哪些就要加哪些
# 微信单位为分
xml = '''<xml>
<appid>%s</appid>
<body>%s</body>
<mch_id>%s</mch_id>
<nonce_str>%s</nonce_str>
<notify_url>*****************************</notify_url>
<out_trade_no>%s</out_trade_no>
<spbill_create_ip>%s</spbill_create_ip>
<total_fee>%s</total_fee>
<trade_type>NATIVE</trade_type>
<sign>%s</sign>
</xml> ''' % (settings.WXAPPID,body,settings.WXMCHID,nonce_str,out_trade_no,
spbill_create_ip,total_fee,sign)
data = urllib2.urlopen(weixin_url,xml).read()
xml_recv = ET.fromstring(data)
WeixinBill.objects.create(
result_code = xml_recv.find("return_code").text,
total_fee = total_fee,
out_trade_no = out_trade_no,
user_id = mem_info.id
)
code_url = xml_recv.find("code_url").text
#使用第三方库qrcode生成二维码
img = qrcode.make(code_url)
img_str = 'static/twocode/%s.png'%out_trade_no
img.save(img_str)
return "/%s"%img_str
# 微信支付异步通知,这里没有贴出验证签名,请自行补充
@csrf_exempt
def notify_weixin(request):
recv_xml = request.body
xml_recv = ET.fromstring(recv_xml)
return_code = xml_recv.find("return_code").text
return_xml=''
if return_code == 'SUCCESS':
try:
#这里可以做成功之后的操作
return_xml = '''
<xml>
<return_code><![CDATA[SUCCESS]]></return_code>
<return_msg><![CDATA[OK]]></return_msg>
</xml>'''
except Exception, e:
return_xml = '''
<xml>
<return_code><![CDATA[FAIL]]></return_code>
<return_msg><![CDATA[参数格式校验错误]]></return_msg>
</xml>'''
else:
return_xml = '''
<xml>
<return_code><![CDATA[FAIL]]></return_code>
<return_msg><![CDATA[参数格式校验错误]]></return_msg>
</xml>'''
return HttpResponse(return_xml)