欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

26.商品模块

程序员文章站 2024-03-23 15:07:28
...

1.创建Goods应用

1.1创建应用

python ../manage.py startapp goods  # 创建商品应用

1.2在settings.py中注册应用

INSTALLED_APPS = [
    'goods.apps.GoodsConfig',
]

1.3syl/urls.py添加路由

urlpatterns = [
	path('goods/', include('goods.urls')), 
]

1.4 创建goods/urls.py路由文件

from django.urls import path,re_path
from . import views
urlpatterns = [

]

2. 在goods/models.py创建模型

2.1 商品表模型

from django.db import models
from course.models import Base


class Goods(Base):
    GOODS_TYPE = (
        ('1','Vip'),
        ('2','Course'),
    )
    CHANNEL_TYPE = (
        ('1','普通'),
        ('2','促销'),
    )
    course = models.ForeignKey('course.Course',on_delete=models.PROTECT)
    goods_type = models.CharField('商品种类',choices=GOODS_TYPE,max_length=8)
    product_id = models.CharField('产品id',max_length=8)
    title = models.CharField('商品名称',max_length=24)
    price = models.DecimalField('商品价格',max_digits=8,decimal_places=2)
    channel_type = models.CharField('购买渠道',choices=CHANNEL_TYPE,max_length=8)
    period = models.IntegerField('有效期',default=365)
    is_launched = models.BooleanField('是否上架',default=True)

    class Meta:
        db_table = 'tb_goods'
        verbose_name_plural ='商品'

    def __str__(self):
        return self.title

2.2 course/models.py中添加用户购买课程

from django.db import models

class UserCourse(Base):
    '''
    用户购买的课程
    '''

    user = models.ForeignKey('user.User',on_delete=models.CASCADE,related_name='payuser')
    course = models.ForeignKey('course.Course',on_delete=models.CASCADE,related_name='paycourse')

    class Meta:
        db_table = 'tb_usercourse'
        verbose_name_plural = '用户购买的课程'

    def __str__(self):
        return "用户:%s,课程:%s" % (self.user.username,self.course.title)

2.3 user/models.py添加VIP表并添加用户关联

from django.db import models
from django.contrib.auth.models import AbstractUser
from course.models import Base

class Vip(Base):
    VIP_CHOISE = (
        ('0','普通用户'),
        ('1','普通会员'),
        ('2','高级会员'),
    )
    title = models.CharField('vip名称',max_length=16)
    vip_type = models.CharField('vip种类',choices=VIP_CHOISE,max_length=4)
    desc = models.CharField('vip描述',max_length=255)
    period = models.IntegerField('有效期',default=365)

    class Meta:
        db_table = 'tb_vip'
        verbose_name_plural = 'Vip'

    def __str__(self):
        return self.title

class User(AbstractUser):
    phone = models.CharField('手机号',max_length=20)
    img = models.ImageField(upload_to='user',null=True, blank=True)
    nick_name = models.CharField('昵称',max_length=20)
    address = models.CharField('地址',max_length=255)
    vip = models.ForeignKey(Vip, on_delete=models.SET_NULL, default=None, null=True)
    vip_expiration = models.DateField('vip到期时间', blank=True, default=None, null=True)

    class Meta:
        db_table = 'tb_user'
        verbose_name_plural = '用户'

2.4 admin.py中注册

2.4.1 goods/admin.py中注册
from django.contrib import admin
from .models import *
# 注册后台管理
admin.site.register(Goods) 
admin.site.register(Orders) 
2.4.2 user/admin.py中注册
from django.contrib import admin

from .models import User
from .models import Vip
admin.site.register(User)
admin.site.register(Vip)

3.通过课程查询商品信息

3.1 只需要修改/course/sourse/1/返回的数 据即可

3.1.1 course/serializers.py添加商品信息序列化
from goods.serializers import GoodsSerializers
class CourseDeepSerializer(CourseSerializers):
    goods_set = GoodsSerializers(many=True)
    chapters = ChaptersSerializers(many=True)
3.1.2 在goods/serializers.py中添加序列化函数
from rest_framework import serializers
from goods.models import *

class GoodsSerializers(serializers.ModelSerializer):
    class Meta:
        model = Goods
        fields = '__all__'

3.2 测试

http://192.168.56.100:8888/course/course/4/

26.商品模块

{
    "id": 4,
    "goods_set": [
        {
            "id": 1,
            "create_time": "03:19:55.585723",
            "update_time": "08:40:29.211433",
            "goods_type": "2",
            "product_id": "1",
            "title": "Linux基础入门",
            "price": "88.00",
            "channel_type": "1",
            "period": 365,
            "is_launched": true,
            "course": 4
        }
    ],
    "chapters": [
        {
            "id": 1,
            "sections": [
                {
                    "id": 1,
                    "create_time": "10:58:41.498937",
                    "update_time": "07:42:54.334322",
                    "title": "1.linux为何物",
                    "serial_num": 1,
                    "learn_time": 1,
                    "video": "http://192.168.56.100:8888/media/videos/20201013/CG%E5%A6%B9%E5%AD%90_htP4i7V.mp4",
                    "seq_num": 1,
                    "chapters": 1
                }
            ],
            "create_time": "10:45:10.946531",
            "update_time": "10:45:10.946558",
            "title": "Linux 系统简介",
            "serial_num": 1,
            "course": 4
        }
    ],
    "create_time": "10:40:42.341240",
    "update_time": "10:40:42.341261",
    "title": "Linux 基础入门",
    "desc": "本课程教你如何熟练地使用 Linux,本实验中通过在线动手实验的方式学习 Linux 常用命令,用户与权限管理,目录结构与文件操作,环境变量,计划任务,管道与数据流重定向等基本知识点。",
    "img": "http://192.168.56.100:8888/media/course/ncn1.jpg",
    "status": "1",
    "attention": 13423,
    "learner": 304693,
    "course_type": 1,
    "course_tag": [
        3
    ]
}

4.支付宝支付

4.1 支付宝支付流程

26.商品模块

26.商品模块

4.2 新建支付宝应用

# 访问"支付宝开发平台"登录,可以访问开发者中心
https://open.alipay.com/platform/home.htm
# 可以参考"电脑网站支付" 熟悉电脑支付整体流程
https://docs.open.alipay.com/270/105899/
4.2.1 第一步:创建应用(这里使用网页)

26.商品模块

4.2.2 下载支付宝开放平台开发助手

https://opendocs.alipay.com/open/291/105971

  • 生成**
    26.商品模块

  • 上传公钥

26.商品模块

  • 公钥加密,私钥解密

26.商品模块

4.2.3 测试支付宝获取支付宝扫码链接
  • 阿里官方没有提供python对接支付的sdk,但是python库中有非官方的sdk包可以使用
  • python-alipay-adk :https://github.com/fzlee/alipay/blob/master/README.zh-hans.md
  • 使用起来非常简单,只要传入几个必要的参数就可以完成
  • 由于支付对安全要求很高,所以要理解对接支付宝安全的流程: 公钥加密、私钥解密 这八个字

1.app_private_key.pem app私钥

-----BEGIN RSA PRIVATE KEY-----
# app私钥
-----END RSA PRIVATE KEY-----
  1. alipay_public_key.pem 支付宝公钥
-----BEGIN PUBLIC KEY-----
# 支付宝公钥
-----END PUBLIC KEY-----
  1. 测试生成支付链接
# -*- coding: utf-8 -*-
from alipay import AliPay

# 沙箱环境中 app 私钥
app_private_key_string = open('app_private_key.pem').read()
# 支付宝公钥
alipay_public_key_string = open('alipay_public_key.pem').read()

def get_alipay_url():
    alipay = AliPay(
        appid="2016102600762723",  # 沙箱appid
        app_notify_url=None,  # 默认回调url
        app_private_key_string=app_private_key_string,
        # 支付宝的公钥,验证支付宝回传消息使用,不是你自己的公钥,
        alipay_public_key_string=alipay_public_key_string,
        sign_type="RSA2",  # RSA 或者 RSA2
        debug=True,  # 默认False,我们是沙箱,所以改成True(让访问沙箱环境支付宝地址)
    )
    # 调用支付接口,生成支付链接
    order_string = alipay.api_alipay_trade_page_pay(
        out_trade_no="201613306",  # 订单id,应该从前端获取
        total_amount=str(66.66),  # 订单总金额
        subject="测试阿里云付款",  # 付款标题信息
        return_url=None,  # 付款成功回调地址(可以为空)
        notify_url=None  # 付款成功后异步通知地址(可以为空)
    )
    pay_url = "https://openapi.alipaydev.com/gateway.do?" + order_string
    print(pay_url)
    
def query_pay():
    alipay = AliPay(
        appid="2016102600762723",  # 沙箱appid
        app_notify_url=None,  # 默认回调url
        app_private_key_string=app_private_key_string,
        # 支付宝的公钥,验证支付宝回传消息使用,不是你自己的公钥
        alipay_public_key_string=alipay_public_key_string,
        sign_type="RSA",  # RSA 或者 RSA2
        debug=True,  # 默认False,我们是沙箱,所以改成True(让访问沙箱环境支付宝地址)
    )
    trade_query = alipay.api_alipay_trade_query(
        out_trade_no=20161112,  # 上面生成支付码页面时传入的商品订单号
        trade_no=None
    )
    print(trade_query)


if __name__ == '__main__':
    get_alipay_url()
    query_pay()


"""
生成的支付链接
https://openapi.alipaydev.com/gateway.do?app_id=2016102600762723&biz_content=%7B%22subject%22%3A%22%5Cu6d4b%5Cu8bd5%5Cu963f%5Cu91cc%5Cu4e91%5Cu4ed8%5Cu6b3e%22%2C%22out_trade_no%22%3A%22201613306%22%2C%22total_amount%22%3A%2266.66%22%2C%22product_code%22%3A%22FAST_INSTANT_TRADE_PAY%22%7D&charset=utf-8&method=alipay.trade.page.pay&sign_type=RSA2&timestamp=2020-10-15+20%3A11%3A02&version=1.0&sign=LBruF55jD8x2%2B5BycRD9NPIKwl9iI9BJZ%2Bla73bZPIUR6khBdRqTnU9UVPAaErlmQy169auTBZFI9%2BKI6zMN5hhexQTF%2FKvtg6Jxz3m6OMrWF1rXXdf7Iao1q5jHXGSG5u0xlVSwsCup27oFwjOIIUUZIyomeiZ4dfR42bo%2BMftImyjNyTRhoRArtv1U6xbMS972uCA%2FRD6Ozljnxo9kiP6K3hqUo3MKCrunlQYVvwzkSrDbim8zfE3eZF4Y97SeOn6os0iRvm65AY0UG86iDKGlcGXFcFz2wN2qbFSKkDNXrR6arXuv9bBwpHmCmB0KK2cD0pYXdcVisSB6Ges7ag%3D%3D

"""

5.创建订单并生成支付链接接口

5.1syl/setings.py中配置支付相关参数

# 支付宝配置
ALIPAY_APPID = '2016102600762723'  # 沙箱appid
ALIPAY_DEBUG = True
ALIPAY_URL = "https://openapi.alipaydev.com/gateway.do"  # alipay沙箱环境支付宝网关
ALIPAY_RETURN_URL = 'http://127.0.0.1:8888/payment/callback/'  # 支付完成后支 付宝回调我们应用的地址

5.2goods/views.py中写视图函数

from rest_framework.views import APIView
from .serializers import *
from rest_framework.response import Response
from rest_framework.permissions import AllowAny,IsAuthenticated
from goods.utils import get_order_id,get_pay_url,alipay

# 获取支付宝 支付链接
class PayUrlView(APIView):
    permission_classes = (IsAuthenticated,)

    def post(self,request):
        # 1.获取课程id,获取购买途径,(普通购买,促销购买)获取 用户
        goods_id = request.data.get('goods_id')
        goods = Goods.objects.get(id=goods_id)
        user = request.user
        # 2.下订单
        order_id = get_order_id()
        if user.vip.vip_type == '1': # 普通会员
            goods_price = goods.price * Decimal('0.80').quantize(Decimal('0.00'))
        elif user.vip.vip_type == '2': # 高级会员
            goods_price = goods.price * Decimal('0.60').quantize(Decimal('0.00'))
        else: # 普通用户
            goods_price = goods.price

        goods_price = Decimal(goods_price).quantize(Decimal('0.00'))
        order = Orders(user=user,goods=goods,order_id=order_id,pay_method=1,status=1,total_amount=goods_price)
        order.save()
        print(order.total_amount,type(order.total_amount))
        # 3.根据订单 生成支付链接
        subject = "实验楼订单:%s, 价格:%s" % (order.order_id, order.total_amount)
        pay_url = get_pay_url(order.order_id,order.total_amount,subject)

        # 4.返回链接
        return Response({'code':0,'msg':'下单成功','data':{'pay_url':pay_url}})
5.3 goods/utils.py中生成随机订单函数和生成支付URL函数
# -*- coding: utf-8 -*-
import  datetime
import os
import random
from alipay import AliPay
from syl import settings


# 获取文件路径
# 沙箱环境中 app 私钥
app_private_key_string = os.path.join(settings.BASE_DIR,'apps/goods/key/app_private_key.pem')
# 支付宝公钥
alipay_public_key_string = os.path.join(settings.BASE_DIR,'apps/goods/key/alipay_public_key.pem')


with open(app_private_key_string) as f:
    app_private_key_string = f.read()
with open(alipay_public_key_string) as f:
    alipay_public_key_string = f.read()

# 创建支付宝支付对象
alipay = AliPay(
        appid=settings.ALIPAY_APPID,  # 沙箱appid
        app_notify_url=None,  # 默认回调url
        app_private_key_string=app_private_key_string,
        # 支付宝的公钥,验证支付宝回传消息使用,不是你自己的公钥,
        alipay_public_key_string=alipay_public_key_string,
        sign_type="RSA2",  # RSA 或者 RSA2
        debug=settings.ALIPAY_DEBUG,  # 默认False,我们是沙箱,所以改成True(让访问沙箱环境支付宝地址)
    )


def get_pay_url(out_trade_no,total_amount,subject):
    # 生成登录支付宝链接
    order_string = alipay.api_alipay_trade_page_pay(
        out_trade_no=out_trade_no,
        total_amount=str(total_amount),
        subject=subject,
        return_url=settings.ALIPAY_RETURN_URL,
    )
    # 响应支付宝链接
    alipay_url = settings.ALIPAY_URL + '?' +order_string
    return alipay_url

def get_order_id():
    '''
    SYL202008241212121200005/24
    生成订单号: 格式: SYL + 年月日时分秒 + 5位随机数
    :return:
    '''
    d = datetime.datetime.now()
    base = 'SYL'
    time_str = '%04d%02d%02d%02d%02d%02d' % (d.year,d.month,d.day,d.hour,d.minute,d.second)
    rand_num = str(random.randint(10000,99999))
    return base + time_str +rand_num

5.4 goods/urls.py中注册路由

from django.urls import path,re_path
from . import views

urlpatterns = [
    path('getpayurl/', views.PayUrlView.as_view()), # /goods/getpayurl/
]

5.5 测试

1.请求地址

http://192.168.56.100:8888/goods/getpayurl/

2.携带参数

{
	"goods_id":1
}

26.商品模块

6.修改订单状态

6.1goods/views.py中写视图函数

# 更新订单的支付状态
class PeymentView(APIView):
    def post(self,request):

        total_amout = request.data.get("total_amount")  # 实际支付金额
        order_id = request.data.get("out_trade_no")     # 订单号
        trade_no = request.data.get("trade_no")     # 支付宝订单号

        orders = Orders.objects.get(order_id=order_id)
        orders.trade_no = trade_no
        orders.total_amout = total_amout
        orders.status = 2
        orders.save()

        return Response({"code": 200, "msg": "支付成功"})

6.2 goods/urls.py中注册路由

from django.urls import path,re_path
from . import views

urlpatterns = [
    path('peyment/', views.PeymentView.as_view()), 
]
相关标签: Django