您好,登錄后才能下訂單哦!
這篇文章主要介紹Python如何實(shí)現(xiàn)的微信支付方式,文中介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們一定要看完!
具體如下:
一、準(zhǔn)備環(huán)境
1、要有微信公眾號(hào),商戶平臺(tái)賬號(hào)
https://pay.weixin.qq.com/wiki/doc/api/index.html
2、支持的支付方式有
3、備案域名
選擇掃碼支付,如果使用模式二則不需要域名,只需要可訪問的ip地址就行。
4、建一個(gè)Django項(xiàng)目。
一、掃碼支付
點(diǎn)擊“掃碼支付”按官方文檔配置好回調(diào)url(具體如何配置看官網(wǎng))
先從公眾號(hào)上獲取APP_ID,APP_SECRECT,從商戶平臺(tái)上獲取MCH_ID,API_KEY
1、使用模式一生成支付二維碼
這個(gè)二維碼是沒有時(shí)間限制的。
create_qrcode.html
創(chuàng)建二維碼頁面
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>生成掃碼支付二維碼</title> </head> <body> <form method="post" action="/wxpay/QRcode/" > 輸入手機(jī)號(hào):<input name="phone"/> <input id="submit" type="submit" value="生成二維碼"> <br> {% if img_url %} <img src="{{ img_url }}" /> {% endif %} <br> {{ url }} </form> </body> </html>
pay_settings.py
#微信支付配置 # ========支付相關(guān)配置信息=========== import random import time import hashlib from random import Random import qrcode from bs4 import BeautifulSoup APP_ID = "xxx" # 你公眾賬號(hào)上的appid MCH_ID = "xxx" # 你的商戶號(hào) API_KEY = "xxx" # 微信商戶平臺(tái)(pay.weixin.qq.com) -->賬戶設(shè)置 -->API安全 -->密鑰設(shè)置,設(shè)置完成后把密鑰復(fù)制到這里 APP_SECRECT = "xxx" UFDODER_URL = "https://api.mch.weixin.qq.com/pay/unifiedorder" # 該url是微信下單api NOTIFY_URL = "http://xxx/" # 微信支付結(jié)果回調(diào)接口,需要改為你的服務(wù)器上處理結(jié)果回調(diào)的方法路徑 CREATE_IP = 'xxx' # 你服務(wù)器的IP def random_str(randomlength=8): """ 生成隨機(jī)字符串 :param randomlength: 字符串長(zhǎng)度 :return: """ str = '' chars = 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz0123456789' length = len(chars) - 1 random = Random() for i in range(randomlength): str+=chars[random.randint(0, length)] return str def order_num(phone): """ 生成掃碼付款訂單號(hào) :param phone: 手機(jī)號(hào) :return: """ local_time = time.strftime('%Y%m%d%H%M%S', time.localtime(time.time())) result = phone + 'T' + local_time + random_str(5) return result def get_sign(data_dict, key): # 簽名函數(shù),參數(shù)為簽名的數(shù)據(jù)和密鑰 params_list = sorted(data_dict.items(), key=lambda e: e[0], reverse=False) # 參數(shù)字典倒排序?yàn)榱斜? params_str = "&".join(u"{}={}".format(k, v) for k, v in params_list) + '&key=' + key # 組織參數(shù)字符串并在末尾添加商戶交易密鑰 md5 = hashlib.md5() # 使用MD5加密模式 md5.update(params_str.encode('utf-8')) # 將參數(shù)字符串傳入 sign = md5.hexdigest().upper() # 完成加密并轉(zhuǎn)為大寫 return sign def trans_dict_to_xml(data_dict): # 定義字典轉(zhuǎn)XML的函數(shù) data_xml = [] for k in sorted(data_dict.keys()): # 遍歷字典排序后的key v = data_dict.get(k) # 取出字典中key對(duì)應(yīng)的value if k == 'detail' and not v.startswith('<![CDATA['): # 添加XML標(biāo)記 v = '<![CDATA[{}]]>'.format(v) data_xml.append('<{key}>{value}</{key}>'.format(key=k, value=v)) return '<xml>{}</xml>'.format(''.join(data_xml)).encode('utf-8') # 返回XML,并轉(zhuǎn)成utf-8,解決中文的問題 def trans_xml_to_dict(data_xml): 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 def wx_pay_unifiedorde(detail): """ 訪問微信支付統(tǒng)一下單接口 :param detail: :return: """ detail['sign'] = get_sign(detail, API_KEY) # print(detail) xml = trans_dict_to_xml(detail) # 轉(zhuǎn)換字典為XML response = requests.request('post', UFDODER_URL, data=xml) # 以POST方式向微信公眾平臺(tái)服務(wù)器發(fā)起請(qǐng)求 # data_dict = trans_xml_to_dict(response.content) # 將請(qǐng)求返回的數(shù)據(jù)轉(zhuǎn)為字典 return response.content def pay_fail(err_msg): """ 微信支付失敗 :param err_msg: 失敗原因 :return: """ data_dict = {'return_msg': err_msg, 'return_code': 'FAIL'} return trans_dict_to_xml(data_dict) def create_qrcode(phone,url): """ 生成掃碼支付二維碼 :param phone: 手機(jī)號(hào) :param url: 支付路由 :return: """ img = qrcode.make(url) # 創(chuàng)建支付二維碼片 # 你存放二維碼的地址 img_url = r'media/QRcode' + '/' + phone + '.png' img.save(img_url) return img_url
views.py
from django.shortcuts import render from django.http import HttpResponse from django.views import View from django.views.decorators.csrf import csrf_exempt from pay_settings.py import * class Wxpay_QRccode(View): """ 生成微信支付二維碼 """ def get(self, request, *args, **kwargs): return render(request, 'create_qrcode.html') def post(self, request, *args, **kwargs): """ # 生成可掃碼支付的二維碼 :param request: :param args: :param kwargs: :return: """ phone = request.data.get('phone', None) if not phone: return HttpResponse('手機(jī)號(hào)獲取失敗') paydict = { 'appid': APP_ID, 'mch_id': MCH_ID, 'nonce_str': random_str(phone), 'product_id': phone, # 商品id,可自定義 'time_stamp': int(time.time()), } paydict['sign'] = get_sign(paydict, API_KEY) url = "weixin://wxpay/bizpayurl?appid=%s&mch_id=%s&nonce_str=%s&product_id=%s&time_stamp=%s&sign=%s" \ % (paydict['appid'], paydict['mch_id'], paydict['nonce_str'], paydict['product_id'], paydict['time_stamp'], paydict['sign']) # 可以直接在微信中點(diǎn)擊該url,如果有錯(cuò)誤,微信會(huì)彈出提示框,如果是掃碼,如果失敗,什么提示都沒有,不利于調(diào)試 print(url) # 創(chuàng)建二維碼 img_url = create_qrcode(url) return render(request, 'create_qrcode.html', context={'img_url': img_url}) @method_decorator(csrf_exempt, name='dispatch') class Wxpay_ModelOne_pay(View): """ 使用微信掃一掃掃描二維碼,微信系統(tǒng)會(huì)自動(dòng)回調(diào)此路由,Post請(qǐng)求 """ def post(self, request, *args, **kwargs): """ 掃描二維碼后,微信系統(tǒng)回調(diào)的地址處理 微信傳來的參數(shù)格式經(jīng)trans_xml_to_dict()轉(zhuǎn)成字典 {'openid': 'xxx', 'is_subscribe': 'Y', 'mch_id': 'xxx', 'nonce_str': 'xxx', 'sign': 'xxx', 'product_id': 'xxx', 'appid': 'xxx'} :param request: :param args: :param kwargs: :return: """ data_dict = trans_xml_to_dict(request.body) # 回調(diào)數(shù)據(jù)轉(zhuǎn)字典 sign = data_dict.pop('sign') # 取出簽名 key = API_KEY # 商戶交易密鑰 back_sign = get_sign(data_dict, key) # 計(jì)算簽名 if sign == back_sign: # 驗(yàn)證簽名是否與回調(diào)簽名相同 total_fee = 1 # 付款金額,單位是分,必須是整數(shù) params = { 'appid': APP_ID, # APPID 'mch_id': MCH_ID, # 商戶號(hào) 'nonce_str': random_str(16), # 隨機(jī)字符串 'out_trade_no': order_num(data_dict['product_id']), # 訂單編號(hào) 'total_fee': total_fee, # 訂單總金額 'spbill_create_ip': CREATE_IP, # 發(fā)送請(qǐng)求服務(wù)器的IP地址 'notify_url': NOTIFY_URL, 'body': 'xxx公司', # 商品描述 'detail': 'xxx商品', # 商品詳情 'trade_type': 'NATIVE', # 掃碼支付類型 } # 調(diào)用微信統(tǒng)一下單支付接口url notify_result = wx_pay_unifiedorde(params) #print(trans_xml_to_dict(notify_result)) return HttpResponse(notify_result) return HttpResponse(pay_fail('交易信息有誤,請(qǐng)重新掃碼'))
2、使用模式二生成支付二維碼
這個(gè)二維碼是有時(shí)間限制的。
模式二與模式一相比,流程更為簡(jiǎn)單,不依賴設(shè)置的回調(diào)支付URL。商戶后臺(tái)系統(tǒng)先調(diào)用微信支付的統(tǒng)一下單接口,微信后臺(tái)系統(tǒng)返回鏈接參數(shù)code_url,商戶后臺(tái)系統(tǒng)將code_url值生成二維碼圖片,用戶使用微信客戶端掃碼后發(fā)起支付。注意:code_url有效期為2小時(shí),過期后掃碼不能再發(fā)起支付。具體流程看微信公眾號(hào)。
主體代碼:
pay_settings.py
#微信支付配置 # ========支付相關(guān)配置信息=========== import random import time import hashlib from random import Random from bs4 import BeautifulSoup APP_ID = "xxx" # 你公眾賬號(hào)上的appid MCH_ID = "xxx" # 你的商戶號(hào) API_KEY = "xxx" # 微信商戶平臺(tái)(pay.weixin.qq.com) -->賬戶設(shè)置 -->API安全 -->密鑰設(shè)置,設(shè)置完成后把密鑰復(fù)制到這里 APP_SECRECT = "xxx" UFDODER_URL = "https://api.mch.weixin.qq.com/pay/unifiedorder" # 該url是微信下單api NOTIFY_URL = "http://xxx/" # 微信支付結(jié)果回調(diào)接口,需要改為你的服務(wù)器上處理結(jié)果回調(diào)的方法路徑 CREATE_IP = 'xxx' # 你服務(wù)器的IP def get_sign(data_dict, key): """ 簽名函數(shù) :param data_dict: 需要簽名的參數(shù),格式為字典 :param key: 密鑰 ,即上面的API_KEY :return: 字符串 """ params_list = sorted(data_dict.items(), key=lambda e: e[0], reverse=False) # 參數(shù)字典倒排序?yàn)榱斜? params_str = "&".join(u"{}={}".format(k, v) for k, v in params_list) + '&key=' + key # 組織參數(shù)字符串并在末尾添加商戶交易密鑰 md5 = hashlib.md5() # 使用MD5加密模式 md5.update(params_str.encode('utf-8')) # 將參數(shù)字符串傳入 sign = md5.hexdigest().upper() # 完成加密并轉(zhuǎn)為大寫 return sign def order_num(phone): """ 生成掃碼付款訂單號(hào) :param phone: 手機(jī)號(hào) :return: """ local_time = time.strftime('%Y%m%d%H%M%S', time.localtime(time.time())) result = phone + 'T' + local_time + random_str(5) return result def random_str(randomlength=8): """ 生成隨機(jī)字符串 :param randomlength: 字符串長(zhǎng)度 :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(data_dict): """ 定義字典轉(zhuǎn)XML的函數(shù) :param data_dict: :return: """ data_xml = [] for k in sorted(data_dict.keys()): # 遍歷字典排序后的key v = data_dict.get(k) # 取出字典中key對(duì)應(yīng)的value if k == 'detail' and not v.startswith('<![CDATA['): # 添加XML標(biāo)記 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(data_xml): """ 定義XML轉(zhuǎn)字典的函數(shù) :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
views.py
import qrcode from django.shortcuts import render from pay_settings import * from django.http import HttpResponse from django.views import View class WXPayView(View): def get(self,request): # 在info.html有一個(gè)按鈕,點(diǎn)擊后跳轉(zhuǎn)到這個(gè)類的post()中,具體urls.py設(shè)置不詳述 return render(request, 'info.html') def post(self,request): phone = request.POST.get('phone','') if not phone: return render(request, 'info.html', {'err_msg': '獲取手機(jī)號(hào)失敗'}) data_dict = wxpay(phone) if data_dict.get('return_code') == 'SUCCESS': # 如果請(qǐng)求成功 qrcode_name = phone + '.png' # 二維碼圖片名稱 img = qrcode.make(data_dict.get('code_url')) # 創(chuàng)建支付二維碼片 img.save(r'static' + '/' + qrcode_name) return render(request, 'qrcode.html', {'qrcode_img': qrcode_name}) return render(request, 'info.html', {'err_msg': '獲取微信的code_url失敗'}) def wxpay(phone): nonce_str = random_str() # 拼接出隨機(jī)的字符串即可,我這里是用 時(shí)間+隨機(jī)數(shù)字+5個(gè)隨機(jī)字母 total_fee = 1 # 付款金額,單位是分,必須是整數(shù) params = { 'appid': APP_ID, # APPID 'mch_id': MCH_ID, # 商戶號(hào) 'nonce_str': nonce_str, # 隨機(jī)字符串 'out_trade_no': order_num(phone), # 訂單編號(hào),可自定義 'total_fee': total_fee, # 訂單總金額 'spbill_create_ip': CREATE_IP, # 自己服務(wù)器的IP地址 'notify_url': NOTIFY_URL, # 回調(diào)地址,微信支付成功后會(huì)回調(diào)這個(gè)url,告知商戶支付結(jié)果 'body': 'xxx公司', # 商品描述 'detail': 'xxx商品', # 商品描述 'trade_type': 'NATIVE', # 掃碼支付類型 } sign = get_sign(params,API_KEY) # 獲取簽名 params['sign'] = sign # 添加簽名到參數(shù)字典 # print(params) xml = trans_dict_to_xml(params) # 轉(zhuǎn)換字典為XML response = requests.request('post', settings._UFDODER_URL, data=xml) # 以POST方式向微信公眾平臺(tái)服務(wù)器發(fā)起請(qǐng)求 data_dict = trans_xml_to_dict(response.content) # 將請(qǐng)求返回的數(shù)據(jù)轉(zhuǎn)為字典 return data_dict class Wxpay_Result(View): """ 微信支付結(jié)果回調(diào)通知路由 """ def get(self, request, *args, **kwargs): machine_code = request.GET.get('machine_code', '獲取機(jī)器編號(hào)失敗') # 返回支付成功頁面,可自定義 return render(request, 'zfcg.html', {'machine': {'machine_code': machine_code}}) def post(self, request, *args, **kwargs): """ 微信支付成功后會(huì)自動(dòng)回調(diào) 返回參數(shù)為: {'mch_id': '', 'time_end': '', 'nonce_str': '', 'out_trade_no': '', 'trade_type': '', 'openid': '', 'return_code': '', 'sign': '', 'bank_type': '', 'appid': '', 'transaction_id': '', 'cash_fee': '', 'total_fee': '', 'fee_type': '', ' is_subscribe': '', 'result_code': 'SUCCESS'} :param request: :param args: :param kwargs: :return: """ data_dict = trans_xml_to_dict(request.body) # 回調(diào)數(shù)據(jù)轉(zhuǎn)字典 # print('支付回調(diào)結(jié)果', data_dict) sign = data_dict.pop('sign') # 取出簽名 back_sign = get_sign(data_dict, API_KEY) # 計(jì)算簽名 # 驗(yàn)證簽名是否與回調(diào)簽名相同 if sign == back_sign and data_dict['return_code'] == 'SUCCESS': ''' 檢查對(duì)應(yīng)業(yè)務(wù)數(shù)據(jù)的狀態(tài),判斷該通知是否已經(jīng)處理過,如果沒有處理過再進(jìn)行處理,如果處理過直接返回結(jié)果成功。 ''' print('微信支付成功會(huì)回調(diào)!') # 處理支付成功邏輯 # 返回接收結(jié)果給微信,否則微信會(huì)每隔8分鐘發(fā)送post請(qǐng)求 return HttpResponse(trans_dict_to_xml({'return_code': 'SUCCESS', 'return_msg': 'OK'})) return HttpResponse(trans_dict_to_xml({'return_code': 'FAIL', 'return_msg': 'SIGNERROR'}))
二、使用JsAPI發(fā)起微信支付
在微信公眾號(hào)中左下角 設(shè)置->公眾號(hào)設(shè)置->功能設(shè)置,把業(yè)務(wù)域名,js接口安全域名,網(wǎng)頁授權(quán)域名設(shè)置好。
用戶在微信中點(diǎn)擊一個(gè)路由Url(可把這個(gè)url封裝成二維碼).在后臺(tái)中的views.py中的WxJsAPIPay類中使用get()函數(shù)處理用戶的請(qǐng)求,先獲取用戶的openid,然后調(diào)用微信統(tǒng)一下單接口,獲取prepay_id,具體看官網(wǎng)。
wx_js_pay.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0" id="vp"/> {# <script type="text/javascript" src="/static/js/rem.js"></script>#} {# <link rel="stylesheet" type="text/css" href="/static/css/base.css" rel="external nofollow" />#} {# <link rel="stylesheet" type="text/css" href="/static/css/index.css" rel="external nofollow" />#} </head> <body> <div class="bigbox"> <div class="top"> <span>訂單詳情</span> </div> <div class="zhong"> </div> <div class="zhifu"> <button class="btn" type="button" onclick="javascript:callpay();return false;">立即支付</button> </div> </div> <script src="https://cdn.bootcss.com/jquery/1.12.1/jquery.js"></script> <script type="text/javascript"> //調(diào)用微信JS api 支付 function onBridgeReady() { WeixinJSBridge.invoke( 'getBrandWCPayRequest', { appId: "{{ params.appid }}", //公眾號(hào)名稱,由商戶傳入 timeStamp: "{{ params.timeStamp }}", //時(shí)間戳,自1970年以來的秒數(shù) nonceStr: "{{ params.nonceStr }}", //隨機(jī)串 package: "prepay_id={{ params.prepay_id }}", //預(yù)支付id signType: "MD5", //微信簽名方式 paySign: "{{ params.sign }}" //微信簽名 }, function (res) { //支付成功后返回 get_brand_wcpay_request:ok if (res.err_msg == "get_brand_wcpay_request:ok") { // 跳轉(zhuǎn)到支付成功的頁面 window.location.href = '#'; {#alert('支付成功');#} } else if (res.err_msg == "get_brand_wcpay_request:cancel") { alert("您已取消支付!"); {#alert({{ params.machine_code }});#} {#window.location.href = '';#} } else if (res.err_msg == "get_brand_wcpay_request:fail") { $.each(res, function(key,value){ alert(value); }); alert("支付失敗!"); } } ); } function callpay() { if (typeof WeixinJSBridge == "undefined") { if (document.addEventListener) { document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false); } else if (document.attachEvent) { document.attachEvent('WeixinJSBridgeReady', onBridgeReady); document.attachEvent('onWeixinJSBridgeReady', onBridgeReady); } } else { onBridgeReady(); } } </script> </body> </html>
pay_settings.py
# encoding: utf-8 import hashlib import time import requests from collections import OrderedDict from random import Random from bs4 import BeautifulSoup APP_ID = "xxx" # 公眾賬號(hào)appid MCH_ID = "xxx" # 商戶號(hào) API_KEY = "xxx" # 微信商戶平臺(tái)(pay.weixin.qq.com) -->賬戶設(shè)置 -->API安全 -->密鑰設(shè)置,設(shè)置完成后把密鑰復(fù)制到這里 APP_SECRECT = "xxx" UFDODER_URL = "https://api.mch.weixin.qq.com/pay/unifiedorder" # url是微信下單api NOTIFY_URL = "http://xxx/wxpay/pay_result/" # 微信支付結(jié)果回調(diào)接口,需要你自定義 CREATE_IP = 'xxx' # 你服務(wù)器上的ip # 生成隨機(jī)字符串 def random_str(randomlength=8): """ 生成隨機(jī)字符串 :param randomlength: 字符串長(zhǎng)度 :return: """ str = '' chars = 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz0123456789' length = len(chars) - 1 random = Random() for i in range(randomlength): str+=chars[random.randint(0, length)] return str def order_num(phone): """ 生成掃碼付款訂單, :param phone: :return: """ local_time = time.strftime('%Y%m%d%H%M%S', time.localtime(time.time())) result = phone + 'T' + local_time + random_str(5) return result def get_sign(data_dict, key): # 簽名函數(shù),參數(shù)為簽名的數(shù)據(jù)和密鑰 params_list = sorted(data_dict.items(), key=lambda e: e[0], reverse=False) # 參數(shù)字典倒排序?yàn)榱斜? params_str = "&".join(u"{}={}".format(k, v) for k, v in params_list) + '&key=' + key # 組織參數(shù)字符串并在末尾添加商戶交易密鑰 md5 = hashlib.md5() # 使用MD5加密模式 md5.update(params_str.encode('utf-8')) # 將參數(shù)字符串傳入 sign = md5.hexdigest().upper() # 完成加密并轉(zhuǎn)為大寫 return sign def trans_dict_to_xml(data_dict): # 定義字典轉(zhuǎn)XML的函數(shù) data_xml = [] for k in sorted(data_dict.keys()): # 遍歷字典排序后的key v = data_dict.get(k) # 取出字典中key對(duì)應(yīng)的value if k == 'detail' and not v.startswith('<![CDATA['): # 添加XML標(biāo)記 v = '<![CDATA[{}]]>'.format(v) data_xml.append('<{key}>{value}</{key}>'.format(key=k, value=v)) return '<xml>{}</xml>'.format(''.join(data_xml)).encode('utf-8') # 返回XML,并轉(zhuǎn)成utf-8,解決中文的問題 def trans_xml_to_dict(data_xml): 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 def wx_pay_unifiedorde(detail): """ 訪問微信支付統(tǒng)一下單接口 :param detail: :return: """ detail['sign'] = get_sign(detail, API_KEY) # print(detail) xml = trans_dict_to_xml(detail) # 轉(zhuǎn)換字典為XML response = requests.request('post', UFDODER_URL, data=xml) # 以POST方式向微信公眾平臺(tái)服務(wù)器發(fā)起請(qǐng)求 # data_dict = trans_xml_to_dict(response.content) # 將請(qǐng)求返回的數(shù)據(jù)轉(zhuǎn)為字典 return response.content def get_redirect_url(): """ 獲取微信返回的重定向的url :return: url,其中攜帶code """ WeChatcode = 'https://open.weixin.qq.com/connect/oauth3/authorize' urlinfo = OrderedDict() urlinfo['appid'] = APP_ID urlinfo['redirect_uri'] = 'http://xxx/wxjsapipay/?getInfo=yes' # 設(shè)置重定向路由 urlinfo['response_type'] = 'code' urlinfo['scope'] = 'snsapi_base' # 只獲取基本信息 urlinfo['state'] = 'mywxpay' # 自定義的狀態(tài)碼 info = requests.get(url=WeChatcode, params=urlinfo) return info.url def get_openid(code,state): """ 獲取微信的openid :param code: :param state: :return: """ if code and state and state == 'mywxpay': WeChatcode = 'https://api.weixin.qq.com/sns/oauth3/access_token' urlinfo = OrderedDict() urlinfo['appid'] = APP_ID urlinfo['secret'] = APP_SECRECT urlinfo['code'] = code urlinfo['grant_type'] = 'authorization_code' info = requests.get(url=WeChatcode, params=urlinfo) info_dict = eval(info.content.decode('utf-8')) return info_dict['openid'] return None def get_jsapi_params(openid): """ 獲取微信的Jsapi支付需要的參數(shù) :param openid: 用戶的openid :return: """ total_fee = 1 # 付款金額,單位是分,必須是整數(shù) params = { 'appid': APP_ID, # APPID 'mch_id': MCH_ID, # 商戶號(hào) 'nonce_str': random_str(16), # 隨機(jī)字符串 'out_trade_no': order_num('123'), # 訂單編號(hào),可自定義 'total_fee': total_fee, # 訂單總金額 'spbill_create_ip': CREATE_IP, # 發(fā)送請(qǐng)求服務(wù)器的IP地址 'openid': openid, 'notify_url': NOTIFY_URL, # 支付成功后微信回調(diào)路由 'body': 'xxx公司', # 商品描述 'trade_type': 'JSAPI', # 公眾號(hào)支付類型 } # print(params) # 調(diào)用微信統(tǒng)一下單支付接口url notify_result = wx_pay_unifiedorde(params) params['prepay_id'] = trans_xml_to_dict(notify_result)['prepay_id'] params['timeStamp'] = int(time.time()) params['nonceStr'] = random_str(16) params['sign'] = get_sign({'appId': APP_ID, "timeStamp": params['timeStamp'], 'nonceStr': params['nonceStr'], 'package': 'prepay_id=' + params['prepay_id'], 'signType': 'MD5', }, API_KEY) return params
views.py
from django.http import HttpResponseRedirect, HttpResponse from django.shortcuts import render from django.views import View from pay_settings import * class WxJsAPIPay(View): def get(self, request, *args, **kwargs): """ 用戶點(diǎn)擊一個(gè)路由或者掃碼進(jìn)入這個(gè)views.py中的函數(shù),首先獲取用戶的openid, 使用jsapi方式支付需要此參數(shù) :param self: :param request: :param args: :param kwargs: :return: """ getInfo = request.GET.get('getInfo', None) openid = request.COOKIES.get('openid', '') if not openid: if getInfo != 'yes': # 構(gòu)造一個(gè)url,攜帶一個(gè)重定向的路由參數(shù), # 然后訪問微信的一個(gè)url,微信會(huì)回調(diào)你設(shè)置的重定向路由,并攜帶code參數(shù) return HttpResponseRedirect(get_redirect_url()) elif getInfo == 'yes': # 我設(shè)置的重定向路由還是回到這個(gè)函數(shù)中,其中設(shè)置了一個(gè)getInfo=yes的參數(shù) # 獲取用戶的openid openid = get_openid(request.GET.get('code'), request.GET.get('state', '')) if not openid: return HttpResponse('獲取用戶openid失敗') response = render_to_response('wx_js_pay.html', context={'params': get_jsapi_params(openid)}) response.set_cookie('openid', openid, expires=60 * 60 * 24 *30) return response else: return HttpResponse('獲取機(jī)器編碼失敗') else: return render(request, 'wx_js_pay.html', context={'params': get_jsapi_params(openid)})
以上是“Python如何實(shí)現(xiàn)的微信支付方式”這篇文章的所有內(nèi)容,感謝各位的閱讀!希望分享的內(nèi)容對(duì)大家有幫助,更多相關(guān)知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。