1.微信商户平台申请(具体流程参考网站内给出的步骤):
https://pay.weixin.qq.com/index.php/core/home/login?return_url=%2F
2.公众号、商户号
class WeChartPay(object):
def __init__(
self,
appid,
mch_id,
spbill_create_ip,
notify_url,
body,
detail,
trade_type
):
self.appid = appid # APPID
self.mch_id = mch_id # 商户号
self.spbill_create_ip = spbill_create_ip # 自己服务器地址
self.notify_url = notify_url # 回调地址
self.body = body # 商家描述
self.detail = detail # 商品描述
self.trade_type = trade_type # 扫码支付类型
def build_data_dict(self, out_trade_no, total_fee):
data_dict = {
'appid': self.appid,
'mch_id': self.mch_id,
'nonce_str': self.random_str(), # 随机字符串
'out_trade_no': out_trade_no, # 订单编号
'total_fee': total_fee, # 订单总金额
'spbill_create_ip': self.spbill_create_ip, # 自己服务器的IP地址
'notify_url': self.notify_url, # 回调地址,微信支付成功后会回调这个url,告知商户支付结果
'body': self.body, # 商品描述
'detail': self.detail, # 商品描述
'trade_type': self.trade_type, # 扫码支付类型
}
return data_dict
def get_sign(self, data_dict, key):
"""
签名函数
:param data_dict: 需要签名的参数,格式为字典
:param key: 密钥 ,即上面的API_KEY
:return: 字符串
"""
params_list = sorted(data_dict.items(), key=lambda e: e[0], reverse=False) # 参数字典倒排序为列表
params_str = "&".join(u"{}={}".format(k, v) for k, v in params_list) + '&key=' + key
# 组织参数字符串并在末尾添加商户交易密钥
md5 = hashlib.md5() # 使用MD5加密模式
md5.update(params_str.encode('utf-8')) # 将参数字符串传入
sign = md5.hexdigest().upper() # 完成加密并转为大写
return sign
def random_str(self, randomlength=8):
"""
生成随机字符串
:param randomlength: 字符串长度
:return:
"""
strs = ''
chars = 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz0123456789'
length = len(chars) - 1
random = Random()
for i in range(randomlength):
strs += chars[random.randint(0, length)]
return strs
def trans_dict_to_xml(self, data_dict):
"""
定义字典转XML的函数
:param data_dict:
:return:
"""
data_xml = []
for k in sorted(data_dict.keys()): # 遍历字典排序后的key
v = data_dict.get(k) # 取出字典中key对应的value
if k == 'detail' and not v.startswith('): # 添加XML标记
v = ''.format(v)
data_xml.append('<{key}>{value}{key}>'.format(key=k, value=v))
return '{} '.format(''.join(data_xml)) # 返回XML
def trans_xml_to_dict(self, data_xml):
"""
定义XML转字典的函数
:param data_xml:
:return:
"""
soup = BeautifulSoup(data_xml, features='xml')
xml = soup.find('xml') # 解析XML
if not xml:
return {}
data_dict = dict([(item.name, item.text) for item in xml.find_all()])
return data_dict
# 获取一个WeChartPay对象
def get_wecpay_object(uid):
wecpay = WeChartPay(
appid=WeChartPayConfig.app_id,
mch_id=WeChartPayConfig.mch_id,
spbill_create_ip=WeChartPayConfig.create_ip,
notify_url=WeChartPayConfig.notify_url+uid+'/',
body='xxx', # 可写商户名称或收款方
detail='xxxx', # 可写订单名或商品名
trade_type='NATIVE'
)
return wecpay
# 微信充值
def weChart_pay(request,uid):
money = request.POST.get('money')
wecpay = get_wecpay_object(uid)
# order_name()是一个生成随机订单的函数,可自定义
out_trade_no = order_num('xx',uid) # 生成一个唯一的订单号(根据自己的订单生成逻辑)
params = wecpay.build_data_dict(out_trade_no,int(float(money)*100)) # 创建一个请求参数字典
sign = wecpay.get_sign(params,WeChartPayConfig.api_key) # 获取签名
params['sign'] = sign # 在参数字典中添加签名
print(params)
xml = wecpay.trans_dict_to_xml(params) # 将字典转换为xml
response = requests.request('post',WeChartPayConfig.ufdoder_url,data=xml) # 以post方式向微信平台服务器发起请求
data_dict = wecpay.trans_xml_to_dict(response.content) # 将请求返回的数据转为字典
# 如果请求成功
if data_dict.get('return_code') == 'SUCCESS':
qrcode_name = out_trade_no + '.png' # 二维码图片名称(此处使用订单号+’.png‘作为图片名称,你也可以自定义,只要保证唯一即可)
img = qrcode.make(data_dict.get('code_url')) # 创建支付二维码
img.save(r'static' + '/qrcode/' + qrcode_name) # 保存二维码图片
return render(request,'user_center/qrcode.html',{'qrcode_img':qrcode_name})
return HttpResponse('获取微信的code_url失败!')
# 支付成功后回调(微信)
@csrf_exempt
def wec_notify(request,uid):
wecpay = get_wecpay_object(uid)
data_dict = wecpay.trans_xml_to_dict(request.body) # 将回调返回的数据转化为字典
sign = data_dict.pop('sign') # 取出签名
key = WeChartPayConfig.api_key # 商户密钥
back_sign = wecpay.get_sign(data_dict,key) # 计算签名
if sign == back_sign:
'''
若没有进行过业务处理则进行业务处理
'''
print('支付成功')
return HttpResponse('success')
else:
'''
支付失败后业务逻辑
'''
return HttpResponse('支付失败')
class WeChartPayConfig(object):
# 公众账号上的appid
app_id = ""
# 商户号
mch_id = ""
# 微信商户平台(pay.weixin.qq.com)-->账户设置 -->API安全-->密钥设置,设置完成后把密钥复制过来
api_key = ""
app_secrect= ""
# 微信下单url
ufdoder_url = "https://api.mch.weixin.qq.com/pay/unifiedorder"
# 微信支付结果回调接口,改为服务器上处理结果的回调方法路径
notify_url = "http://xxx/"
# 你的服务器ip
create_ip = ""
以上代码仅供参考,如若直接商用出现任何后果概不负责。