一、在微信支付子应用创建utils.py文件并添加一下内容
import hashlib
import datetime
import random
import xml.etree.ElementTree as ET
# 配置文件导入小程序appid、商户号、商户密钥
from settings.dev import APPID, Mch_id, Mch_key
def paysign(APPID, body, mch_id, nonce_str, notify_url, openid, out_trade_no, client_ip, total_fee):
ret = {
"appid": APPID,
"body": body,
"mch_id": mch_id,
"nonce_str": nonce_str,
"notify_url": notify_url,
"openid": openid,
"out_trade_no": out_trade_no,
"spbill_create_ip": client_ip,
"total_fee": total_fee,
"trade_type": 'JSAPI'
}
# 处理函数,对参数按照key=value的格式,并按照参数名ASCII字典序排序
stringA = '&'.join(["{0}={1}".format(k, ret.get(k)) for k in sorted(ret)])
stringSignTemp = '{0}&key={1}'.format(stringA, Mch_key)
sign = hashlib.md5(stringSignTemp.encode("utf-8")).hexdigest()
return sign.upper()
# 生成随机字符串
def getNonceStr():
data = "123456789zxcvbnmasdfghjklqwertyuiopZXCVBNMASDFGHJKLQWERTYUIOP"
nonce_str = ''.join(random.sample(data, 30))
return nonce_str
# 生成商品订单号
def getWxPayOrdrID():
date = datetime.datetime.now()
# 根据当前系统时间来生成商品订单号。时间精确到微秒
payOrdrID = date.strftime("%Y%m%d%H%M%S%f")
return payOrdrID
# 获取全部参数信息,封装成xml
def get_bodyData(openid, client_ip, price, timeStamp, user_id, time_data):
body = '购买质量安宝服务' # 商品描述
notify_url = 'https://127.0.0.1:8000/payOrder/' # 支付成功的回调地址 可访问 不带参数
nonce_str = getNonceStr() # 随机字符串
out_trade_no = getWxPayOrdrID() # 商户订单号
total_fee = str(price) # 订单价格 单位是 分
# 获取签名
sign = paysign(APPID, body, Mch_id, nonce_str, notify_url, openid, out_trade_no, client_ip, total_fee)
bodyData = '<xml>'
bodyData += '<appid>' + APPID + '</appid>' # 小程序ID
bodyData += '<body>' + body + '</body>' # 商品描述
bodyData += '<mch_id>' + Mch_id + '</mch_id>' # 商户号
bodyData += '<nonce_str>' + nonce_str + '</nonce_str>' # 随机字符串
bodyData += '<notify_url>' + notify_url + '</notify_url>' # 支付成功的回调地址
bodyData += '<openid>' + openid + '</openid>' # 用户标识
bodyData += '<out_trade_no>' + out_trade_no + '</out_trade_no>' # 商户订单号
bodyData += '<spbill_create_ip>' + client_ip + '</spbill_create_ip>' # 客户端终端IP
bodyData += '<total_fee>' + total_fee + '</total_fee>' # 总金额 单位为分
bodyData += '<trade_type>JSAPI</trade_type>' # 交易类型 小程序取值如下:JSAPI
bodyData += '<sign>' + sign + '</sign>'
bodyData += '</xml>'
return bodyData
def xml_to_dict(xml_data):
'''
xml to dict
:param xml_data:
:return:
'''
xml_dict = {}
root = ET.fromstring(xml_data)
for child in root:
xml_dict[child.tag] = child.text
return xml_dict
# 获取返回给小程序的paySign
def get_paysign(prepay_id, timeStamp, nonceStr):
pay_data = {
'appId': APPID,
'nonceStr': nonceStr,
'package': "prepay_id=" + prepay_id,
'signType': 'MD5',
'timeStamp': timeStamp
}
stringA = '&'.join(["{0}={1}".format(k, pay_data.get(k)) for k in sorted(pay_data)])
stringSignTemp = '{0}&key={1}'.format(stringA, Mch_key)
sign = hashlib.md5(stringSignTemp.encode("utf-8")).hexdigest()
return sign.upper()
二、视图实现一下内容
import datetime
import requests
import time
from rest_framework import status
from rest_framework.response import Response
from rest_framework.views import APIView
from users.models import User
from wxpay import utils
class PayViews(APIView):
# 统一下单支付接口
def post(self, request):
# 获取价格
price = request.data.get("price")
# print(price)
# 获取user_id
user_id = request.data.get("user_id")
# print(user_id)
# 获取客户端ip
client_ip = request.META['REMOTE_ADDR']
# print(client_ip)
# 获取小程序openid
openid = User.objects.get(id=user_id).openid
# 请求微信的url
url = 'https://api.mch.weixin.qq.com/pay/unifiedorder'
# 获取时间戳
timeStamp = str(int(time.time()))
time_data = datetime.date.today()
# 拿到封装好的xml数据
body_data = utils.get_bodyData(openid, client_ip, price, timeStamp, user_id, time_data)
# 请求微信接口下单
respone = requests.post(url, body_data.encode("utf-8"), headers={'Content-Type': 'application/xml'})
# 回复数据为xml,将其转为字典
content = utils.xml_to_dict(respone.content)
if content["return_code"] == 'SUCCESS':
# 获取预支付交易会话标识
prepay_id = content.get("prepay_id")
# 获取随机字符串
nonceStr = content.get("nonce_str")
# 获取paySign签名,这个需要我们根据拿到的prepay_id和nonceStr进行计算签名
paySign = utils.get_paysign(prepay_id, timeStamp, nonceStr)
# 封装返回给前端的数据
data = {"prepay_id": prepay_id, "nonceStr": nonceStr, "paySign": paySign, "timeStamp": timeStamp}
return Response(data=data, status=status.HTTP_200_OK)
else:
return Response("请求支付失败")