课程管理
- 121.课程管理-发布课程界面和模型完成
- 122.课程管理-视频云存储讲解
- 123.课程管理-发布课程功能完成
- 124.课程管理-视频加密播放实现
- 125.购买课程-课程订单页面完成
- 126.购买课程-支付宝和微信支付功能准备工作
- 127.购买课程-生成课程订单
- 128.购买课程-配置pycharm同步代码到服务器
- 129.购买课程-添加数据(选看)
- 130.购买课程-支付宝和微信支付功能完成
- 131.购买课程-购买课程流程补充
课程管理-发布课程界面和模型完成
{% extends 'cms/base.html' %}
{% block title %}
发布课程
{% endblock %}
{% block head %}
<script src="{% static 'ueditor/ueditor.config.js' %}"></script>
<script src="{% static 'ueditor/ueditor.all.min.js' %}"></script>
<script src="{% static 'js/pub_course.min.js' %}"></script>
{% endblock %}
{% block content-header %}
<h1>发布课程</h1>
{% endblock %}
{% block content %}
<div class="row">
<div class="col-md-12">
<div class="box">
<div class="box-header">
<div class="form-group">
<label for="title-input">标题:</label>
<input type="text" class="form-control" placeholder="课程标题" name="title" id="title-input">
</div>
<div class="form-group">
<label for="category-input">分类:</label>
<select name="category" class="form-control" id="category-input">
{% for category in categories %}
<option value="{{ category.pk }}">{{ category.name }}</option>
{% endfor %}
</select>
</div>
<div class="form-group">
<label for="teacher-input">讲师:</label>
<select name="teacher" id="teacher-input" class="form-control">
{% for teacher in teachers %}
<option value="{{ teacher.pk }}">{{ teacher.username }}</option>
{% endfor %}
</select>
</div>
<div class="form-group">
<label for="video-input">视频地址:</label>
<input type="text" class="form-control" name="video_url" id="video-input" placeholder="视频地址">
</div>
<div class="form-group">
<label for="cover-input">封面图:</label>
<input type="text" class="form-control" name="cover" id="cover-input" placeholder="封面图">
</div>
<div class="form-group">
<label for="price-input">价格:</label>
<input type="text" class="form-control" name="price" id="price-input" placeholder="价格">
</div>
<div class="form-group">
<label for="duration-input">时长:</label>
<input type="text" class="form-control" name="duration" id="duration-input">
</div>
<div class="form-group">
<label>简介:</label>
<script id="editor" type="text/plain"></script>
</div>
<div class="form-group">
<button class="btn btn-primary pull-right" id="submit-btn">发布课程</button>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
# 这是课程相关的url映射
urlpatterns += [
path('pub_course/',course_views.PubCourse.as_view(),name='pub_course')
]
function PubCourse() {
}
PubCourse.prototype.initUEditor = function () {
window.ue = UE.getEditor("editor",{
'serverUrl': '/ueditor/upload/'
});
};
PubCourse.prototype.listenSubmitEvent = function () {
var submitBtn = $("#submit-btn");
submitBtn.click(function () {
var title = $("#title-input").val();
var category_id = $("#category-input").val();
var teacher_id = $("#teacher-input").val();
var video_url = $("#video-input").val();
var cover_url = $("#cover-input").val();
var price = $("#price-input").val();
var duration = $("#duration-input").val();
var profile = window.ue.getContent();
xfzajax.post({
'url': '/cms/pub_course/',
'data': {
'title': title,
'video_url': video_url,
'cover_url': cover_url,
'price': price,
'duration': duration,
'profile': profile,
'category_id': category_id,
'teacher_id': teacher_id
},
'success': function (result) {
if(result['code'] === 200){
window.location = window.location.href;
}
}
});
});
};
PubCourse.prototype.run = function () {
this.initUEditor();
this.listenSubmitEvent();
};
$(function () {
var course = new PubCourse();
course.run();
});
class CourseCategory(models.Model):
name = models.CharField(max_length=100)
class Teacher(models.Model):
username = models.CharField(max_length=100)
avatar = models.URLField()
jobtitle = models.CharField(max_length=100)
profile = models.TextField()
class Course(models.Model):
title = models.CharField(max_length=200)
category = models.ForeignKey('CourseCategory',on_delete=models.DO_NOTHING)
teacher = models.ForeignKey("Teacher",on_delete=models.DO_NOTHING)
video_url = models.URLField()
cover_url = models.URLField()
price = models.FloatField()
duration = models.IntegerField()
profile = models.TextField()
pub_time = models.DateTimeField(auto_now_add=True)
class CourseOrder(models.Model):
uid = ShortUUIDField(primary_key=True)
course = models.ForeignKey("Course",on_delete=models.DO_NOTHING)
buyer = models.ForeignKey("xfzauth.User",on_delete=models.DO_NOTHING)
amount = models.FloatField(default=0)
pub_time = models.DateTimeField(auto_now_add=True)
# 1:代表的是支付宝支付。2:代表的是微信支付
istype = models.SmallIntegerField(default=0)
# 1:代表的是未支付。2:代表的是支付成功
status = models.SmallIntegerField(default=1)
课程管理-视频云存储讲解
课程管理-发布课程功能完成
class PubCourseForm(forms.ModelForm,FormMixin):
category_id = forms.IntegerField()
teacher_id = forms.IntegerField()
class Meta:
model = Course
exclude = ("category",'teacher')
@method_decorator(permission_required(perm="course.change_course",login_url='/'),name='dispatch')
class PubCourse(View):
def get(self,request):
context = {
'categories': CourseCategory.objects.all(),
'teachers': Teacher.objects.all()
}
return render(request,'cms/pub_course.html',context=context)
def post(self,request):
form = PubCourseForm(request.POST)
if form.is_valid():
title = form.cleaned_data.get('title')
category_id = form.cleaned_data.get('category_id')
video_url = form.cleaned_data.get('video_url')
cover_url = form.cleaned_data.get("cover_url")
price = form.cleaned_data.get('price')
duration = form.cleaned_data.get('duration')
profile = form.cleaned_data.get('profile')
teacher_id = form.cleaned_data.get('teacher_id')
category = CourseCategory.objects.get(pk=category_id)
teacher = Teacher.objects.get(pk=teacher_id)
Course.objects.create(title=title, video_url=video_url, cover_url=cover_url, price=price, duration=duration,
profile=profile, category=category, teacher=teacher)
return restful.ok()
else:
return restful.params_error(message=form.get_errors())
def course_index(request):
context = {
'courses': Course.objects.all()
}
return render(request,'course/course_index.html',context=context)
def course_detail(request,course_id):
course = Course.objects.get(pk=course_id)
buyed = CourseOrder.objects.filter(course=course,buyer=request.user,status=2).exists()
context = {
'course': course,
'buyed': buyed
}
return render(request,'course/course_detail.html',context=context)
{% extends 'base/front_base.html' %}
{% block title %}
课程列表页
{% endblock %}
{% block head %}
<link rel="stylesheet" href="{% static 'css/course/course_index.min.css' %}">
{% endblock %}
{% block main %}
<div class="main">
<div class="course-nav">
<div class="nav-container">
<h3 class="title">在线课堂</h3>
<ul class="nav-list">
<li class="active"><a href="#">最新课堂</a></li>
<li><a href="#">投资人说</a></li>
<li><a href="#">明星案例</a></li>
<li><a href="#">创业知识</a></li>
</ul>
</div>
</div>
<div class="wrapper">
<ul class="course-list">
{% for course in courses %}
<li>
<a href="{% url 'course:course_detail' course_id=course.pk %}">
<div class="thumbnail-group">
<img src="{{ course.cover_url }}" alt="" class="thumbnial">
</div>
<div class="course-info">
<p class="title">{{ course.title }}</p>
<p class="author">{{ course.teacher.username }}</p>
<p class="price-group">
{% if course.price > 0 %}
<span class="pay">¥{{ course.price }}</span>
{% else %}
<span class="free">免费</span>
{% endif %}
</p>
</div>
</a>
</li>
{% endfor %}
</ul>
</div>
</div>
{% endblock %}
{% extends 'base/front_base.html' %}
{% block title %}
课程列表页
{% endblock %}
{% block head %}
<link rel="stylesheet" href="{% static 'css/course/course_detail.min.css' %}">
<script src="{% static 'videojs/video.min.js' %}"></script>
<script src="{% static 'videojs/videojs-contrib-hls.min.js' %}"></script>
<script src="{% static 'videojs/videojs-contrib-quality-levels.min.js' %}"></script>
<script type="text/javascript" src="https://cdn.bdstatic.com/jwplayer/latest/cyberplayer.js"></script>
<script src="{% static 'js/course_detail.min.js' %}"></script>
{% endblock %}
{% block main %}
<div class="main">
<div class="course-nav">
<div class="nav-container">
<h3 class="title">在线课堂</h3>
<ul class="nav-list">
<li class="active"><a href="#">最新课堂</a></li>
<li><a href="#">投资人说</a></li>
<li><a href="#">明星案例</a></li>
<li><a href="#">创业知识</a></li>
</ul>
</div>
</div>
<div class="wrapper">
<div class="course-wrapper">
<div class="course-info">
<p class="course-title">{{ course.title }}</p>
<div class="price-group">
<div class="share-group">
<span class="title">分享至:</span>
</div>
<div class="buy-group">
<!-- <span class="price pay">¥49.0</span>
<a href="#" class="buy-btn">立即购买</a> -->
{% if course.price > 0 %}
{% if not buyed %}
<span class="price pay">¥{{ course.price }}</span>
<a href="{% url 'course:course_order' course_id=course.pk %}" class="buy-btn">立即购买</a>
{% endif %}
{% else %}
<span class="price free">免费</span>
{% endif %}
</div>
</div>
</div>
<div class="video-group">
<span id="video-info" hidden data-video-url="{{ course.video_url }}" data-cover-url="{{ course.cover_url }}" data-course-id="{{ course.pk }}"></span>
<div id="playercontainer"></div>
</div>
</div>
<div class="bottom-wrapper">
<div class="course-detail-wrapper">
<div class="item-group">
<p class="item-title">课程讲师</p>
<div class="teacher-group">
<div class="avatar-group">
<img src="{{ course.teacher.avatar }}" alt="" class="avatar">
</div>
<div class="teacher-info">
<p class="teacher-name">{{ course.teacher.username }}</p>
<p class="teacher-desc">{{ course.teacher.jobtitle }}</p>
</div>
</div>
<p class="item-content">{{ course.teacher.profile }}</p>
</div>
<div class="item-group">
<p class="item-title">课程简介</p>
<p class="item-content">{{ course.profile|safe }}</p>
</div>
<div class="item-group">
<p class="item-title">课程大纲</p>
<p class="item-content">小饭桌在线课堂是小饭桌旗下的线上视频课程产品,汇聚顶级创业大咖导师、行业资深专家,致力于用系统、垂直的知识体系让创业者认知升级、技能进阶。小饭桌在线课堂用知识陪伴创业者从平凡到卓越!
</p>
</div>
<div class="item-group">
<p class="item-title">适宜人群</p>
<p class="item-content">想学习如何做投资的!
</p>
</div>
<div class="item-group">
<p class="item-title">帮助中心</p>
<p class="item-content">
1. 购买后的课程在线可反复观看学习,视频有效期以具体课程信息为准。 <br>
2. 课程暂不支持下载观看,均为在线观看视频。 <br>
3. 课程一经购买,不可转让、不可退款;仅限购买账号观看。 <br>
4. 如有问题请咨询客服饭桌君: 电话:18618172287 微信:fanzhuojun888 <br>
</p>
</div>
<div class="item-group">
<p class="item-title">关于小饭桌在线课堂</p>
<p class="item-content">
小饭桌在线课堂是小饭桌旗下的线上视频课程产品,汇聚顶级创业大咖导师、行业资深专家,致力于用系统、垂直的知识体系让创业者认知升级、技能进阶。小饭桌在线课堂用知识陪伴创业者从平凡到卓越!
</p>
</div>
</div>
<div class="recommand-wrapper">
<p class="recommand-title">推荐课程</p>
<ul class="course-list">
<li>
<a href="#">
<div class="course-info-group">
<p class="course-title">教你制作抓住投资人眼球的商业计划书</p>
<p class="teacher">知了课堂CEO</p>
</div>
<div class="thumbnail-group">
<img src="https://static-image.xfz.cn/1526455098_289.png-course.list.small" alt="" class="thumbnail">
</div>
</a>
</li>
<li>
<a href="#">
<div class="course-info-group">
<p class="course-title">教你制作抓住投资人眼球的商业计划书</p>
<p class="teacher">知了课堂CEO</p>
</div>
<div class="thumbnail-group">
<img src="https://static-image.xfz.cn/1526455098_289.png-course.list.small" alt="" class="thumbnail">
</div>
</a>
</li>
</ul>
</div>
</div>
</div>
</div>
{% endblock %}
课程管理-视频加密播放实现
def course_token(request):
# video:是视频文件的完整链接
file = request.GET.get('video')
course_id = request.GET.get('course_id')
if not CourseOrder.objects.filter(course_id=course_id,buyer=request.user,status=2).exists():
return restful.params_error(message='请先购买课程!')
expiration_time = int(time.time()) + 2 * 60 * 60
USER_ID = settings.BAIDU_CLOUD_USER_ID
USER_KEY = settings.BAIDU_CLOUD_USER_KEY
# file=http://hemvpc6ui1kef2g0dd2.exp.bcevod.com/mda-igjsr8g7z7zqwnav/mda-igjsr8g7z7zqwnav.m3u8
extension = os.path.splitext(file)[1]
media_id = file.split('/')[-1].replace(extension, '')
# unicode->bytes=unicode.encode('utf-8')bytes
key = USER_KEY.encode('utf-8')
message = '/{0}/{1}'.format(media_id, expiration_time).encode('utf-8')
signature = hmac.new(key, message, digestmod=hashlib.sha256).hexdigest()
token = '{0}_{1}_{2}'.format(signature, USER_ID, expiration_time)
return restful.result(data={'token': token})
function CourseDetail() {
}
CourseDetail.prototype.initPlayer = function () {
var videoInfoSpan = $("#video-info");
var video_url = videoInfoSpan.attr("data-video-url");
var cover_url = videoInfoSpan.attr("data-cover-url");
var course_id = videoInfoSpan.attr('data-course-id');
var player = cyberplayer("playercontainer").setup({
width: '100%',
height: '100%',
file: video_url,
image: cover_url,
autostart: false,
stretching: "uniform",
repeat: false,
volume: 100,
controls: true,
tokenEncrypt: true,
// AccessKey
ak: '42455a8c985649aeaa4ca86b50482d78'
});
player.on('beforePlay',function (e) {
if(!/m3u8/.test(e.file)){
return;
}
xfzajax.get({
'url': '/course/course_token/',
'data': {
'video': video_url,
'course_id': course_id
},
'success': function (result) {
if(result['code'] === 200){
var token = result['data']['token'];
player.setToken(e.file,token);
}else{
window.messageBox.showInfo(result['message']);
player.stop();
}
},
'fail': function (error) {
console.log(error);
}
});
});
};
CourseDetail.prototype.run = function () {
this.initPlayer();
};
$(function () {
var courseDetail = new CourseDetail();
courseDetail.run();
});
# 百度云的配置
# 控制台->用户中心->用户ID
BAIDU_CLOUD_USER_ID = '5b8849ddc6504318abcea39fe620948e'
# 点播VOD->全局设置->发布设置->安全设置->UserKey
BAIDU_CLOUD_USER_KEY = 'c228d166497b400d'
购买课程-课程订单页面完成
{% block head %}
<link rel="stylesheet" href="{% static 'css/common/header.min.css' %}">
<link rel="stylesheet" href="{% static 'css/common/footer.min.css' %}">
<link rel="stylesheet" href="{% static 'css/common/body.min.css' %}">
<style>
.table{
width: 100%;
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
background: #eaeaea;
text-align: center;
}
.table{
border-spacing: 20px;
}
.table img{
width: 120px;
height: 68px;
float: left;
}
.table .title{
margin-left: 10px;
}
.pay-way label{
float: right;
}
.pay-way span{
border: 1px solid #ccc;
position: relative;
top: 20px;
}
.pay-way .zfb-btn{
display: inline-block;
width: 139px;
height: 48px;
cursor: pointer;
background: url("http://study.163.com/res/images/pay/payList.png");
background-position: -140px 0;
background-size: 300% 200%;
margin-right:20px;
}
.pay-way .wx-btn{
display: inline-block;
width: 139px;
height: 48px;
position: relative;
cursor: pointer;
}
.pay-way .wx-btn img{
top: 12px;
left: 16px;
position: absolute;
}
.submit-group{
overflow: hidden;
padding: 60px 0;
}
.submit-btn{
display: block;
text-align: center;
width: 136px;
height:49px;
line-height: 49px;
background: url("http://s.stu.126.net/res/images/pay/payBtns.png?c9b6b849b38cca45b160a96802575ac8") no-repeat 4449px 4449px;
background-position: 0 -302px;
border: none;
cursor: pointer;
color: #fff;
font-size: 16px;
float: right;
}
.submit-btn:hover{
background-position: -139px -302px;
}
</style>
<script>
$(function () {
var submitBtn = $("#submit-btn");
submitBtn.click(function (event) {
event.preventDefault();
var goodsname = $("input[name='goodsname']").val();
var istype = $("input[name='istype']:checked").val();
var notify_url = $("input[name='notify_url']").val();
var orderid = $("input[name='orderid']").val();
var price = $("input[name='price']").val();
var return_url = $("input[name='return_url']").val();
xfzajax.post({
'url': '/course/course_order_key/',
'data': {
'goodsname': goodsname,
'istype': istype,
'notify_url': notify_url,
'orderid': orderid,
'price': price,
'return_url': return_url
},
'success': function (result) {
if(result['code'] === 200){
var key = result['data']['key'];
var keyInput = $("input[name='key']");
keyInput.val(key);
$("#pay-form").submit();
}
}
});
});
});
</script>
{% endblock %}
{% block main %}
<div class="main">
<div class="wrapper">
<table class="table">
<thead>
<tr>
<th>商品名称</th>
<th>单价(元)</th>
<th>小计(元)</th>
</tr>
</thead>
<tbody>
<tr>
<td align="left">
<a href="#">
<img class="thumbnail" src="{{ goods.thumbnail }}" alt="">
<span class="title">{{ goods.title }}</span>
</a>
</td>
<td>{{ goods.price }}</td>
<td>{{ goods.price }}</td>
</tr>
</tbody>
</table>
<form action="https://pay.bbbapi.com/" method="post" id="pay-form">
<input type="hidden" name="uid" value="49dc532695baa99e16e01bc0">
<input type="hidden" name="price" value="{{ goods.price }}">
<input type="hidden" name="notify_url" value="{{ notify_url }}">
<input type="hidden" name="return_url" value="{{ return_url }}">
<input type="hidden" name="orderid" value="{{ order.pk }}">
<input type="hidden" name="orderuid" value="{{ request.user.pk }}">
<input type="hidden" name="goodsname" value="{{ goods.title }}">
<input type="hidden" name="key" value="">
<div class="pay-way">
<label for="istype-wx">
<input id="istype-wx" type="radio" name="istype" value="2">
<span class="wx-btn">
<img src="http://nos.netease.com/test-edu-image/1BD9F69D6760CE1508D2269864AA54F8.png" alt="">
</span>
</label>
<label for="istype-zfb">
<input id="istype-zfb" type="radio" name="istype" value="1" checked>
<span class="zfb-btn"></span>
</label>
<div style="clear: both;"></div>
</div>
<div class="submit-group">
<input type="submit" value="去支付" id="submit-btn" class="submit-btn">
</div>
</form>
</div>
</div>
{% endblock %}
@xfz_login_required
def course_order(request,course_id):
course = Course.objects.get(pk=course_id)
order = CourseOrder.objects.create(course=course,buyer=request.user,status=1,amount=course.price)
context = {
'goods': {
'thumbnail': course.cover_url,
'title': course.title,
'price': course.price
},
'order': order,
# /course/notify_url/
'notify_url': request.build_absolute_uri(reverse('course:notify_view')),
'return_url': request.build_absolute_uri(reverse('course:course_detail',kwargs={"course_id":course.pk}))
}
return render(request,'course/course_order.html',context=context)
购买课程-支付宝和微信支付功能准备工作
class CourseOrder(models.Model):
uid = ShortUUIDField(primary_key=True)
course = models.ForeignKey("Course",on_delete=models.DO_NOTHING)
buyer = models.ForeignKey("xfzauth.User",on_delete=models.DO_NOTHING)
amount = models.FloatField(default=0)
pub_time = models.DateTimeField(auto_now_add=True)
# 1:代表的是支付宝支付。2:代表的是微信支付
istype = models.SmallIntegerField(default=0)
# 1:代表的是未支付。2:代表的是支付成功
status = models.SmallIntegerField(default=1)
@xfz_login_required
def course_order(request,course_id):
course = Course.objects.get(pk=course_id)
order = CourseOrder.objects.create(course=course,buyer=request.user,status=1,amount=course.price)
context = {
'goods': {
'thumbnail': course.cover_url,
'title': course.title,
'price': course.price
},
'order': order,
# /course/notify_url/
'notify_url': request.build_absolute_uri(reverse('course:notify_view')),
'return_url': request.build_absolute_uri(reverse('course:course_detail',kwargs={"course_id":course.pk}))
}
return render(request,'course/course_order.html',context=context)
购买课程-生成课程订单
购买课程-配置pycharm同步代码到服务器
购买课程-添加数据(选看)
购买课程-支付宝和微信支付功能完成
@xfz_login_required
def course_order_key(request):
goodsname = request.POST.get("goodsname")
istype = request.POST.get("istype")
notify_url = request.POST.get("notify_url")
orderid = request.POST.get("orderid")
price = request.POST.get("price")
return_url = request.POST.get("return_url")
token = 'e6110f92abcb11040ba153967847b7a6'
uid = '49dc532695baa99e16e01bc0'
orderuid = str(request.user.pk)
print('goodsname:',goodsname)
print('istype:',istype)
print('notify_url:',notify_url)
print('orderid:',orderid)
print('price:',price)
print('return_url:',return_url)
key = md5((goodsname + istype + notify_url + orderid + orderuid + price + return_url + token + uid).encode(
"utf-8")).hexdigest()
return restful.result(data={"key": key})
@csrf_exempt
def notify_view(request):
orderid = request.POST.get('orderid')
print('='*10)
print(orderid)
print('='*10)
CourseOrder.objects.filter(pk=orderid).update(status=2)
return restful.ok()
@xfz_login_required
def course_order(request,course_id):
course = Course.objects.get(pk=course_id)
order = CourseOrder.objects.create(course=course,buyer=request.user,status=1,amount=course.price)
context = {
'goods': {
'thumbnail': course.cover_url,
'title': course.title,
'price': course.price
},
'order': order,
# /course/notify_url/
'notify_url': request.build_absolute_uri(reverse('course:notify_view')),
'return_url': request.build_absolute_uri(reverse('course:course_detail',kwargs={"course_id":course.pk}))
}
return render(request,'course/course_order.html',context=context)
<script>
$(function () {
var submitBtn = $("#submit-btn");
submitBtn.click(function (event) {
event.preventDefault();
var goodsname = $("input[name='goodsname']").val();
var istype = $("input[name='istype']:checked").val();
var notify_url = $("input[name='notify_url']").val();
var orderid = $("input[name='orderid']").val();
var price = $("input[name='price']").val();
var return_url = $("input[name='return_url']").val();
xfzajax.post({
'url': '/course/course_order_key/',
'data': {
'goodsname': goodsname,
'istype': istype,
'notify_url': notify_url,
'orderid': orderid,
'price': price,
'return_url': return_url
},
'success': function (result) {
if(result['code'] === 200){
var key = result['data']['key'];
var keyInput = $("input[name='key']");
keyInput.val(key);
$("#pay-form").submit();
}
}
});
});
});
</script>
{% endblock %}
{% block main %}
<div class="main">
<div class="wrapper">
<table class="table">
<thead>
<tr>
<th>商品名称</th>
<th>单价(元)</th>
<th>小计(元)</th>
</tr>
</thead>
<tbody>
<tr>
<td align="left">
<a href="#">
<img class="thumbnail" src="{{ goods.thumbnail }}" alt="">
<span class="title">{{ goods.title }}</span>
</a>
</td>
<td>{{ goods.price }}</td>
<td>{{ goods.price }}</td>
</tr>
</tbody>
</table>
<form action="https://pay.bbbapi.com/" method="post" id="pay-form">
<input type="hidden" name="uid" value="49dc532695baa99e16e01bc0">
<input type="hidden" name="price" value="{{ goods.price }}">
<input type="hidden" name="notify_url" value="{{ notify_url }}">
<input type="hidden" name="return_url" value="{{ return_url }}">
<input type="hidden" name="orderid" value="{{ order.pk }}">
<input type="hidden" name="orderuid" value="{{ request.user.pk }}">
<input type="hidden" name="goodsname" value="{{ goods.title }}">
<input type="hidden" name="key" value="">
<div class="pay-way">
<label for="istype-wx">
<input id="istype-wx" type="radio" name="istype" value="2">
<span class="wx-btn">
<img src="http://nos.netease.com/test-edu-image/1BD9F69D6760CE1508D2269864AA54F8.png" alt="">
</span>
</label>
<label for="istype-zfb">
<input id="istype-zfb" type="radio" name="istype" value="1" checked>
<span class="zfb-btn"></span>
</label>
<div style="clear: both;"></div>
</div>
<div class="submit-group">
<input type="submit" value="去支付" id="submit-btn" class="submit-btn">
</div>
</form>
</div>
</div>
{% endblock %}
购买课程-购买课程流程补充
def course_token(request):
# video:是视频文件的完整链接
file = request.GET.get('video')
course_id = request.GET.get('course_id')
if not CourseOrder.objects.filter(course_id=course_id,buyer=request.user,status=2).exists():
return restful.params_error(message='请先购买课程!')
expiration_time = int(time.time()) + 2 * 60 * 60
USER_ID = settings.BAIDU_CLOUD_USER_ID
USER_KEY = settings.BAIDU_CLOUD_USER_KEY
# file=http://hemvpc6ui1kef2g0dd2.exp.bcevod.com/mda-igjsr8g7z7zqwnav/mda-igjsr8g7z7zqwnav.m3u8
extension = os.path.splitext(file)[1]
media_id = file.split('/')[-1].replace(extension, '')
# unicode->bytes=unicode.encode('utf-8')bytes
key = USER_KEY.encode('utf-8')
message = '/{0}/{1}'.format(media_id, expiration_time).encode('utf-8')
signature = hmac.new(key, message, digestmod=hashlib.sha256).hexdigest()
token = '{0}_{1}_{2}'.format(signature, USER_ID, expiration_time)
return restful.result(data={'token': token})
var player = cyberplayer("playercontainer").setup({
width: '100%',
height: '100%',
file: video_url,
image: cover_url,
autostart: false,
stretching: "uniform",
repeat: false,
volume: 100,
controls: true,
tokenEncrypt: true,
// AccessKey
ak: '42455a8c985649aeaa4ca86b50482d78'
});
player.on('beforePlay',function (e) {
if(!/m3u8/.test(e.file)){
return;
}
xfzajax.get({
'url': '/course/course_token/',
'data': {
'video': video_url,
'course_id': course_id
},
'success': function (result) {
if(result['code'] === 200){
var token = result['data']['token'];
player.setToken(e.file,token);
}else{
window.messageBox.showInfo(result['message']);
player.stop();
}
},
'fail': function (error) {
console.log(error);
}
});
});
};
def course_detail(request,course_id):
course = Course.objects.get(pk=course_id)
buyed = CourseOrder.objects.filter(course=course,buyer=request.user,status=2).exists()
context = {
'course': course,
'buyed': buyed
}
return render(request,'course/course_detail.html',context=context)