-
Notifications
You must be signed in to change notification settings - Fork 8
/
version3.py
123 lines (106 loc) · 3.71 KB
/
version3.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
#-*- coding: utf-8 -*-
# 微信支付V3接口
import hashlib
from random import Random
import time
import xmltodict
import requests
config = {
'appId': '',
'Mchid': '',
'Key': '',
'notify_url': ''
}
def build_sign(params):
# 对所有传入参数按照字段名的 ASCII 码从小到大排序(字典序)
keys = params.keys()
keys.sort()
array = []
for key in keys:
# 值为空的参数不参与签名
if params[key] == None or params[key] == '':
continue
# sign不参与签名
if key == 'sign':
continue
array.append("%s=%s" % (key, params[key]))
# 使用 URL 键值对的格式拼接成字符串string1
string1 = "&".join(array)
# 在 string1 最后拼接上 key=Key(商户支付密钥)得到 stringSignTemp 字符串
stringSignTemp = string1 + '&key=' + config['Key']
# 对 stringSignTemp 进行 md5 运算,再将得到的字符串所有字符转换为大写
m = hashlib.md5(stringSignTemp.encode('utf-8'))
return m.hexdigest().upper()
def build_unifiedorder(params):
base_params = {
'appid': config['appId'],
'mch_id': config['Mchid'],
'nonce_str': generate_random_string(),
'trade_type': 'JSAPI',
'body': params['body'],
'attach': params['attach'], #any other params that need transfer from wx side
'out_trade_no': params['out_trade_no'],
'total_fee': params['total_fee'],
'spbill_create_ip': params['spbill_create_ip'],
'notify_url': config['notify_url'],
'openid': params['openid'] #if `trade_type` == `APP`, remove this line.
}
base_params['sign'] = build_sign(base_params)
return dict_to_xml(base_params)
def generate_random_string(randomlength=32):
str = ''
chars = 'abcdefghijklmnopqrstuvwxyz0123456789'
length = len(chars) - 1
random = Random()
for i in range(randomlength):
str += chars[random.randint(0, length)]
return str
def dict_to_xml(params):
xml_elements = ["<xml>",]
for (k, v) in params.items():
if str(v).isdigit():
xml_elements.append('<%s>%s</%s>' % (k, v, k))
else:
xml_elements.append('<%s><![CDATA[%s]]></%s>' % (k, v, k))
xml_elements.append('</xml>')
return ''.join(xml_elements)
def build_form_by_prepay_id(prepay_id):
base_params = {
'appid': config['appId'],
'partnerid': config['Mchid'],
'prepayid': prepay_id,
'timestamp': str(int(time.time())),
'noncestr': generate_random_string(),
'package': "Sign=WXPay",
#'signType': "MD5"
}
base_params['sign'] = build_sign(base_params)
return base_params
def build_form_by_params(params):
headers = {'Content-Type': 'application/xml'}
xml = build_unifiedorder(params).encode('utf-8')
response = requests.post('https://api.mch.weixin.qq.com/pay/unifiedorder', data=xml, headers=headers)
response.encoding = 'utf-8'
response_dict = xmltodict.parse(response.text)['xml']
if response_dict['return_code'] == 'SUCCESS':
return build_form_by_prepay_id(response_dict['prepay_id'])
def notify_string_to_params(string):
params = {}
key_value_array = string.split('&')
for item in key_value_array:
key, value = item.split('=')
params[key] = value
return params
def verify_notify_string(string):
params = notify_xml_string_to_dict(string)
notify_sign = params['sign']
del params['sign']
if build_sign(params) == notify_sign:
return True
return False
def notify_xml_string_to_dict(string):
xml_data = xmltodict.parse(string)['xml']
params = {}
for k in xml_data:
params[k] = xml_data[k]
return params