您好,登錄后才能下訂單哦!
本篇內容主要講解“python怎么實現微信小程序的多種支付方式”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“python怎么實現微信小程序的多種支付方式”吧!
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怎么實現微信小程序的多種支付方式”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。