千家信息网

python怎么实现微信小程序的多种支付方式

发表于:2024-11-23 作者:千家信息网编辑
千家信息网最后更新 2024年11月23日,本篇内容主要讲解"python怎么实现微信小程序的多种支付方式",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"python怎么实现微信小程序的多种支付方式"
千家信息网最后更新 2024年11月23日python怎么实现微信小程序的多种支付方式

本篇内容主要讲解"python怎么实现微信小程序的多种支付方式",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"python怎么实现微信小程序的多种支付方式"吧!

多支付

原理

1.利用鸭子类型。规定前台传过来支付方式。pay_methon2.再支付方式里面实现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 importlibclass 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支付

# 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支付方式

# YLpay支付方式class YLpay:    def pay(self,order_data):        pass    def notify(self,request_data):        #验签        #数据处理        pass

Wxpay支付方式

import timefrom app01.wx import settingsclass 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

Creat下订单

from  rest_framework.views import  APIViewfrom rest_framework.response import  Responsefrom app01.wx import wx_loginimport hashlib ,timefrom app01 import modelsfrom django.core.cache import cachefrom django.db import transactionfrom app01.func import function_toolimport importlibclass 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怎么实现微信小程序的多种支付方式"有了更深的了解,不妨来实际操作一番吧!这里是网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

0