最近公司项目需要做个支付,首先考虑的就是大众化的支付宝支付和微信支付,其中也遇见了一些坑,在这里就记录下来:

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)