【25.0】路飞支付相关

Dream-Z / 2023-08-19 / 原文

【一】订单相关表设计

  • Order 订单表
  • OrderDetail 订单详情表
from django.db import models
from luffyCity.apps.course.models import Course
from luffyCity.apps.user.models import User


# Order  订单表
class Order(models.Model):
    """订单模型"""
    status_choices = (
        (0, '未支付'),
        (1, '已支付'),
        (2, '已取消'),
        (3, '超时取消'),
    )
    pay_choices = (
        (1, '支付宝'),
        (2, '微信支付'),
    )
    subject = models.CharField(max_length=150, verbose_name="订单标题")
    total_amount = models.DecimalField(max_digits=10, decimal_places=2, verbose_name="订单总价", default=0)
    out_trade_no = models.CharField(max_length=64, verbose_name="订单号", unique=True)  # 唯一,不能重复,后期可以根据订单号修改订单状态
    trade_no = models.CharField(max_length=64, null=True, verbose_name="交易流水号")  # 支付宝支付,生成流水号,存起来
    order_status = models.SmallIntegerField(choices=status_choices, default=0, verbose_name="订单状态")
    pay_type = models.SmallIntegerField(choices=pay_choices, default=1, verbose_name="支付方式")
    pay_time = models.DateTimeField(null=True, verbose_name="支付时间")  # 支付宝返回的时间
    user = models.ForeignKey(User, related_name='order_user', on_delete=models.DO_NOTHING, db_constraint=False,
                             verbose_name="下单用户")
    created_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')

    class Meta:
        db_table = "luffy_order"
        verbose_name = "订单记录"
        verbose_name_plural = "订单记录"

    def __str__(self):
        return "%s - ¥%s" % (self.subject, self.total_amount)


# OrderDetail  订单详情表
class OrderDetail(models.Model):
    """订单详情"""
    order = models.ForeignKey(Order, related_name='order_courses', on_delete=models.CASCADE, db_constraint=False,
                              verbose_name="订单")
    course = models.ForeignKey(Course, related_name='course_orders', on_delete=models.CASCADE, db_constraint=False,
                               verbose_name="课程")
    price = models.DecimalField(max_digits=6, decimal_places=2, verbose_name="课程原价")
    real_price = models.DecimalField(max_digits=6, decimal_places=2, verbose_name="课程实价")

    class Meta:
        db_table = "luffy_order_detail"
        verbose_name = "订单详情"
        verbose_name_plural = "订单详情"

    def __str__(self):
        try:
            return "%s的订单:%s" % (self.course.name, self.order.out_trade_no)
        except:
            return super().__str__()
  • 数据库迁移
python ../../manage.py makemigrations
python ../../manage.py migrate

【二】下单接口

【1】分析

(1)前端

  • 前端传入数据

    • 在订单表中插入记录,生成支付链接,返回给前端
  • 前端传入数据

{'subject':'某个课程', 'total_amount':100, 'pay_type':1, 'courses':[1,2,3]}

(2)后端

  • 后端做的事情--要保存,要校验

    • 序列化类来做
  • 1)订单总价校验

  • 2)生成订单号:唯一的

  • 3)获取支付用户:request.user

  • 4)支付链接生成:支付宝支付链接

  • 5)入库(两个表)的信息准备

【2】代码实现

(1)视图类

  • luffyCity\luffyCity\apps\orders\views.py
from django.shortcuts import render
from rest_framework.views import APIView
from rest_framework_jwt.authentication import JSONWebTokenAuthentication
from luffyCity.apps.orders.serializers.OrderSerializers import PaySerializer
from luffyCity.libs.ALiPaySDK import ALiPay
from luffyCity.utils.common_response import CommonResponse
from rest_framework.viewsets import GenericViewSet
from rest_framework.permissions import IsAuthenticated


# Create your views here.

# 测试封装包
class ALiPayView(APIView):
    def get(self, request, *args, **kwargs):
        pay = ALiPay()
        order_id = "201102102102102150"
        total_amount = 644491.03
        order_name = '兰博基尼'
        order_url = pay.create_order_url(order_id=order_id, total_amount=total_amount, order_name=order_name)

        return CommonResponse(order_url=order_url)


class PayOrderView(GenericViewSet):
    serializer_class = PaySerializer
    authentication_classes = [JSONWebTokenAuthentication]
    permission_classes = [IsAuthenticated]

    def create(self, request, *args, **kwargs):
        pay_ser = self.get_serializer(context={"request": request}, data=request.data)
        pay_ser.is_valid(raise_exception=True)
        pay_ser.save()
        pay_url = pay_ser.context.get('pay_url')

        return CommonResponse(msg="保存成功", pay_url=pay_url)

(2)路由

  • luffyCity\luffyCity\apps\orders\urls.py
from django.urls import path

from luffyCity.apps.orders.views import ALiPayView, PayOrderView
from rest_framework.routers import SimpleRouter

router = SimpleRouter()
router.register('pay', PayOrderView, 'pay')

urlpatterns = [
    # path('pay/', ALiPayView.as_view()),
]
urlpatterns += router.urls

(3)序列化类

  • luffyCity\luffyCity\apps\orders\serializers\OrderSerializers.py

【三】支付宝回调

  • 因为咱们 地址是 127.0.0.1

    • 支付宝回调,只能回调公网地址,调不回我们这,我们收不到支付宝的回调--->
  • 解决方案:

    • 1 使用公网ip部署项目
    • 2 使用内网穿透
      https://zhuanlan.zhihu.com/p/370483324