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/
{
"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 支付宝支付流程
4.2 新建支付宝应用
# 访问"支付宝开发平台"登录,可以访问开发者中心
https://open.alipay.com/platform/home.htm
# 可以参考"电脑网站支付" 熟悉电脑支付整体流程
https://docs.open.alipay.com/270/105899/
4.2.1 第一步:创建应用(这里使用网页)
4.2.2 下载支付宝开放平台开发助手
https://opendocs.alipay.com/open/291/105971
-
生成**
-
上传公钥
公钥加密,私钥解密
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-----
- alipay_public_key.pem 支付宝公钥
-----BEGIN PUBLIC KEY-----
# 支付宝公钥
-----END PUBLIC KEY-----
- 测试生成支付链接
# -*- 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×tamp=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
}
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()),
]
上一篇: Webpack:Webpack入门
下一篇: webpack入门