Python+Django实现微信扫码支付流程

关注公众号“轻松学编程”了解更多。
获取源码可以加我微信【1257309054】,文末有二维码。
【微信公众号支付官网】https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_1

【必备资料】:微信公众号、商户平台

登录https://mp.weixin.qq.com/cgi-bin/loginpage公众号,左边找到“开发”->“基本配置”,找到:

  • 开发者ID(AppID)

  • 开发者密码(AppSecret)

  • 设置IP白名单

登录https://pay.weixin.qq.com/core/home/login商户平台,找到:

  • 商户号mchID

一、实现生成二维码扫码支付

1、创建一个Django项目,名为wechatPay

2、创建一个子应用,名为pay

3、在项目下创建static文件夹存放静态文件

4、创建templates存放html文件

点击templates文件夹右键,“Mark Directory as”–>“Template Folder”

4.1 创建报名页面buy.html

<!DOCTYPE html>
<html>
<head>
<title>报名</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/4.1.0/css/bootstrap.min.css">
<script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>
<script src="https://cdn.bootcss.com/popper.js/1.12.5/umd/popper.min.js"></script>
<script src="https://cdn.bootcss.com/bootstrap/4.1.0/js/bootstrap.min.js"></script>
</head>
<body> <div class="jumbotron text-center">
<h2>报名</h2>
<p>已报名人数:&nbsp;&nbsp;8465</p>
</div> <div class="container">
<h2>填写信息</h2>
<form action="{% url "to_pay" %}" method="post">
{% csrf_token %}
<div class="form-group">
<label for="name">姓名</label>
<input type="text" class="form-control" id="name" placeholder="姓名" name="name">
</div>
<div class="form-group">
<label for="phone">手机号</label>
<input type="phone" class="form-control" id="phone" placeholder="手机号" name="phone">
</div> <button type="submit" class="btn btn-primary">提交</button>
</form>
</div> </body>
</html>

4.2 创建二维码扫码页面qrcode.html

<!DOCTYPE html>
<html lang="zh-CN"> <head>
<meta charset="UTF-8">
<title>扫码支付</title>
</head>
<style>
.box {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%);
text-align: center;
} .conten {
width: 100%;
} body {
background: #ccc;
}
</style> <body>
{% load static %}
<div class="box">
<h2 class="content"><span>扫码支付</span></h2>
<!--<h2>扫码支付</h2>-->
<img src="{% static qrcode_img %}"><!--显示支付二维码--> </div>
</body> </html>

5、项目目录结构

6、settings.py配置

6.1 注册子应用

INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
#注册子应用
'pay', ]

6.2 添加微信支付配置

#微信支付配置
# ========支付相关配置信息===========
_APP_ID = "你的appid" # 公众账号appid
_MCH_ID = "你的商户号" # 商户号
_API_KEY = "你的商户号密钥" # 微信商户平台(pay.weixin.qq.com) -->账户设置 -->API安全 -->密钥设置,设置完成后把密钥复制到这里 _UFDODER_URL = "https://api.mch.weixin.qq.com/pay/unifiedorder"; #url是微信下单api
_NOTIFY_URL = "支付结果回调" # 微信支付结果回调接口,需要改为你的服务器上处理结果回调的方法路径
_CREATE_IP = '你的ip' # 发起支付请求的ip APPEND_SLASH=False

6.3 静态文件配置

STATIC_URL = '/static/'
STATIC_ROOT = '/static/'
# 添加静态资源路由地址
STATICFILES_DIRS=[
os.path.join(BASE_DIR,'static'), ]

7、项目下的urls.py配置

from django.conf import settings
from django.contrib import admin
from django.urls import path
from django.views.static import serve
from pay import views urlpatterns = [
path('admin/', admin.site.urls),
path('buy/', views.buy), # 打开购买页面
path('to_pay/', views.wxpay, name='to_pay'), # 跳转二维码扫描页面
path('check_wxpay/', views.check_wxpay), # 支付结果验签
path('static/<str:path>', serve, {'document_root': settings.STATIC_ROOT}), # 静态文件访问配置
]

8、子应用中的views.py配置

from __future__ import unicode_literals

import os
from random import Random
import string
import time from django.shortcuts import render
from django.http.response import HttpResponse, HttpResponseBadRequest
from django.views.decorators.csrf import csrf_exempt # 解除csrf验证 from bs4 import BeautifulSoup
from wechatPay import settings
import random
import requests
import hashlib
import qrcode #报名首页
def buy(request):
return render(request, 'buy.html') # 定义字典转XML的函数
def trans_dict_to_xml(data_dict):
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 # 定义XML转字典的函数
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 wxpay(request):
nonce_str = random_str() # 拼接出随机的字符串即可,我这里是用 时间+随机数字+5个随机字母 total_fee = 1 #付款金额,单位是分,必须是整数
body = 'baoming' # 商品描述
out_trade_no = order_num(user_id=request.POST.get('phone','12345')) # 订单编号 params = {
'appid': settings._APP_ID, # APPID
'mch_id': settings._MCH_ID, # 商户号
'nonce_str':nonce_str, # 回调地址
'out_trade_no': out_trade_no,# 订单编号
'total_fee':total_fee,# 订单总金额
'spbill_create_ip':settings._CREATE_IP,# 发送请求服务器的IP地址
'notify_url':settings._NOTIFY_URL, # 支付回调地址
'body':body, # 商品描述
'trade_type':'NATIVE' #扫码支付
} sign = get_sign(params,settings._API_KEY) # 获取签名
params['sign'] = sign # 添加签名到参数字典
# print(params)
xml = trans_dict_to_xml(params) # 转换字典为XML
response = requests.request('post', settings._UFDODER_URL, data=xml) # 以POST方式向微信公众平台服务器发起请求
data_dict = trans_xml_to_dict(response.content) # 将请求返回的数据转为字典
qrcode_name = out_trade_no + '.png' # 支付二维码图片保存路径 if data_dict.get('return_code') == 'SUCCESS': # 如果请求成功
img = qrcode.make(data_dict.get('code_url')) # 创建支付二维码片
img.save('static' + '/' + qrcode_name) # return render(request, 'qrcode.html', {'qrcode_img': qrcode_name}) # 为支付页面模板传入二维码图像 return HttpResponse('交易请求失败!') # 支付成功后回调
@csrf_exempt # 去除csrf验证
def check_wxpay(request):
data_dict = trans_xml_to_dict(request.body) # 回调数据转字典
sign = data_dict.pop('sign') # 取出签名
key = settings._API_KEY # 商户交易密钥
back_sign = get_sign(data_dict, key) # 计算签名
if sign == back_sign: # 验证签名是否与回调签名相同
'''
检查对应业务数据的状态,判断该通知是否已经处理过,如果没有处理过再进行处理,如果处理过直接返回结果成功。
'''
print('支付成功!')
return HttpResponse('SUCCESS')
else:
'''
此处编写支付失败后的业务逻辑
''' return HttpResponse('failed') #获取签名
def get_sign(data_dict, key): # 签名函数,参数为签名的数据和密钥
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()) # 将参数字符串传入
sign = md5.hexdigest().upper() # 完成加密并转为大写
return sign #生成订单号
def order_num(package_id=12345, user_id=56789):
# 商品id后2位+下单时间的年月日12+用户2后四位+随机数4位
local_time = time.strftime('%Y%m%d%H%M%S', time.localtime(time.time()))[2:]
result = str(package_id)[-2:] + local_time + str(user_id)[-2:] + str(random.randint(1000, 9999))
return result #生成随机字符串
def random_str(randomlength=8):
str = ''
chars = 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz0123456789'
length = len(chars) - 1
random = Random()
for i in range(randomlength):
str+=chars[random.randint(0, length)]
return str

9、效果图

启动服务:

python manage.py runserver

在浏览器中输入127.0.0.1:8000/buy/

填写信息点击提交后会跳转到扫码支付页面。

10、注意

说明:现在微信不支持长按识别二维码支付,这个二维码只能通过微信右上角的扫一扫功能进行扫码支付。

附录

第三方依赖库:requirements.txt

beautifulsoup4==4.6.3
certifi==2018.8.24
chardet==3.0.4
colorama==0.3.9
Django==2.1.1
django-qrcode==0.3
django-wechat==0.1a1
html5lib==1.0.1
idna==2.7
image==1.5.25
lxml==4.2.5
optionaldict==0.1.1
Pillow==5.2.0
python-dateutil==2.7.3
pytz==2018.5
qrcode==6.0
requests==2.6.0
six==1.10.0
urllib3==1.23
webencodings==0.5.1
wechatpy==1.7.5
xmltodict==0.11.0

后记

【后记】为了让大家能够轻松学编程,我创建了一个公众号【轻松学编程】,里面有让你快速学会编程的文章,当然也有一些干货提高你的编程水平,也有一些编程项目适合做一些课程设计等课题。

也可加我微信【1257309054】,拉你进群,大家一起交流学习。
如果文章对您有帮助,请我喝杯咖啡吧!
我的微信:

公众号

关注我,我们一起成长~~

Python+Django实现微信扫码支付流程的更多相关文章

  1. Win10环境前后端分离项目基于Vue.js+Django+Python3实现微信(wechat)扫码支付流程(2021年最新攻略)

    原文转载自「刘悦的技术博客」https://v3u.cn/a_id_182 之前的一篇文章:mpvue1.0+python3.7+Django2.0.4实现微信小程序的支付功能,主要介绍了微信小程序内 ...

  2. 微信公众号支付|微信H5支付|微信扫码支付|小程序支付|APP微信支付解决方案总结

    最近负责的一些项目开发,都用到了微信支付(微信公众号支付.微信H5支付.微信扫码支付.APP微信支付).在开发的过程中,在调试支付的过程中,或多或少都遇到了一些问题,今天总结下,分享,留存. 先说注意 ...

  3. C#版微信公众号支付|微信H5支付|微信扫码支付问题汇总及解决方案总结

    最近负责的一些项目开发,都用到了微信支付(微信公众号支付.微信H5支付.微信扫码支付).在开发的过程中,在调试支付的过程中,或多或少都遇到了一些问题,今天总结下,分享,留存.代码在文章结尾处,有需要的 ...

  4. PHP PC端微信扫码支付【模式二】详细教程-附带源码(转)

    博主写这破玩意儿的时候花了大概快两天时间才整体的弄懂逻辑,考虑了一下~还是把所有代码都放出来给大家~抱着开源大无私的精神!谁叫我擅长拍黄片呢?同时也感谢我刚入行时候那些无私帮过我的程序员们! 首先还是 ...

  5. asp.net core 微信扫码支付(扫码支付,H5支付,公众号支付,app支付)之1

    2018-08-13更新生成二维码的方法 在做微信支付前,首先要了解你需要什么方式的微信支付,目前本人做过的支付包含扫码支付.H5支付.公众号支付.App支付等,本人使用的是asp.net mvc c ...

  6. ThinkPHP5微信扫码支付

    1.把微信官网下载的demo放在根目录/vendor/目录下,这里我的是/vendor/wxpay_pc目录 2.把cert里面的文件替换成自己项目的证书(登陆微信商户平台,账户中心,API安全下载) ...

  7. JAVA微信扫码支付模式二功能实现完整例子

    概述 本例子实现微信扫码支付模式二的支付功能,应用场景是,web网站微信扫码支付.实现从点击付费按钮.到弹出二维码.到用户用手机微信扫码支付.到手机上用户付费成功.web网页再自动调整到支付成功后的页 ...

  8. thinkphp.2 thinkphp5微信支付 微信公众号支付 thinkphp 微信扫码支付 thinkphp 微信企业付款5

    前面已经跑通了微信支付的流程,接下来吧微信支付和微信企业付款接入到thinkphp中,版本是3.2 把微信支付类.企业付款类整合到一起放到第三方类库,这里我把微信支付帮助类和企业付款类放到同一个文件了 ...

  9. ThinkPHP微信扫码支付接口

    最近折腾微信扫码支付,看了微信官方文档,找了很多网页,发现和文档/demo不匹配,现在自己算是弄出来了(文件名称有所更改),贴出来分享一下 一.将有用的官方lib文件和使用的相关文件放置到vendor ...

随机推荐

  1. Lyndon Word相关

    Lyndon Word 定义 对于字符串 \(S\),若 \(S\) 的最小后缀为其本身,那么称 \(S\) 为 \(\text{Lyndon}\) 串(\(\text{Lyndon Word}\)) ...

  2. notepad快捷使用

    1.快捷键 参考:https://www.php.cn/tool/notepad/428638.html notepad++是经常使用的一款编辑器软件,在编辑特殊文本的时候(html,java...) ...

  3. Flutter沉浸式状态栏/AppBar导航栏/仿咸鱼底部凸起导航

    Flutter中如何实现沉浸式透明Statusbar状态栏效果? 如下图:状态栏是指android手机顶部显示手机状态信息的位置.android 自4.4开始新加入透明状态栏功能,状态栏可以自定义颜色 ...

  4. Django ORM 引发的数据库 N+1 性能问题

    背景描述 最近在使用 Django 时,发现当调用 api 后,在数据库同一个进程下的事务中,出现了大量的数据库查询语句.调查后发现,是由于 Django ORM 的机制所引起. Django Obj ...

  5. vue点击切换样式,点击切换地址栏,点击显示或者隐藏

    1. vue点击显示切换 :class='{"span":index==0}' class原本是 类选择器 加上 :class就是绑定属性的意思 '{"span" ...

  6. RFC 8684---TCP Extensions for Multipath Operation with Multiple Addresses

    https://datatracker.ietf.org/doc/rfc8684/?include_text=1 TCP Extensions for Multipath Operation with ...

  7. 测试AAA

    程序计数器(线程私有) 程序计数器(Program Counter Register),也有称作为 PC 寄存器.保存的是程序当 前执行的指令的地址(也可以说保存下一条指令的所在存储单元的地址),当 ...

  8. 多测师讲解自动化测试 _RF分配id_高级讲师肖sir

    1.Assign Id To Element.

  9. python数据清洗

    盖帽法 分箱法 简单随机抽和分层抽

  10. pytest文档59-运行未提交git的用例(pytest-picked)

    前言 我们每天写完自动化用例后都会提交到 git 仓库,随着用例的增多,为了保证仓库代码的干净,当有用例新增的时候,我们希望只运行新增的未提交 git 仓库的用例. pytest-picked 插件可 ...