
流程搞清楚就行 我就直接丢代码了 ==文档==
# 支付接口
class Pay(APIView):
def post(self, request, *args, **kwargs):
login_key = request.data.get('login_key')
if not login_key:
return Response({'status': 400, 'msg': '参数错误'})
data_list = cache.get(login_key)
if not data_list:
return Response({'status': 400, 'msg': '没有login_key对应的值'})
session_key, open_id = data_list.split('&')
# 把open_id放入self中 写pay方法
self.open_id = open_id
# 获取ip
# 使用负载均衡 获取ip方法
if request.META.get('HTTP_X_FORWARDED_FOR'):
self.ip =request.META.get('HTTP_X_FORWARDED_FOR')
else:
# 原本的ip获取
self.ip = request.META.get('REMOTE_ADDR')
data = self.pay()
return Response({'status': 200, 'msg': 'ok', 'data':data})
# 随机字符串
def get_str(self):
str_all = '1234567890abcdefjhigklmnpqrstuvwxyz'
nonce_str = ''.join(random.sample(str_all, 20))
return nonce_str
# 签名
def get_sign(self):
# sign 不参与签名
data_dic = {
"nonce_str": self.nonce_str,
"out_trade_no": self.out_trade_no,
"spbill_create_ip": self.ip,
"notify_url": self.notify_url,
"openid": self.open_id,
"body": self.body,
"trade_type": "JSAPI",
"appid": self.app_id,
"total_fee": self.total_fee,
"mch_id": self.pay_mchid
}
# 拼接
# sorted 按照ASCII 排序
sign_str = "&".join([f"{k}={data_dic[k]}" for k in sorted(data_dic)])
sign_str = f"{sign_str}&key{setting.pay_apikey}"
md5 = hashlib.md5()
md5.update(sign_str.encode('utf-8'))
return md5.hexdigest().upper()
# 订单id
def get_order_id(self):
order_id = str(time.strftime('%Y%m%d%X'))
return order_id
# xml转dic
def xml_to_dic(self, xml):
import xml.etree.ElementTree as ET
xml_dict = {}
data_dic = ET.fromstring(xml)
for item in data_dic:
xml_dict[item.tag] = item.text
return xml_dict
# 支付接口
def pay(self):
self.app_id = setting.APP_ID
self.pay_mchid = setting.pay_mchid
self.pay_apikey = setting.pay_apikey
self.nonce_str = self.get_str()
# 订单id
self.out_trade_no = self.get_order_id()
self.body = '龙哥的生活费'
self.total_fee = 1
self.spbill_create_ip = self.ip
# 回调地址
self.notify_url = 'https://www.baidu.com'
self.trade_type = 'JSAPI'
# 签名
self.sign = self.get_sign()
# 数据加密 且 变成xml形式
data = f"""
<xml>
<appid>{self.app_id}</appid>
<body>{self.body}</body>
<mch_id>{self.pay_mchid}</mch_id>
<nonce_str>{self.nonce_str}</nonce_str>
<notify_url>{self.notify_url}</notify_url>
<openid>{self.open_id}</openid>
<out_trade_no>{self.out_trade_no}</out_trade_no>
<spbill_create_ip>{self.spbill_create_ip}</spbill_create_ip>
<total_fee>{self.total_fee}</total_fee>
<trade_type>{self.trade_type}</trade_type>
<sign>{self.sign}</sign>
</xml>
"""
# 发起请求
url = 'https://api.mch.weixin.qq.com/pay/unifiedorder'
response = requests.post(url=url, data=data.encode('utf-8'),
headers={'content-type':'application/xml'}
)
data = self.xml_to_dic(response.content) # 二进制数据
data = self.two_sign(data['prepay_id'])
return data
# 再次签名
def two_sign(self, prepay_id):
data_dict = {
"appId": setting.APP_ID,
"timeStamp": str(int(time.time())),
"nonceStr": self.get_str(),
"package": f"prepay_id={prepay_id}",
"signType": "MD5"
}
sign_str = "&".join([f"{k}={data_dict[k]}" for k in sorted(data_dict)])
sign_str = f"{sign_str}&key={setting.pay_apikey}"
md5 = hashlib.md5()
md5.update(sign_str.encode("utf-8"))
sign=md5.hexdigest().upper()
data_dict["paySign"]=sign
data_dict.pop("appId")
return data_dict