流程搞清楚就行 我就直接丢代码了 ==文档==
# 支付接口 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