Code example
- preface
This paper mainly introduces the internal payment process of wechat applet. However, in fact, wechat applet has certain limitations, that is, the scope of users is limited to the internal ecosystem of the applet. The payment method that is truly extensive, efficient and convenient in life must also be code scanning payment. The advantage of code scanning is that the promotion cost is low. It goes to Diaoyutai State Guesthouse, It can be used down to the hair salon and the stall, and it will be finished when printed. Compared with other payment methods, cash change and counterfeit banknotes, the threshold of credit card processing, and the sunk cost of pos machine, even if wechat can integrate h5 payment and applet payment, many elderly people don't use applet and mobile browser at all, let alone payment operation, Therefore, code scanning payment based on QR code is indeed very in line with national conditions. This time, we use the front and rear end separation project Vue JS + Django to integrate the code scanning payment function of wechat and experience the most versatile payment method in the 21st century.
1 related operations
1.1 register wechat public platform
https://mp.weixin.qq.com
1.1.1 obtain developer id and secret key
- appid & appsecret
[the external chain image transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-X1B78lZO-1619328207946)(imgs/image-20201228081701914.png)]
1.1.2 access to wechat payment interface
[the external link image transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (IMG hyfzwjdq-1619328207949) (IMGs / image-20201228081756400. PNG)]
1.2 register wechat payment merchant platform
https://pay.weixin.qq.com/
1.2.1 obtain the merchant number of wechat payment
- On the account information page
[the external link image transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-MbmhSUnR-1619328207951)(imgs/image-20201228081956188.png)]
1.3 get the secret key of wechat payment interface
- Account center - > API security
1.4 configure payment domain name
- Product Center - > development configuration page
1.5 relevant precautions
1.5.1 domain name
Unlike wechat applet, the applet can only allow https protocol interface, and the code scanning payment domain name supports both https and http, which is very convenient. At the same time, note that the domain name must be a filed domain name.
1.5.2 wechat interface uses xml
qrcode module is used to generate QR code and bs4 module is used to parse the xml returned by wechat interface into json. In the 20th year of the 21st century, wechat interface still uses the original xml. This kind of anti-human behavior is really incomprehensible.
2. Business process description
(1)The merchant background system generates orders according to the commodities purchased by users. (2)Users confirm payment and call WeChat payment. API]Generate advance payment transaction; (3)After receiving the request, the wechat payment system generates an advance payment transaction form and returns the QR code link of the transaction session code_url. (4)The merchant background system returns code_url Generate QR code. (5)The user opens the wechat "scan" to scan the QR code, and the wechat client sends the scanned content to the wechat payment system. (6)The wechat payment system receives the client request and initiates user payment after verifying the validity of the link, requiring user authorization. (7)The user enters the password in the wechat client, and after confirming the payment, the wechat client submits the authorization. (8)The wechat payment system completes the payment transaction according to the user's authorization. (9)After completing the payment transaction, the wechat payment system returns the transaction result to the wechat client, and prompts the user of the transaction result through SMS and wechat message. Wechat client displays the payment transaction result page. (10)The wechat payment system notifies the merchant background system of the payment results by sending asynchronous messages. The merchant background system needs to reply to the reception and inform the wechat background system not to send the payment notice of this order. (11)If the payment notice is not received, the merchant background system calls [query order] API]. (12)The merchant will deliver the goods to the user after confirming that the order has been paid.
3 Django
3.1 packages to be installed
pip install lxml pip install qrcode
3.2 utils.py
import json import qrcode import requests from django.http import HttpResponse, HttpResponseRedirect import random import time import hashlib from bs4 import BeautifulSoup def trans_xml_to_dict(data_xml): soup = BeautifulSoup(data_xml, features='xml') xml = soup.find('xml') # Parsing XML if not xml: return {} data_dict = dict([(item.name, item.text) for item in xml.find_all()]) return data_dict def trans_dict_to_xml(data_dict): # Define the function of dictionary to XML data_xml = [] for k in sorted(data_dict.keys()): # Traverse the sorted key of the dictionary v = data_dict.get(k) # Take out the value corresponding to the key in the dictionary if k == 'detail' and not v.startswith('<![CDATA['): # Add XML tag v = '<![CDATA[{}]]>'.format(v) data_xml.append('<{key}>{value}</{key}>'.format(key=k, value=v)) return '<xml>{}</xml>'.format(''.join(data_xml)) # Return XML def get_sign(data_dict, key): # Signature function with parameters of signed data and key params_list = sorted(data_dict.items(), key=lambda e: e[0], reverse=False) # The parameter dictionary is inverted into a list params_str = "&".join(u"{}={}".format(k, v) for k, v in params_list) + '&key=' + key # Organize the parameter string and add the merchant transaction key at the end md5 = hashlib.md5() # Use MD5 encryption mode md5.update(params_str.encode()) # Pass parameter string into sign = md5.hexdigest().upper() # Complete encryption and convert to uppercase return sign def wx_pay(request): url = 'https://api.mch.weixin.qq.com/pay/unifiedorder '# wechat code scanning payment interface key = '945bec9df3614cffb74e39aba8fbf7d7' # total_fee = 1 #Payment amount, unit: minute body = '123456' # Product description out_trade_no = 'order_%s' % random.randrange(100000, 999999) # Order number params = { 'appid': 'wx092344a76b9979ff', # APPID 'mch_id': '1602932608', # Merchant number 'notify_url': 'http://wxpay.v3u.cn/wx_back / ', # callback address 'product_id': 'goods_%s' % random.randrange(100000, 999999), # Item number 'trade_type': 'NATIVE', # Payment type (code scanning payment) 'spbill_create_ip': '114.254.176.137', # IP address of the sending request server 'total_fee': total_fee, # Total order amount 'out_trade_no': out_trade_no, # Order number 'body': body, # Product description 'nonce_str': 'ibuaiVcKdpRxkhJA' # character string } sign = get_sign(params, key) # Get signature params.setdefault('sign', sign) # Add signature to parameter dictionary xml = trans_dict_to_xml(params) # Convert dictionary to XML response = requests.request('post', url, data=xml) # Send a request to wechat public platform server by POST data_dict = trans_xml_to_dict(response.content) # Turn the data returned by the request into a dictionary print(data_dict) qrcode_name = out_trade_no + '.png' # Pay QR code image saving path if data_dict.get('return_code') == 'SUCCESS': # If the request is successful img = qrcode.make(data_dict.get('code_url')) # Create payment QR code chip img.save('./static/upload/' + qrcode_name) # Save the payment QR code, your own address, and upload your own creation return HttpResponse(json.dumps({'img':qrcode_name}))
3.3 urls.py
from django.urls import path, re_path from eventlet import serve from walletapp.utils import payment, payment_execute, wx_pay urlpatterns = [ path('paypal/', payment), # Payment address path('execute/', payment_execute), # Callback # path('refund/', payment_execute), # refund path('wx_pay/', wx_pay), # wx payment re_path('^static/upload/(?P<path>.*)$', serve, {'document_root':'/static/upload/'}), ]
4 Vue end
4.1 payFor.vue
<template> <div> <h1>wx</h1> <div> <a-form-item v-bind="formItemLayout" label="amount of money" style="width:200px;margin-left:650px"> <a-input v-model="money"/> </a-form-item> <a-form-item v-bind="tailFormItemLayout"> <a-button type="primary" html-type="submit" @click="submit"> Generate QR code </a-button> </a-form-item> <a-form-item v-bind="formItemLayout" label="QR code"> <img :src="src" /> </a-form-item> </div> </div> </template> <script> import axios from 'axios' 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(){ axios.get('http://127.0.0.1:1594/wallet/wx_pay/').then((result) =>{ console.log(result.data.img); this.src = "http://127.0.0.1:1594/static/upload/"+result.data.img }) }, onDelete(key) { console.log(this.dataSource[key]); } }, created() { } } </script> <style scoped> </style>
his.src = "http://127.0.0.1:1594/static/upload/"+result.data.img
}) }, onDelete(key) { console.log(this.dataSource[key]); } }, created() { }
}