1. 程式人生 > >django2.0呼叫微信支付介面實現PC端掃碼支付

django2.0呼叫微信支付介面實現PC端掃碼支付

準備工作:

程式碼實現:

目錄結構

圖一

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 = ""

以上程式碼僅供參考,如若直接商用出現任何後果概不負責。