首页 > 其他分享 >【25.0】路飞支付相关

【25.0】路飞支付相关

时间:2023-08-19 17:35:01浏览次数:43  
标签:25.0 name models pay self 路飞 支付 import order

【一】订单相关表设计

  • 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
# -*-coding: Utf-8 -*-
# @File : OrderSerializers .py
# author: Chimengmeng
# blog_url : https://www.cnblogs.com/dream-ze/
# Time:2023/8/13
import uuid
from luffyCity.libs.ALiPaySDK import ALiPay
from rest_framework import serializers
from rest_framework.exceptions import APIException
from luffyCity.apps.course.models import Course
from luffyCity.apps.orders.models import Order, OrderDetail


# 校验 -- 保存
class PaySerializer(serializers.ModelSerializer):
    '''
    - 1)订单总价校验
    - 2)生成订单号:唯一的
    - 3)获取支付用户:request.user
    - 4)支付链接生成:支付宝支付链接
    - 5)入库(两个表)的信息准备
    '''
    # 要支持单购物和群购物(购物车),前台要提交 课程主键(们)
    # PrimaryKeyRelatedField:前端传入 [1,2,3] ---帮我们转成---> [id为1的课程对象,id为2的课程对象,id为3的课程对象]
    courses = serializers.PrimaryKeyRelatedField(queryset=Course.objects.all(), write_only=True, many=True)

    class Meta:
        model = Order
        fields = ['subject', 'total_amount', 'pay_type', 'courses']

    def _check_price(self, attrs):
        '''
        (1)取出前端传入的总价格
        (2)计算总价格,核验总价格
        :return:
        '''
        # (1)取出前端传入的总价格
        total_amount = attrs.get('total_amount')
        # (2)计算总价格,核验总价格
        # course 经过上面的字段序列已经转成了对象
        courses = attrs.get('courses')
        real_total_amount = 0
        for course in courses:
            real_total_amount += course.price
        if not real_total_amount == total_amount:
            raise APIException("两次价格不一致")

    def _create_order_id(self):
        return str(uuid.uuid4())

    def _get_user(self):
        request = self.context.get('request')
        return request.user

    def _get_pay_url(self, order_id, subject, total_amount, pay_type):
        # pay_type 如果是多方式付款,这里需要判断一下
        pay = ALiPay()
        pay_url = pay.create_order_url(order_id=order_id, total_amount=float(total_amount), order_name=subject)
        return pay_url

    def validate(self, attrs):
        # 1)订单总价校验
        self._check_price(attrs)
        # 2)生成订单号:唯一的
        order_id = self._create_order_id()
        # 3)获取支付用户:request.user
        user = self._get_user()
        # 4)支付链接生成:支付宝支付链接
        pay_url = self._get_pay_url(order_id, attrs.get('subject'), attrs.get('total_amount'), attrs.get('pay_type'))
        # 5)入库(两个表)的信息准备
        attrs['user'] = user
        attrs['out_trade_no'] = order_id
        self.context['pay_url'] = pay_url
        # 当前 attrs 中数据 {'subject', 'total_amount', 'pay_type', 'courses','user','order_id'}
        return attrs

    def create(self, validated_data):
        # 当前 attrs 中数据 {'subject', 'total_amount', 'pay_type', 'courses','user','order_id'}
        courses = validated_data.pop('courses')
        order = Order.objects.create(**validated_data)
        for course in courses:
            OrderDetail.objects.create(order=order, course=course, price=course.price, real_price=course.price)

        return order

【三】支付宝回调

  • 因为咱们 地址是 127.0.0.1

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

标签:25.0,name,models,pay,self,路飞,支付,import,order
From: https://www.cnblogs.com/dream-ze/p/17642754.html

相关文章

  • 【5.0】路飞项目之数据库相关
    【一】软件开发模式【1】BBSBBS(BulletinBoardSystem)是一种基于电子信息交流的系统,通常用于在线讨论和发布信息。BBS使用了瀑布开发模式。瀑布开发模式是一种线性的软件开发过程,按照固定的顺序依次完成需求分析、系统设计、编码、测试和运维等阶段。在这个开发模式中,软......
  • 【9.0】路飞项目前端搭建
    【一】Vue2创建项目创建项目vuecreatelufycity_web选择Vue版本(2.0)VueCLIv5.0.8?Pleasepickapreset:(Usearrowkeys)>normal([Vue2]babel,router,vuex)vue3.0_cli([Vue3]babel,router,vuex)Default([Vue3]babel,eslint)D......
  • 【13.0】路飞项目的Gitee
    【一】管理路飞项目忽略一下文件夹及文件.idea*.log__pycache__*.pycscripts【二】忽视部分文件初识化仓库gitinitInitializedemptyGitrepositoryinE:/OldBoy/luffy/luffyCity/.git/查看仓库状态gitstatusOnbranchmasterNocommitsyetUnt......
  • 【4.0】路飞项目后端搭建
    【一】创建django项目的两种方式创建Django项目有两种常用的方式一种是通过命令行,另一种是通过PyCharm。【1】命令行方式:打开终端或命令提示符,并进入你想要创建项目的目录。在命令行中输入以下命令:django-adminstartproject项目名。其中,项目名是你为项目指定......
  • uniapp APP微信登录、支付、分享以及支付宝支付 实战踩坑记录
    1、微信支付和支付宝支付  先上代码、封装好了的组件   html部分    <template> <viewclass="rows"> <!------------------------------充值的弹框开始------------------------------> <uni-popupclass="common-popup"ref="popupChongZhi":i......
  • 互站价值1888全新二开游戏支付通道/话费/电网、抖音、快手、紫水晶带云端源码
    源码修复可用。价格修复,YY业务都可用  腾讯暂时不可用拍前必看:本店所售程序只供测试研究,不得使用于非法用途,不得违反国家法律,不得用于进行违法行为,否则后果自负!购买以后用作他用附带的一切法律责任后果都由购买者承担于本店无任何关系!请先联系客服看好演示后,确认无吴后在拍,免责......
  • 订单支付_阅读订单
                  ......
  • 订单支付_微信支付准备工作
              ......
  • 订单支付_微信支付介绍_微信支付相关接口介绍
        ......
  • 笔试- 新国都嘉联支付-测开
    笔试 新国都嘉联支付-测开1、abcde5个球,抽中的比例10,15,20,25,30循环100次,打印每个球的抽中次数按下面思路倒是也可以publicstaticStringranomBall(){intran=(int)(Matn.random()*150);if(ran<50){return"B";}elseif(ran<90){return"D";}els......