登录 https://mp.weixin.qq.com/cgi-bin/loginpage公众号,左边找到“开发”->“基本配置”,找到:
-
开发者ID(AppID)
-
开发者密码(AppSecret)
-
设置IP白名单
登录 https://pay.weixin.qq.com/core/home/login商户平台,找到:
- 商户号mchID
NATIVE
一、实现生成二维码扫码支付
- 创建一个Django项目,名为wechatPay
- 创建一个子应用,名为pay
- settings.py配置
3.1 注册子应用
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
#注册子应用
'pay',
]
3.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
3.3 静态文件配置
MEDIA_ROOT = os.path.join(BASE_DIR, 'media').replace('\\', '/') #设置静态文件路径为主目录下的media文件夹
MEDIA_URL = '/media/'
- 项目下的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
from wechatPay.settings import MEDIA_ROOT
urlpatterns = [
path('admin/', admin.site.urls),
path('wxpay/', WxTes.as_view()),
path('check_wxpay/', views.check_wxpay), # 支付结果验签
re_path('^media/(?P<path>.*)$', serve, {
"document_root": MEDIA_ROOT}), # 静态文件访问配置
]
- 子应用中的views.py配置 视图
import os
from random import Random
import string
import time
from rest_framework.response import Response
from rest_framework.views import APIView
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 test_django import settings
import random
import requests
import hashlib
import qrcode
from io import BytesIO
import base64
from PIL import Image
# 定义字典转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='html.parser')
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
class WxTes(APIView):
# 发起微信支付
def post(self,request):
nonce_str = random_str() # 拼接出随机的字符串即可,我这里是用 时间+随机数字+5个随机字母
total_fee = 1 #付款金额,单位是分,必须是整数
body = 'test' # 商品描述
out_trade_no = getWxPayOrdrID()
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':request.get_host().split(":")[0],# 发送请求服务器的IP地址
'notify_url':settings._NOTIFY_URL, # 支付回调地址
'body':body, # 商品描述
'trade_type':'NATIVE' #扫码支付
}
sign = get_sign(params,settings._API_KEY) # 获取签名
params['sign'] = sign # 添加签名到参数字典
xml = trans_dict_to_xml(params).encode("utf-8") # 转换字典为XML encode 进行编码,否则 中文无法作为body(商品描述)
response = requests.request('post', settings._UFDODER_URL, data=xml) # 以POST方式向微信公众平台服务器发起请求
data_dict = trans_xml_to_dict(response.content) # 将请求返回的数据转为字典
qrcode_name = 'wxpay' + '.png' # 支付二维码图片保存路径
if data_dict.get('return_code') == 'SUCCESS': # 如果请求成功
# 保存图片 形式
# img = qrcode.make(data_dict.get('code_url')) # 创建支付二维码片
# # print(img) <qrcode.image.pil.PilImage object at 0x0000029F83620978>
# # print(type(img)) <class 'qrcode.image.pil.PilImage'>
# img.save('media