網(wǎng)上有很多關(guān)于農(nóng)業(yè)銀行pos機(jī)掃微信,Win10基于Vue.js+Django+Python3微信掃碼支付流程的知識(shí),也有很多人為大家解答關(guān)于農(nóng)業(yè)銀行pos機(jī)掃微信的問(wèn)題,今天pos機(jī)之家(www.rcqwhg.com)為大家整理了關(guān)于這方面的知識(shí),讓我們一起來(lái)看下吧!
本文目錄一覽:
農(nóng)業(yè)銀行pos機(jī)掃微信
之前的一篇文章:mpvue1.0+python3.7+Django2.0.4實(shí)現(xiàn)微信小程序的支付功能,主要介紹了微信小程序內(nèi)部支付的流程,然而實(shí)際上微信小程序有一定的局限性,也就是用戶范圍僅限于小程序內(nèi)部生態(tài)圈,在生活中真正具有廣泛性、高效性、使用方便性的支付方式還得是掃碼支付,掃碼的優(yōu)點(diǎn)在于推廣成本低,上至釣魚臺(tái)國(guó)賓館,下至發(fā)廊地?cái)偠寄苡?,打印出?lái)就完事了,而相比其他支付方式,現(xiàn)金的找零及假鈔問(wèn)題,信用卡的辦理門檻、pos機(jī)的沉沒(méi)成本,就算微信可集成的h5支付和小程序支付,奈何很多老年人根本不會(huì)用小程序和手機(jī)瀏覽器,更別說(shuō)再進(jìn)行支付操作了,所以基于二維碼的掃碼支付的確是非常符合國(guó)情的。
本次我們使用前后端分離項(xiàng)目Vue.js+Django來(lái)集成微信的掃碼支付功能,體驗(yàn)一下21世紀(jì)泛用性最高的支付方式,首先注冊(cè)微信公眾平臺(tái):https://mp.weixin.qq.com
獲得開(kāi)發(fā)者id和秘鑰(appid & appsecret)
同時(shí)確保獲取微信支付接口的權(quán)限:
隨后注冊(cè)微信支付商戶平臺(tái):https://pay.weixin.qq.com/
獲取微信支付的商戶號(hào)(在賬戶信息頁(yè)面):
獲取微信支付接口的秘鑰(賬戶中心->api安全):
同時(shí)在產(chǎn)品中心->開(kāi)發(fā)配置頁(yè)面,將支付域名配置好:
這里不像微信小程序,小程序只能允許https協(xié)議接口,而掃碼支付域名既支持https也支持http,非常方便,同時(shí)注意域名必須是一個(gè)備案域名。
至此,微信支付的前置操作就搞定了,下面我們來(lái)編寫后臺(tái)接口wx_pay.py,首先導(dǎo)入依賴的庫(kù)和一些工具方法:
import requestsfrom django.http import HttpResponse, HttpResponseRedirectimport randomimport timeimport hashlibimport qrcodefrom bs4 import BeautifulSoupdef 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_dictdef 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['): # 添加X(jué)ML標(biāo)記 v = '<![CDATA[{}]]>'.format(v) data_xml.append('<{key}>{value}</{key}>'.format(key=k, value=v)) return '<xml>{}</xml>'.format(''.join(data_xml)) # 返回XMLdef 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()) # 將參數(shù)字符串傳入 sign = md5.hexdigest().upper() # 完成加密并轉(zhuǎn)為大寫 return sign
qrcode模塊用來(lái)生成二維碼,bs4模塊用來(lái)將微信接口返回的xml解析成json,在21世紀(jì)的第二十個(gè)年頭,微信接口居然還在使用原始的xml,這種反人類行為實(shí)在不能理解。
接下來(lái)我們來(lái)編寫支付邏輯,參考微信官方文檔:https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_5&index=3
業(yè)務(wù)流程說(shuō)明:(1)商戶后臺(tái)系統(tǒng)根據(jù)用戶選購(gòu)的商品生成訂單。(2)用戶確認(rèn)支付后調(diào)用微信支付【統(tǒng)一下單API】生成預(yù)支付交易;(3)微信支付系統(tǒng)收到請(qǐng)求后生成預(yù)支付交易單,并返回交易會(huì)話的二維碼鏈接code_url。(4)商戶后臺(tái)系統(tǒng)根據(jù)返回的code_url生成二維碼。(5)用戶打開(kāi)微信“掃一掃”掃描二維碼,微信客戶端將掃碼內(nèi)容發(fā)送到微信支付系統(tǒng)。(6)微信支付系統(tǒng)收到客戶端請(qǐng)求,驗(yàn)證鏈接有效性后發(fā)起用戶支付,要求用戶授權(quán)。(7)用戶在微信客戶端輸入密碼,確認(rèn)支付后,微信客戶端提交授權(quán)。(8)微信支付系統(tǒng)根據(jù)用戶授權(quán)完成支付交易。(9)微信支付系統(tǒng)完成支付交易后給微信客戶端返回交易結(jié)果,并將交易結(jié)果通過(guò)短信、微信消息提示用戶。微信客戶端展示支付交易結(jié)果頁(yè)面。(10)微信支付系統(tǒng)通過(guò)發(fā)送異步消息通知商戶后臺(tái)系統(tǒng)支付結(jié)果。商戶后臺(tái)系統(tǒng)需回復(fù)接收情況,通知微信后臺(tái)系統(tǒng)不再發(fā)送該單的支付通知。(11)未收到支付通知的情況,商戶后臺(tái)系統(tǒng)調(diào)用【查詢訂單API】。(12)商戶確認(rèn)訂單已支付后給用戶發(fā)貨。
一望而知,我們需要調(diào)用微信的統(tǒng)一下單接口,文檔:https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=9_1
編寫邏輯:
def wx_pay(request): url = 'https://api.mch.weixin.qq.com/pay/unifiedorder' # 微信掃碼支付接口 key = '945bec********a8fbf7d7' #商戶api秘鑰 total_fee = 1 #支付金額,單位分 body = '123123' # 商品描述 out_trade_no = 'order_%s' % random.randrange(100000, 999999) # 訂單編號(hào) params = { 'appid': 'wx09*****f', # APPID 'mch_id': '16****08', # 商戶號(hào) 'notify_url': 'http://wxpay.v3u.cn/wx_back/', # 支付域名回調(diào)地址 'product_id': 'goods_%s' % random.randrange(100000, 999999), # 商品編號(hào) 'trade_type': 'NATIVE', # 支付類型(掃碼支付) 'spbill_create_ip': '114.254.176.137', # 發(fā)送請(qǐng)求服務(wù)器的IP地址 'total_fee': total_fee, # 訂單總金額 'out_trade_no': out_trade_no, # 訂單編號(hào) 'body': body, # 商品描述 'nonce_str': 'ibuaiVcKdpRxkhJA' # 字符串 } sign = get_sign(params, key) # 獲取簽名 params.setdefault('sign', sign) # 添加簽名到參數(shù)字典 xml = trans_dict_to_xml(params) # 轉(zhuǎn)換字典為XML response = requests.request('post', url, data=xml) # 以POST方式向微信公眾平臺(tái)服務(wù)器發(fā)起請(qǐng)求 data_dict = trans_xml_to_dict(response.content) # 將請(qǐng)求返回的數(shù)據(jù)轉(zhuǎn)為字典 print(data_dict) qrcode_name = out_trade_no + '.png' # 支付二維碼圖片保存路徑 if data_dict.get('return_code') == 'SUCCESS': # 如果請(qǐng)求成功 img = qrcode.make(data_dict.get('code_url')) # 創(chuàng)建支付二維碼片 img.save('./' + qrcode_name) # 保存支付二維碼 return HttpResponse(qrcode_name)
隨后配置路由:
from myapp.wx_pay import wx_payfrom django.contrib.staticfiles.urls import staticfiles_urlpatterns# ... the rest of your URLconf goes here ...urlpatterns = [ #定義超鏈接路由 re_path('^static/upload/(?P<path>.*)$',serve,{'document_root':'/static/upload/'}), path('wx_pay/', wx_pay),]
啟動(dòng)django服務(wù):
python manage.py runserver
訪問(wèn)http://localhost:8000/wx_pay/
沒(méi)有問(wèn)題,查看后臺(tái)日志:
{'return_code': 'SUCCESS', 'return_msg': 'OK', 'appid': 'wx092344a76b9979ff', 'mch_id': '1602932608', 'nonce_str': 'bnJwGlXZ3eDSNgjs', 'sign': '2D81402DABEDF75E9A58F200FE7B6775', 'result_code': 'SUCCESS', 'prepay_id': 'wx1816114416896958d6f84177bd71da0000', 'trade_type': 'NATIVE', 'code_url': 'weixin://wxpay/bizpayurl?pr=JgBYgTS00'}
可以看到已經(jīng)下單成功,不過(guò)訂單狀態(tài)處于預(yù)支付狀態(tài),同時(shí)檢查二維碼圖片是否生成:
至此,后臺(tái)邏輯基本搞定,下面就是如何在前端進(jìn)行調(diào)用,同時(shí)讓用戶進(jìn)行掃描操作,編寫wx_pay.vue組件:
<template> <div> <center><h1>掃碼支付</h1></center> <a-form-item v-bind="formItemLayout" label="金額"> <a-input v-model="money"/> </a-form-item> <a-form-item v-bind="tailFormItemLayout"> <a-button type="primary" html-type="submit" @click="submit"> 生成二維碼 </a-button> </a-form-item> <a-form-item v-bind="formItemLayout" label="二維碼"> <img :src="src" /> </a-form-item> </div></template><script>export default { data() { return { money:"1", src:"", formItemLayout: { labelCol: { xs: { span: 24 }, sm: { span: 8 }, }, wrapperCol: { xs: { span: 24 }, sm: { span: 16 }, }, }, tailFormItemLayout: { wrapperCol: { xs: { span: 24, offset: 0, }, sm: { span: 16, offset: 8, }, }, }, dataSource: [ { key: '0', name: 'Edward King 0', age: '32', address: 'London, Park Lane no. 0', }, { key: '1', name: 'Edward King 1', age: '32', address: 'London, Park Lane no. 1', }, ], columns: [ { title: 'name', dataIndex: 'name', }, { title: 'age', dataIndex: 'age', }, { title: 'address', dataIndex: 'address', }, { title: 'operation', dataIndex: 'operation', scopedSlots: { customRender: 'operation' }, }, ], }; }, methods: { submit:function(){ this.axios.get('http://localhost:8000/wx_pay/').then((result) =>{ console.log(result.data.img); this.src = "http://localhost:8000/static/upload/"+result.data.img }); }, onDelete(key) { console.log(this.dataSource[key]); } },};</script>
當(dāng)用戶點(diǎn)擊按鈕之后,旋即請(qǐng)求后端支付接口,將接口生成的二維碼返回給前端,效果是這樣的:
隨后使用微信掃一掃功能進(jìn)行掃碼支付,需要注意的是,該二維碼有效期只有五分鐘,所以最好加上刷新功能。
支付成功之后,我們還需要對(duì)交易進(jìn)行確認(rèn),所以根據(jù)微信官方文檔,調(diào)用統(tǒng)一查詢接口:
https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=9_2,根據(jù)接口文檔編寫邏輯:
def wx_check(request): #統(tǒng)一訂單查詢接口 url = "https://api.mch.weixin.qq.com/pay/orderquery" out_trade_no = "order_537236" #支付后的商戶訂單號(hào) key = '945b******d7' # 商戶api密鑰 params = { 'appid': 'wx0*****ff', # APPID 'mch_id': '16*****08', # 商戶號(hào) 'out_trade_no': out_trade_no, # 訂單編號(hào) 'nonce_str': 'ibuaiVcKdpRxkhJA' # 隨機(jī)字符串 } sign = get_sign(params, key) # 獲取簽名 params.setdefault('sign', sign) # 添加簽名到參數(shù)字典 xml = trans_dict_to_xml(params) # 轉(zhuǎn)換字典為XML response = requests.request('post', url, data=xml) # 以POST方式向微信公眾平臺(tái)服務(wù)器發(fā)起請(qǐng)求 data_dict = trans_xml_to_dict(response.content) # 將請(qǐng)求返回的數(shù)據(jù)轉(zhuǎn)為字典 print(data_dict) return HttpResponse('ok')
這里需要注意的是,查詢的訂單編號(hào)可以使商戶自己的訂單編號(hào),也可以是微信訂單號(hào),二者必取其一:
訪問(wèn)接口 http://localhost:8000/wx_check/
返回結(jié)果:
{'return_code': 'SUCCESS', 'return_msg': 'OK', 'appid': 'wx092344a76b9979ff', 'mch_id': '1602932608', 'nonce_str': 'BVoaDmxxADkpSFEl', 'sign': '23A86EB406B743E0C2C61C7E78DC9373', 'result_code': 'SUCCESS', 'openid': 'oy9q36f9Dpeokj9FWyN3j0znpIqE', 'is_subscribe': 'N', 'trade_type': 'NATIVE', 'bank_type': 'OTHERS', 'total_fee': '1', 'fee_type': 'CNY', 'transaction_id': '4200000806202012174121934231', 'out_trade_no': 'order_537236', 'attach': ' ', 'time_end': '20201217231553', 'trade_state': 'SUCCESS', 'cash_fee': '1', 'trade_state_desc': '支付成功', 'cash_fee_type': 'CNY'}
可以看到?jīng)]有問(wèn)題,但是由于涉及金錢業(yè)務(wù),為了養(yǎng)成良好的測(cè)試習(xí)慣,最好登錄商戶后臺(tái)再次確認(rèn):
結(jié)語(yǔ):至此,整個(gè)微信掃碼支付流程全部跑通,流程上比微信小程序支付邏輯要簡(jiǎn)單一些,同時(shí)由于不需要在線用戶的openid,所以像微信小程序獲取不到openid這樣的大坑并不存在,后續(xù)會(huì)分享一些關(guān)于微信掃碼訂單退款的邏輯,搞笑的是,統(tǒng)一下單和查詢接口沒(méi)有并發(fā)限制,而申請(qǐng)退款居然有qps上的限制,所以退款流程應(yīng)該會(huì)需要消息隊(duì)列的介入。
以上就是關(guān)于農(nóng)業(yè)銀行pos機(jī)掃微信,Win10基于Vue.js+Django+Python3微信掃碼支付流程的知識(shí),后面我們會(huì)繼續(xù)為大家整理關(guān)于農(nóng)業(yè)銀行pos機(jī)掃微信的知識(shí),希望能夠幫助到大家!