路飞学城项目-支付相关-支付接口

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

"""
支付逻辑
一,前端传递参数,
点击立即支付,应该做什么? 必须要弄清楚这个业务,
前端需要传递什么?  下面就是前端需要传递的数据,
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

 

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

 

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

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

 

posted @ 2020-02-13 02:29  技术改变命运Andy  阅读(157)  评论(0编辑  收藏  举报