zoukankan      html  css  js  c++  java
  • 递归与树的写法-多种支付的设计-支付的接通-celery订单的回退实现

    递归与树的写法

    data:

    data=[
        {"cat_id":1,"name":"北京","parent_id":0},
        {"cat_id":2,"name":"上海","parent_id":0},
        {"cat_id":3,"name":"沙河","parent_id":1},
        {"cat_id":4,"name":"sb镇","parent_id":3},
        {"cat_id":5,"name":"昌平","parent_id":1},
        {"cat_id":6,"name":"青浦","parent_id":2},
    ]
    #需求
    '''
    问题:
    我们数据不是有序的,但是我们要排序,并归类,把父集放在子集的前面,辈分等级通过level标明
    
    '''

     实现的方法

    res=[]
    def get_son(data,level=0,parent_id=0,is_clear=True):
        if is_clear:
            res.clear()
        for item in data:
            if item['parent_id']==parent_id:
                item['level']=level
                res.append(item)
                get_son(data,level=level+1,parent_id=item['cat_id'],is_clear=False)
        return res

    实现树状的等级分类

    '''
    问题:
    
    因为前端,需要通过循环多少成来,展示多个等级
    for item in data:
        print(item.name)
        for item1 in item.children 
            item1.name
            
    归档:我要把我的子集,都放在我的children列表里面
             
    '''
    def get_tree(data):
        lists=[]
        tree={}
        for i in data:
            tree[i['cat_id']]=i
        for item in data:
            if not item['parent_id']:
                lists.append(tree[item['cat_id']])
            else:
                if "children" not in tree[item['parent_id']]:
                    tree[item['parent_id']]['children']=[]
                tree[item['parent_id']]['children'].append(tree[item['cat_id']])
        return lists

    分析

     多种支付的设计

      例如实现微信或支付宝等支付接口的封装.

     

    封装的支付接口方法

    class Notity(APIView):
        def post(self,request,paymethon):
            pay_file = importlib.import_module(f"app01.Pay.{paymethon}")
            pay_class = getattr(pay_file, paymethon)
            data=pay_class().notity(request.data)
            if data['status']=="success":
                models.Order.objects.filter(order_id=data['order']).updata(pay_status=1)

    pay.Alipay.py

    class Alipay():
        def pay(self):
            pass
            "order/notify/Alipay"
    
        def notity(self,data):
            data['shangcheng_id']
            data['sucess']
            if data['sucess']="00":
                return_data['stauts']="success"
                return_data['order_id'] = data['shangcheng_id']
                return  return_data
            else:
                pass

    pay.Wxpay.py

    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

     支付的接通

    from rest_framework.views import APIView
    from rest_framework.response import  Response
    from django.core.cache import cache
    from  app01 import models
    
    import hashlib,time
    from django.db import transaction
    
    from django import forms
    import importlib
    
    class OrderForm(forms.Form):
        phone = forms.CharField(
            error_messages={
                "required": "手机号不能为空"
            },
            # 调用Form组件中的验证器来校验手机号
           # validators=[RegexValidator(r'1[1-9][0-9]{9}', '手机号格式不正确')],
        )
        token = forms.CharField( error_messages={
                "required": "token不能为空"
            })
        province=forms.CharField( error_messages={
                "required": "省份不能为空"
            })
        city = forms.CharField(error_messages={
            "required": "城市不能为空"
        })
        county = forms.CharField(error_messages={
            "required": "县/区不能为空"
        })
        address = forms.CharField(error_messages={
            "required": "详细地址不能为空"
        })
        name = forms.CharField(error_messages={
            "required": "姓名不能为空"
        })
    class Creat(APIView):
        @transaction.atomic
        def post(self,request):
            param=request.data
            form_obj=OrderForm(param)
    
            if form_obj.is_valid() and param['buy_list']:
                if request.META.get("HTTP_X_FORWARDED_FOR"):
                    host_ip = request.META["HTTP_X_FROWARDED_FOR"]
                else:
                    host_ip = request.META["REMOTE_ADDR"]
                user_cache=cache.get(param['token'])
                if user_cache:
                    openid=user_cache.split("&")[0]
                    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'] ,
                                  }
                    buy_list=param['buy_list']
                    goods_key=list(buy_list.keys())
                    all_product=models.Product.objects.filter(product_id__in=goods_key)
                    order_data['order_id']=func.get_order_id()
                    order_data['order_total']=0
                    order_data['quantity']=0
                    #开启库存
                    sid=transaction.savepoint()
                    for product in all_product:
                        product.product_id=str(product.product_id)
                        order_data['order_total']+=product.price*buy_list[product.product_id]
                        order_data['quantity']+=buy_list[product.product_id]
    
                        #创建子订单
                        for i in range(3):
                            #查询当前库存
                            stock=product.stock.quantity
                            #当前减轻购买的数量,等于剩余的库存
                            new_stock=stock-buy_list[product.product_id]
                            #判断库存是否足够
                            if new_stock<0:
                                #回滚
                                transaction.savepoint_rollback(sid)
                                #如果库存不住够,我们直接返回
                                return Response({"code":203,"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": 203, "msg": f"创建订单失败"})
                                else:
                                    continue
                            else:
                                break
                        new_buy_count = product.buy_count + buy_list[product.product_id]
                        models.Product.objects.filter(product_id=product.product_id).update(buy_count=new_buy_count)
                        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)
                    pay_methon="Wxpay"
                    try:
                        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:
                        transaction.savepoint_rollback(sid)
                        return Response({"code": 200, "msg": "未知的支付方式" })
    
                    transaction.savepoint_commit(sid)
                    func.add_task(order_data['order_id'])
                    return Response({"code": 200, "msg": "ok" ,"data":data})
    
                else:
                    return Response({"code":202,"msg":"token已过期"})
            else:
                return Response({"code":201,"msg":"缺少参数"})

    celery实现订单的回退

      简单的理解就是通过celery异步回调的机制,设置代码段过多少时间之后再去工作,把发起订单后为支付的数据信息返回。

    task方法:

    from pro_celery.celery import del_order
    def add_task(order_id,seconds=5):
        ctime = datetime.now()
        utc_ctime = datetime.utcfromtimestamp(ctime.timestamp())
        from datetime import timedelta
        time_delay = timedelta(seconds=seconds)
        task_time = utc_ctime + time_delay
        result = del_order.apply_async(args=[order_id, ], eta=task_time)

    celery.py方法的封装

    import celery
    import time
    # broker='redis://127.0.0.1:6379/2' 不加密码
    backend='redis://127.0.0.1:6379/1'
    broker='redis://127.0.0.1:6379/2'
    cel=celery.Celery('test',backend=backend,broker=broker)
    
    
    import os, sys
    import django
    BASE_DIR = os.path.dirname(os.path.dirname(__file__))  # 定位到你的django根目录
    # sys.path.append(os.path.join(BASE_DIR, "app01"))
    sys.path.append(os.path.abspath(BASE_DIR))
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "wxshop.settings")
    django.setup()
    from django.db import transaction
    
    
    @cel.task
    @transaction.atomic
    def del_order(order_id):
        '''
        1 拿订单查询,订单号,是否支付,活跃
        2 判断data是否有
    
        :param order_id:
        :return:
        '''
        from app01 import models
        data=models.Order.objects.filter(order_id=order_id,pay_status=0,status="active").first()
        if  data:
            item_data=models.Order_items.objects.filter(order_id=order_id).values("product","nums")
            # [{product:1,nums:3}]
            # {1:3,2:1}
            all_product_dict = { k['product']:k['nums'] for k in item_data}
            all_product_id =list(all_product_dict.keys())
            products_all=models.Product.objects.filter(product_id__in=all_product_id)
            sid=transaction.savepoint()
    
            for product in  products_all:
                for i in range(3):
                    stock=product.stock.quantity
                    new_stock=stock+all_product_dict[product.product_id]
                    new_buy_count=product.buy_count-all_product_dict[product.product_id]
                    res=models.Stock.objects.filter(quantity=stock,stock_id=product.stock).update(quantity=new_stock)
                    if  not res:
                        if i==2:
                            from app01.comment import func
                            transaction.savepoint_rollback(sid)
                            func.add_task(order_id,1)
                            return
                        else:
                            continue
                    else:
                         break
                models.Product.objects.filter(product_id=product.product_id).update(buy_count=new_buy_count)
    
            row=models.Order.objects.filter(order_id=order_id,pay_status=0).update(status="dead")
            if row:
                transaction.savepoint_commit(sid)
            else:
                transaction.savepoint_rollback(sid)

     

  • 相关阅读:
    java读写文件
    idea文件全部变红, 文件全部红色
    PowerDesigner连接MySQL数据库
    mysql 使用ip地址连接不上;MySQL 可以用localhost 连接,但不能用IP连接的问题,局域网192.168.*.* 无法连接mysql
    powerdesigner连接MySQL数据库时出现Non SQL Error : Could not load class com.mysql.jdbc.Driver
    JSP的九大对象和四大作用域
    C#面试问题及答案
    数据库面试题及答案
    多态的深入理解
    面向对象编程----继承---笔记
  • 原文地址:https://www.cnblogs.com/Gaimo/p/11830626.html
Copyright © 2011-2022 走看看