zoukankan      html  css  js  c++  java
  • 路飞学城项目-支付相关-支付接口

     ###############     支付接口    ################

    """
    支付逻辑
    一,前端传递参数,
    点击立即支付,应该做什么? 必须要弄清楚这个业务,
    前端需要传递什么?  下面就是前端需要传递的数据,
    1,优惠券的信息都不需要发,都在redis里面放着呢,
    2,一定要传递最后的应付金额,不能说前面看到900,后台最后支付是1000了,后端和前端的计算要校验一致,
    3,只有支付宝支付,所以不需要支付方式,
    所以点击立即支付之后,需要传递贝里金额,和总金额
    {
        beili : 100
        money : 900
    }
    
    二,后端处理;
    1,获取前端传过来的数据,有贝里和总金额,
    2,数据验证,
        2.1 需要两个值都是大于等于0的,
        2.2 个人账户是否有100贝里,余额不足就不能往下走,
    3,去结算中心获取课程信息,课程信息可能会有多个,需要循环课程信息
    payment_userid_courseid : {
        course_id:1
        title
        img
        price_policy_id:1
        coupon_id :{
                    1: {  }
                    2: {  }
                }
        default_coupoon:
        period:
        period_display:
        price:
        }
    payment_global_coupon_用户ID: {
      'coupon': {
          2: {'money_equivalent_value': 200},  # 优惠券 ID :{优惠券信息}
      },
      'default_coupon': 0
    }
        3.1 校验课程,检查课程是否还在有效期,或者上线状态,
        3.2 价格策略是否合法,是否在存在
        3.3 校验优惠券是否合法,
        3.4 获取原价和优惠券类型,
            如果是立减,就是原价-优惠金额,如果是结果是负数,就是直接0.
            如果是满减,判断是否满足最低的限制,
            如果是折扣,就是原价*折扣比例,
    4,通用优惠券处理:
        4.1 通用优惠券是否合法
            如果是立减,就是原价-优惠金额,如果是结果是负数,就是直接0.
            如果是满减,判断是否满足最低的限制,
            如果是折扣,就是原价*折扣比例,
        这一步之后就是实际支付的金额了,
    5,处理beli
        4.1 计算beli是否充足
        4.2 计算beli后的价格
    6,总金额校验
         实际支付-贝里就是应付金额了,需要和前端传过来的paymoney判断是否一致
         最终金额的计算方式,先计算每一个课程的原价-优惠券=折扣价,然后所有课程的折扣价加起来,然后再去-通用优惠券,得到最终的价格,
    7,生成订单,如果是一个订单买了三个课程
    这里面是基于事务来操作的,要么都成功,要么都失败,
        订单表生成数据,
        订单详细表生成三条数据,并且对应的生成三条已报名课程的记录,
        报名表,需要生成记录,
        如果有贝里,第一个还需要生成贝里的交易记录,第二个,余额字段需要扣除,
        优惠券的状态更新,
        注意:如果支付金额是0,直接不用调用支付宝接口了,订单状态就是已支付,
        注意:如果支付金额是大于0,就要调用支付宝的接口了,
            生成url,包含了订单号,
            回调函数用来更新订单状态,
    
    """

     ###############     支付接口    ################

    from django.core.exceptions import ObjectDoesNotExist
    from utils.pay import AliPay
    import time
    class PaymentView(APIView):
        # 前端需要传递什么?  下面就是前端需要传递的数据,
        # {
        # pay_money:800
        # course_info :[
        #                 {
        #                 course_id:1
        #                 price_policy_id:1
        #                 coupon_record_id :1
        #                   },
        #                 {
        #                 course_id:2
        #                 price_policy_id:5
        #                 coupon_record_id :2
        #                   }
        # ]
        # global_coupon_id :1
        # beli:1000
        # }
    
        authentication_classes = [TokenAuth, ]
        def post(self,request):
            now = datetime.datetime.utcnow()
            res = BaseException()
            # 1,获取前端传过来的数据
            user = request.user
            courses_info = request.data.get('courses_info')
            global_coupon_id = request.data.get('global_coupon_id')
            beli = request.data.get('beli')
            pay_money = request.data.get('pay_money')
            print(courses_info,global_coupon_id,beli,pay_money)
            # 2,循环课程信息
            course_price_list = []
            try:
                for course_info in courses_info:
                    course_id = course_info.get('course_id')
                    price_policy_id = course_info.get('price_policy_id')
                    coupon_id = course_info.get('coupon_record_id')
                    print(course_id,price_policy_id,coupon_id)
                #     2.1 校验数据
                #     2.2 校验课程是否存在,
                    course_obj= models.Course.objects.get(id=course_id)
                #     2.3 价格策略是否合法,
                    if price_policy_id not in [obj.pk for obj in course_obj.price_policy.all()]:
                        raise CommentException(1051,'价格策略不存在')
    
                #     2.4 校验优惠券是否合法
                    coupon_record = models.CouponRecord.objects.filter(
                        pk = coupon_id,
                        # account = request.user,
                        # status=0,
                        # coupon__valid_begin_date__lte=now,
                        # coupon__valid_end_date__gte=now,
                        # coupon__object_id=course_id
                    ).first()
                    print(coupon_record)
                    if not coupon_record:
                        raise CommentException(1052,'优惠券有问题')
                #     2.5 计算课程优惠券的折后价
                    # 要根据不同的优惠券类型来计算
                    course_price = models.PricePolicy.objects.get(pk= price_policy_id).price
                    print(course_price)
                    coupon_price = self.coupon_price(course_price,coupon_record)
                    course_price_list.append(coupon_price)
                    print(course_price_list)
                # 3,通用优惠券处理:
                #     3.1 通用优惠券是否合法
                global_coupon_record = models.CouponRecord.objects.filter(
                    pk=global_coupon_id,
                    account=request.user,
                    status=0,
                    coupon__valid_begin_date__lte=now,
                    coupon__valid_end_date__gte=now,
                    coupon__object_id=None
                ).first()
                if not global_coupon_record:
                    raise CommentException(1053,'通用优惠券有问题')
                #     计算通用优惠券后的价格
                global_coupon_price = self.coupon_price(sum(course_price_list),global_coupon_record)
                print(global_coupon_price)
    
                # 4,处理beli
                #     4.1 计算beli是否充足
                if beli >request.user.beli:
                    raise CommentException(1054,'beli数不足')
                #     4.2 计算beli后的价格
                final_price = global_coupon_price - beli/10
                print(final_price)
                if final_price < 0:
                    final_price = 0
                # 5,比较参数和paymoney是否一致
                if final_price != pay_money:
                    raise CommentException(1055,'实际支付价格和参数价格不一致')
    
                # 7,生成订单
                # 订单表
                # 订单详情表
    
                # 8 ,构建支付宝的二维码页面的url,
    
                alipay = self.get_alipy()
    
                query_params = alipay.direct_pay(
                    subject="充气式韩红",  # 商品简单描述
                    out_trade_no="x2" + str(time.time()),  # 商户订单号
                    total_amount=pay_money,  # 交易金额(单位: 元 保留俩位小数)
                )
    
                pay_url = "https://openapi.alipaydev.com/gateway.do?{}".format(query_params)
    
                res.data='订单创建成功'
                res.url = pay_url
            except ObjectDoesNotExist as e:
                res.code =1050
                res.error='课程信息不存在'
            except CommentException as e:
                res.code =e.code
                res.error=e.msg
            except Exception as e:
                res.code = 500
                res.error = str(e)
            return Response(res.dict)
    
    
        def coupon_price(self,price,coupon_record):
            coupon_type = coupon_record.coupon.coupon_type
            money_equivalent_value = coupon_record.coupon.money_equivalent_value
            off_percent = coupon_record.coupon.off_percent
            minimum_consume = coupon_record.coupon.minimum_consume
    
            rebate_price = 0
            if coupon_type==0:
                rebate_price = price-money_equivalent_value
                if rebate_price<0:
                    rebate_price=0
            elif coupon_type==1:
                if price<minimum_consume:
                    raise CommentException('不满足最低消费',1054)
            else:
                rebate_price*off_percent/100
            return rebate_price
    
    
        def get_alipy(self):
    
            obj = AliPay(
                appid=settings.APPID,
                app_notify_url=settings.NOTIFY_URL,  # 如果支付成功,支付宝会向这个地址发送POST请求(校验是否支付已经完成)
                return_url=settings.RETURN_URL,  # 如果支付成功,重定向回到你的网站的地址。
                alipay_public_key_path=settings.PUB_KEY_PATH,  # 支付宝公钥
                app_private_key_path=settings.PRI_KEY_PATH,  # 应用私钥
                debug=True,  # 默认False,
            )
            return obj

     ###############     支付接口    ################

     ###############     支付接口    ################

     ###############     支付接口    ################

  • 相关阅读:
    DOM
    ES6的export和import
    JavaScript:Location
    垃圾回收机制之一:标记删除算法
    KnockoutJS:
    package.json
    2016/7/27
    requirejs:研究笔记
    postmessage/cors跨域postMessage、xhr2和xmldomain
    javascript:算法之数组sort排序
  • 原文地址:https://www.cnblogs.com/andy0816/p/12302097.html
Copyright © 2011-2022 走看看