AI学习吧-支付宝支付

支付宝支付流程

1、接收前端发过来的贝里数和结算金额

2、检查贝里数是否够用

3、获取结算中心的课程并应用优惠券

4、应用未绑定课程的优惠券

5、判断总价格减去优惠券价格是否等于实际支付金额

6、生成订单

7、生成去支付宝支付的链接

支付宝支付详细流程

 表结构

 1 class Order(models.Model):
 2     """订单"""
 3     payment_type_choices = ((0, '微信'), (1, '支付宝'), (2, '优惠码'), (3, '贝里'))
 4     payment_type = models.SmallIntegerField(choices=payment_type_choices)
 5     payment_number = models.CharField(max_length=128, verbose_name="支付第3方订单号", null=True, blank=True)
 6     order_number = models.CharField(max_length=128, verbose_name="订单号", unique=True)  # 考虑到订单合并支付的问题
 7     user = models.ForeignKey("User")
 8     actual_amount = models.FloatField(verbose_name="实付金额")
 9 
10     status_choices = ((0, '交易成功'), (1, '待支付'), (2, '退费申请中'), (3, '已退费'), (4, '主动取消'), (5, '超时取消'))
11     status = models.SmallIntegerField(choices=status_choices, verbose_name="状态")
12     date = models.DateTimeField(auto_now_add=True, verbose_name="订单生成时间")
13     pay_time = models.DateTimeField(blank=True, null=True, verbose_name="付款时间")
14     cancel_time = models.DateTimeField(blank=True, null=True, verbose_name="订单取消时间")
15 
16     class Meta:
17         verbose_name_plural = "订单表"
18 
19     def __str__(self):
20         return "%s" % self.order_number
21 
22 class OrderDetail(models.Model):
23     """订单详情"""
24     order = models.ForeignKey("Order")
25 
26     content_type = models.ForeignKey(ContentType)  # 可关联普通课程或学位
27     object_id = models.PositiveIntegerField()
28     content_object = GenericForeignKey('content_type', 'object_id')
29 
30     original_price = models.FloatField("课程原价")
31     price = models.FloatField("折后价格")
32     content = models.CharField(max_length=255, blank=True, null=True)  #
33     valid_period_display = models.CharField("有效期显示", max_length=32)  # 在订单页显示
34     valid_period = models.PositiveIntegerField("有效期(days)")  # 课程有效期
35     memo = models.CharField(max_length=255, blank=True, null=True)
36 
37     def __str__(self):
38         return "%s - %s - %s" % (self.order, self.content_type, self.price)
39 
40     class Meta:
41         verbose_name_plural = "订单详细"
42         unique_together = ("order", 'content_type', 'object_id')
models.py

逻辑

默认-会校验用户是否登录,使用UserAuth

数据格式:
{
      course:
          {1:{choice_price_id:1,coupon_id:2},
            2:{choise_price_id:4,coupon_record_id:3}},

      global_coupon_id:3,

      beli:2000,

      total_money:2000
}

计算价格公式:(课程1原价格*课程1优惠券+课程2原价格*课程2优惠券)*通用优惠券-贝里/10

1.接收前端来的数据
 获取用户的贝里数,课程的头像、名称、价格等信息,全局优惠券,总价格

2.校验数据
    2.1校验贝里数是否在用户拥有的范围之内
    2.2校验课程信息
        2.2.1校验课程是否存在
        2.2.2校验价格策略
        2.2.3校验课程优惠券
        2.2.4计算优惠后的价格-按照三种优惠券分为三种计算方式,
    2.3校验通用优惠券的合法性
    2.4校验最终价格是否一致   #防止别人篡改支付宝的支付信息,让我们受害!!

3.生成订单
    Order记录
    OrderDetail
4.调支付宝接口
    利用支付宝的沙箱环境,使用公钥私钥一些知识,使用Alipay这个类中的逻辑,完成支付宝支付
#payment.py

from
rest_framework.views import APIView from rest_framework.viewsets import ViewSetMixin,ModelViewSet from app01.utils.auth_class import UserAuth from app01.utils.response import BaseResponse from rest_framework.response import Response from app01.utils.exceptions import CommonException from app01.models import Course,CouponRecord,PricePolicy,CourseDetail import datetime class PaymentView(APIView,ViewSetMixin): """ 支付接口===订单接口: 1 接收数据 2 校验数据 3 生成订单(默认未支付状态) --- Order --- OrderDetail --- OrderDetail --- OrderDetail 4 调支付宝的支付接口: 返回的post:修改订单,修改优惠券,修改贝里 返回的get: 查看订单状态 """ authentication_classes = [UserAuth] def create(self, request, *args, **kwargs): ''' 请求发送的数据: { courses:{ 1:{ choose_price_id:1, coupon_id:2, }, 2:{ choose_price_id:4, coupon_record_id:3, }, }, global_coupon_id:3, beli:2000, total_money:2000 } 计算价格优先级 (课程1原价格*课程1优惠券+课程2原价格*课程2优惠券)*通用优惠券-贝里/10 ''' res=BaseResponse() try: # 1 获取数据 user = request.user beli = int(request.data.get("beli", 0)) courses_dict=request.data.get("courses") global_coupon_id=request.data.get("global_coupon_id") total_money=request.data.get("total_money") # 2 校验数据 # 2.1 校验内里数是否在登录用户实际拥有范围内 if user.beli < beli: raise CommonException("贝里数有问题!",1004) # 2.2 校验课程信息 now = datetime.datetime.now() course_price_list=[] for course_pk,course_info in courses_dict.items(): # 2.2.2 校验课程是否存在 course_obj=Course.objects.filter(pk=course_pk).first() if not course_obj: raise CommonException("课程不存在!",1002) if course_obj.status != 0: raise CommonException("课程未上线或者已下线!", 1005) # 2.2.3 校验价格策略 choose_price_id=course_info.get("choose_price_id") price_policy_all=course_obj.price_policy.all() if choose_price_id not in [obj.pk for obj in price_policy_all]: raise CommonException("价格策略错误!",1003) # 2.2.4 校验课程优惠券 coupon_record_id=course_info.get("coupon_record_id") coupon_record=CouponRecord.objects.filter(pk=coupon_record_id, user=user, status=0, coupon__valid_begin_date__lt=now, coupon__valid_end_date__gt=now, ).first() if not coupon_record: raise CommonException("优惠券有问题!", 1006) rel_course_obj=coupon_record.coupon.content_object if course_obj != rel_course_obj: raise CommonException("优惠券与课程不匹配!", 1007) # 计算优惠后的价格 price=PricePolicy.objects.filter(pk=choose_price_id).first().price rebate_price=self.cal_price(price,coupon_record) course_price_list.append(rebate_price) # 2.3 校验通用优惠券合法性 global_coupon_record = CouponRecord.objects.filter(pk=global_coupon_id, user=user, status=0, coupon__valid_begin_date__lt=now, coupon__valid_end_date__gt=now, ).first() if not global_coupon_record: raise CommonException("通用优惠券有问题!", 1009) # 2.4 校验最终价格是否一致 cal_price = self.cal_price(sum(course_price_list), global_coupon_record) final_price = cal_price - beli / 10 if final_price < 0: final_price = 0 if total_money != final_price : raise CommonException("支付价格有问题!", 1010) # 3 生成订单 # Order记录 # OrderDetail # OrderDetail # 4 调用支付宝接口 # alipay = ali() # 生成支付的url # query_params = alipay.direct_pay( # subject="Django课程", # 商品简单描述 # out_trade_no="x2" + str(time.time()), # 商户订单号 # total_amount=money, # 交易金额(单位: 元 保留俩位小数) # ) # # pay_url = "https://openapi.alipaydev.com/gateway.do?{}".format(query_params) # # return redirect(pay_url) # 注意: # POST请求访问notify_url: # 更改订单 # 更改优惠券 # 更改贝里数 # GET请求return_url,用于页面的跳转展示 except CommonException as e: res.code=1004 res.error=e.error return Response(res.dict) def cal_price(self,price,coupon_record): """ price:原价格 coupon_record:优惠券对象 目的:计算优惠后的价格 :param price: :param coupon_record: :return: """ # 获取优惠券的类型 coupon_type=coupon_record.coupon.coupon_type if coupon_type == 0: # 立减券 money_equivalent_value=coupon_record.coupon.money_equivalent_value rebate_price=price - money_equivalent_value if rebate_price < 0 : rebate_price=0 elif coupon_type == 1: # 满减券 minimum_consume=coupon_record.coupon.minimum_consume if price > minimum_consume: money_equivalent_value = coupon_record.coupon.money_equivalent_value rebate_price=price-money_equivalent_value else: raise CommonException("优惠券不符合条件",1008) elif coupon_type == 2: off_percent=coupon_record.coupon.off_percent rebate_price=price*(off_percent/100) else: rebate_price=price return rebate_price

支付逻辑

from django.shortcuts import render, redirect, HttpResponse
from utils.pay import AliPay
import json
import time

def ali():

    # 沙箱环境地址:https://openhome.alipay.com/platform/appDaily.htm?tab=info
    app_id = "2016091100486897"
    # POST请求,用于最后的检测
    notify_url = "http://47.94.172.250:8804/page2/"
    # notify_url = "http://www.wupeiqi.com:8804/page2/"
    # GET请求,用于页面的跳转展示
    return_url = "http://47.94.172.250:8804/page2/"
    # return_url = "http://www.wupeiqi.com:8804/page2/"
    merchant_private_key_path = "keys/app_private_2048.txt"
    alipay_public_key_path = "keys/alipay_public_2048.txt"

    alipay = AliPay(
        appid=app_id,
        app_notify_url=notify_url,
        return_url=return_url,
        app_private_key_path=merchant_private_key_path,
        alipay_public_key_path=alipay_public_key_path,  # 支付宝的公钥,验证支付宝回传消息使用,不是你自己的公钥
        debug=True,  # 默认False,
    )
    return alipay


def page1(request):
    if request.method == "GET":

        return render(request, 'page1.html')
    else:
        money = float(request.POST.get('money'))
        alipay = ali()
        # 生成支付的url
        query_params = alipay.direct_pay(
            subject="Django课程",  # 商品简单描述
            out_trade_no="x2" + str(time.time()),  # 商户订单号
            total_amount=money,  # 交易金额(单位: 元 保留俩位小数)
        )

        pay_url = "https://openapi.alipaydev.com/gateway.do?{}".format(query_params)

        return redirect(pay_url)


def page2(request):
    alipay = ali()
    if request.method == "POST":
        # 检测是否支付成功
        # 去请求体中获取所有返回的数据:状态/订单号
        from urllib.parse import parse_qs
        body_str = request.body.decode('utf-8')
        post_data = parse_qs(body_str)

        post_dict = {}
        for k, v in post_data.items():
            post_dict[k] = v[0]
        print(post_dict)

        sign = post_dict.pop('sign', None)
        status = alipay.verify(post_dict, sign)
        print('POST验证', status)

        if status:
            # 修改订单状态
            pass
        return HttpResponse('POST返回')

    else:
        params = request.GET.dict()
        sign = params.pop('sign', None)
        status = alipay.verify(params, sign)
        print('GET验证', status)
        if status:
             # 获取订单状态,显示给用户
             return HttpResponse('支付成功')
原文地址:https://www.cnblogs.com/djfboai/p/10120158.html