<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
1.利用鴨子型別。規定前臺傳過來支付方式。pay_methon
2.再支付方式裡面實現pay(名字統一)方法
3.回撥函數,在支付方式裡面寫notify(名字統一)統一方法,返回的data統一格式。
eg: data={"statu":'success',"order_id":notity_data['order_id'],"print":"0000"}
這樣的的牛逼之處:我們在修改、新增支付方式的時候,只需要按照鴨子型別,命名一樣的函數名,寫好自己的支付方式即可。不需要改其他的程式碼
urls.py:
path("order/create",order.Creat.as_view()), path("order/notify/<paymethod>",order.Notify.as_view())
# 這裡所有的支付都是走的小程式微信支付: import importlib class Creat(APIView): ...虛擬碼 pay_methon = "Wxpay" # 如果是PC端,可以前臺傳過來支付方式 try: #pay_file是物件 pay_file = importlib.import_module(f"app01.Pay.{pay_methon}") # 呼叫對應的支付方式 pay_class = getattr(pay_file, pay_methon) # 反射機制 order_data['open_id'] = openid # 傳的引數 order_data['ip'] = host_ip # 傳的引數 data = pay_class().pay(order_data) # 呼叫支付 except: return Response({"code":201,"msg":"未知支付方式"}) # 非同步回撥的 class Notify(APIView): def post(self,request,paymethod): pay_file = importlib.import_module(f"app01.Pay.{paymethod}") pay_class = getattr(pay_file,paymethod) data = pay_class().notify(request.data) # 呼叫非同步回撥 # 判斷data資料中屬性,然後修改訂單 if data["statu"] == "success": models.Order.objects.filter(order_id =data['order_id']).update(pay_status =1) return Response(data["print"])
# Alipay支付 class Alipay: def pay(self,order_data): #統一下單方法 pass def notify(self,notity_data): if notity_data['success'] : #notity_data['order_id']表示商城訂單號 data={"statu":'success',"order_id":notity_data['order_id'],"print":"0000"} return data
# YLpay支付方式 class YLpay: def pay(self,order_data): pass def notify(self,request_data): #驗籤 #資料處理 pass
import time from app01.wx import settings class Wxpay: def pay(self,order_data): self.order_id = order_data["order_id"] self.open_id = order_data['open_id'] self.ip = order_data['ip'] data_body = self.get_body_data() import requests url = "https://api.mch.weixin.qq.com/pay/unifiedorder" response = requests.post(url, data_body.encode("utf-8"), headers={'content-type': "application/xml"}) res_dict = self.xml_to_dic(response.content) timeStamp = str(int(time.time())) paySign = self.get_pay_sign(res_dict, timeStamp) data_dic = { 'timeStamp': timeStamp, 'nonceStr': res_dict['nonce_str'], 'package': f"prepay_id={res_dict['prepay_id']}", 'signType': 'MD5', "paySign": paySign, } return data_dic def get_pay_sign(self, res_dict, timeStamp): data_dic = { 'appId': res_dict['appid'], 'timeStamp': timeStamp, 'nonceStr': res_dict['nonce_str'], 'package': f"prepay_id={res_dict['prepay_id']}", "signType": "MD5" } sign_str = "&".join([f"{k}={data_dic[k]}" for k in sorted(data_dic)]) sign_str = f"{sign_str}&key={settings.pay_apikey}" import hashlib md5 = hashlib.md5() md5.update(sign_str.encode("utf-8")) sign = md5.hexdigest() return sign.upper() def xml_to_dic(self, xml_data): import xml.etree.ElementTree as ET ''' 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 def get_random(self): import random data = "123456789zxcvbnmasdfghjklqwertyuiopZXCVBNMASDFGHJKLQWERTYUIOP" nonce_str = "".join(random.sample(data, 30)) return nonce_str def get_sign(self): data_dic = { "nonce_str": self.nonce_str, "out_trade_no": self.out_trade_no, "spbill_create_ip": self.spbill_create_ip, "notify_url": self.notify_url, "openid": self.open_id, "body": self.body, "trade_type": "JSAPI", "appid": self.appid, "total_fee": "1", "mch_id": self.mch_id } sign_str = "&".join([f"{k}={data_dic[k]}" for k in sorted(data_dic)]) sign_str = f"{sign_str}&key={settings.pay_apikey}" import hashlib md5 = hashlib.md5() md5.update(sign_str.encode("utf-8")) sign = md5.hexdigest() return sign.upper() def get_body_data(self): self.appid = settings.AppId # openid=self.open_id self.mch_id = str(settings.pay_mchid) self.nonce_str = self.get_random() self.out_trade_no = self.order_id self.spbill_create_ip = self.ip self.notify_url = "https://www.test.com" self.body = "老男孩學費" self.sign = self.get_sign() body_data = f""" <xml> <appid>{self.appid}</appid> <mch_id>{self.mch_id}</mch_id> <nonce_str>{self.nonce_str}</nonce_str> <sign>{self.sign}</sign> <body>{self.body}</body> <out_trade_no>{self.out_trade_no}</out_trade_no> <total_fee>1</total_fee> <spbill_create_ip>{ self.spbill_create_ip}</spbill_create_ip> <notify_url>{self.notify_url}</notify_url> <openid>{self.open_id}</openid> <trade_type>JSAPI</trade_type> </xml>""" return body_data
from rest_framework.views import APIView from rest_framework.response import Response from app01.wx import wx_login import hashlib ,time from app01 import models from django.core.cache import cache from django.db import transaction from app01.func import function_tool import importlib class Creat(APIView): @transaction.atomic def post(self,request): #小程式提交給我們的資料 ''' {'token': '0bb2aa1102ca9c8306133b2539c3508b', 'remark': '', 'province': '廣東省', 'city': '廣州市', 'county': '海珠區', 'address': '新港中路397號', 'phone': '020-81167888', 'name': '張三', 'buy_list': {'2': 1}} ''' param = request.data if param.get("token") and param.get("buy_list"): user_cache = cache.get(param["token"]) if user_cache: # 獲取ip if request.META.get("HTTP_X_FORWARDED_FOR"): host_ip = request.META["HTTP_X_FROWARDED_FOR"] else: host_ip = request.META["REMOTE_ADDR"] openid = user_cache.split("&")[0] #data['openid']+"&"+data["session_key"] user_data = models.Wxuser.objects.filter(openid=openid).first() order_data = { "consignee_mobile": param['phone'], 'consignee_name': param['name'], 'wxuser_id': user_data.id, "memo": param['remark'], "consignee_area": f"{param['province']},{param['city']},{param['county']}", "consignee_address": param['address'], "order_id": function_tool.get_order_id(), "order_total": 0 } # 1 上面的order_data 出來上面的資料,有些是需要通過購買上面列表做累加才能獲得到 # 2 order_item 是通過buy_list裡面的商品列表,一個鍵值對就是一條記入'buy_list': {'2': 1,「1」:2} # 3 再每一次增加一個order_item的時候,我們都需要校驗庫存。如果有一個商品的庫存不足,我們就應該不然使用者下單 # 4 由於第三步中進行多次增加,如果再後面的的商品庫存有問題,我們不讓他下單,但是前面的資料已經插入。 # 所有我們要用資料庫的事務管理資料的統一。就算order_item沒有問題,order_data,插入的時候,也可能出錯,所以也要用事務 # 5 由於並行問題,所有的使用者都會對資料的庫存進行加減,所以我們這裡再校驗庫存的時候要用鎖。 buy_list = param.get("buy_list") # 獲取到buy_list是沒有商品資訊只有有id,我們先把buy_list中的所有商品查出來 goods_key = list(buy_list.keys()) all_product = models.Product.objects.filter(product_id__in = goods_key) #用for迴圈新增order_item sid = transaction.savepoint() for product in all_product: # 將product.product_id 轉字串,為了通過product.product_id在buy_list獲取商品的購買數量 product.product_id = str(product.product_id) # 獲取訂單總金額 order_data['order_total'] += product.price* buy_list[product.product_id] for i in range(3): #先查庫存,重新查庫的 stock = product.stock.quantity #當前的庫存的庫存數量,減去購買數量,是否大於0 new_stock = stock-buy_list[product.product_id] if new_stock < 0 : #庫存不足,回滾 transaction.savepoint_rollback(sid) return Response({"code":201,"msg": f"{product.name}庫存不足"}) #樂觀鎖 res = models.Stock.objects.filter(quantity= stock,stock_id =product.stock.stock_id).update(quantity = new_stock) if not res: if i == 2: transaction.savepoint_rollback(sid) return Response({"code":201,"msg": "建立訂單失敗"}) else: continue else: break #獲取購買數量 new_buy_cout = product.buy_count + buy_list[product.product_id] models.Product.objects.filter(product_id=product.product_id).update(buy_count =new_buy_cout) #組織order_item的資料 order_item_data = { 'order_id': order_data['order_id'], 'product_id': product.product_id, "name": product.name, "image": product.image, "price": product.price, "nums": buy_list[product.product_id], "brief": product.brief } models.Order_items.objects.create(**order_item_data) models.Order.objects.create(**order_data) transaction.savepoint_commit(sid) #所有的支付都是走的小程式微信支付: pay_methon = "Wxpay" try: #pay_file是物件 pay_file = importlib.import_module(f"app01.Pay.{pay_methon}") pay_class = getattr(pay_file, pay_methon) order_data['open_id'] = openid order_data['ip'] = host_ip data = pay_class().pay(order_data) except: return Response({"code":201,"msg":"未知支付方式"}) # 1對接小程式支付 # 2 我們要用celery去定時檢查,該訂單在指定時間內用沒有支付,沒有支付,取消訂單,回滾庫存 function_tool.pay_status(order_data['order_id']) return Response({"code":200,"msg":"ok","data":data}) else: return Response({"code": 201, "msg": "無效的token"}) else: return Response({"code":202,"msg":"缺少引數"}) class Notify(APIView): def post(self,request,paymethod): pay_file = importlib.import_module(f"app01.Pay.{paymethod}") pay_class = getattr(pay_file,paymethod) data = pay_class().notify(request.data) # 判斷data資料中屬性,然後修改訂單 if data["statu"] == "success": models.Order.objects.filter(order_id =data['order_id']).update(pay_status =1) return Response(data["print"])
以上就是python實現微信小程式的多種支付方式的詳細內容,更多關於python微信支付方式的資料請關注it145.com其它相關文章!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45