1 #-*- coding:utf-8 -*-
2 importrequests3 importhashlib4 importxmltodict5 importtime6 importrandom7 importstring8 importurllib29 importsys10
11
12 classWX_PayToolUtil():13 """微信支付工具"""
14
15 def __init__(self, APP_ID, MCH_ID, API_KEY, NOTIFY_URL):16 self._APP_ID = APP_ID #小程序ID
17 self._MCH_ID = MCH_ID ## 商户号
18 self._API_KEY =API_KEY19 self._UFDODER_URL = "https://api.mch.weixin.qq.com/pay/unifiedorder" #接口链接
20 self._NOTIFY_URL = NOTIFY_URL #异步通知
21
22 defgenerate_sign(self, param):23 '''生成签名'''
24 stringA = ''
25 ks =sorted(param.keys())26 #参数排序
27 for k inks:28 stringA += (k + '=' + param[k] + '&')29 #拼接商户KEY
30 stringSignTemp = stringA + "key=" +self._API_KEY31 #md5加密,也可以用其他方式
32 hash_md5 = hashlib.md5(stringSignTemp.encode('utf8'))33 sign =hash_md5.hexdigest().upper()34 returnsign35
36 '''
37 # python2另外一种实现方法38 def generate_sign(self, params):39 ret = []40 for k in sorted(params.keys()):41 if (k != 'sign') and (k != '') and (params[k] is not None):42 ret.append('%s=%s' % (k, params[k]))43 params_str = '&'.join(ret)44 params_str = '%(params_str)s&key=%(partner_key)s' % {'params_str': params_str, 'partner_key': key}45
46 reload(sys)47 sys.setdefaultencoding('utf8')48
49 params_str = hashlib.md5(params_str.encode('utf-8')).hexdigest()50 sign = params_str.upper()51 return sign52 '''
53
54 def getPayUrl(self, orderid, openid, goodsPrice, **kwargs):55 """向微信支付端发出请求,获取url"""
56 key =self._API_KEY57 nonce_str = ''.join(random.sample(string.letters + string.digits, 30)) #生成随机字符串,小于32位
58 params ={59 'appid': self._APP_ID, #小程序ID
60 'mch_id': self._MCH_ID, #商户号
61 'nonce_str': nonce_str, #随机字符串
62 "body": '测试订单', #支付说明
63 'out_trade_no': orderid, #生成的订单号
64 'total_fee': str(goodsPrice), #标价金额
65 'spbill_create_ip': "127.0.0.1", #小程序不能获取客户ip,web用socekt实现
66 'notify_url': self._NOTIFY_URL,67 'trade_type': "JSAPI", #支付类型
68 "openid": openid, #用户id
69 }70 #生成签名
71 params['sign'] =self.generate_sign(params)72
73 #python3一种写法
74 param = {'root': params}75 xml =xmltodict.unparse(param)76 response = requests.post(self._UFDODER_URL, data=xml.encode('utf-8'), headers={'Content-Type': 'text/xml'})77 #xml 2 dict
78 msg =response.text79 xmlmsg =xmltodict.parse(msg)80 #4. 获取prepay_id
81 if xmlmsg['xml']['return_code'] == 'SUCCESS':82 if xmlmsg['xml']['result_code'] == 'SUCCESS':83 prepay_id = xmlmsg['xml']['prepay_id']84 #时间戳
85 timeStamp =str(int(time.time()))86 #5. 五个参数
87 data ={88 "appId": self._APP_ID,89 "nonceStr": nonce_str,90 "package": "prepay_id=" +prepay_id,91 "signType": 'MD5',92 "timeStamp": timeStamp,93 }94 #6. paySign签名
95 paySign =self.generate_sign(data)96 data["paySign"] = paySign #加入签名
97 #7. 传给前端的签名后的参数
98 returndata99
100 #python2一种写法
101 '''
102 request_xml_str = ''103 for key, value in params.items():104 if isinstance(value, str):105 request_xml_str = '%s%s>' % (request_xml_str, key, value, key,)106 else:107 request_xml_str = '%s%s%s>' % (request_xml_str, key, value, key,)108 request_xml_str = '%s' % request_xml_str109
110 # 向微信支付发出请求,并提取回传数据111 res = urllib2.Request(self._UFDODER_URL, data=request_xml_str.encode("utf-8"))112 res_data = urllib2.urlopen(res)113 res_read = res_data.read()114 doc = xmltodict.parse(res_read)115 return_code = doc['xml']['return_code']116 if return_code == "SUCCESS":117 result_code = doc['xml']['result_code']118 if result_code == "SUCCESS":119 doc = doc['xml']120 data = {121 "appId": self._APP_ID,122 "nonceStr": nonce_str,123 "package": "prepay_id=" + doc["prepay_id"],124 "signType": 'MD5',125 "timeStamp": str(int(time.time())),126 }127 # paySign签名128 paySign = self.generate_sign(data)129 data["paySign"] = paySign # 加入签名130 return data131 else:132 err_des = doc['xml']['err_code_des']133 return err_des134 else:135 fail_des = doc['xml']['return_msg']136 return fail_des137 '''