wx tripartite payment + QR code generation

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() {

}

}

Keywords: Python Vue http

Added by SteveFrost on Sat, 19 Feb 2022 18:09:26 +0200