django2.0呼叫微信支付介面實現PC端掃碼支付
阿新 • • 發佈:2018-12-17
準備工作:
程式碼實現:
目錄結構
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('<![CDATA['): # 新增XML標記
v = '<![CDATA[{}]]>'.format(v)
data_xml.append('<{key}>{value}</{key}>'.format(key=k, value=v))
return '<xml>{}</xml>'.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 = ""
以上程式碼僅供參考,如若直接商用出現任何後果概不負責。