Django电商项目
订单支付页面
订单支付模板
{% extends 'base_user_center.html' %}
{% load staticfiles %}
{% block right_content %}
<div class="right_content clearfix">
{% csrf_token %}
<h3 class="common_title2">全部订单</h3>
{% for order in order_page %}
<ul class="order_list_th w978 clearfix">
<li class="col01">{{ order.create_time }}</li>
<li class="col02">订单号:{{ order.order_id }}</li>
<li class="col02 stress">{{ order.status_name }}</li>
</ul>
<table class="order_list_table w980">
<tbody>
<tr>
<td width="55%">
{% for order_sku in order.order_skus %}
<ul class="order_goods_list clearfix">
<li class="col01"><img src="{{ order_sku.sku.image.url }}"></li>
<li class="col02">{{ order_sku.sku.name }}<em>{{ order_sku.price }}元/{{ order_sku.sku.unite }}</em></li>
<li class="col03">{{ order_sku.count }}</li>
<li class="col04">{{ order_sku.amount }}元</li>
</ul>
{% endfor %}
</td>
<td width="15%">{{ order.total_price|add:order.transit_price }}(含运费:{{ order.transit_price }})元</td>
<td width="15%">{{ order.status_name }}</td>
<td width="15%"><a href="#" order_id="{{ order.order_id }}" status="{{ order.order_status }}" class="oper_btn">去付款</a></td>
</tr>
</tbody>
</table>
{% endfor %}
<div class="pagenation">
{% if order_page.has_previous_page %}
<a href="{% url 'user:order' order_page.previous_page_number %}"><上一页</a>
{% endif %}
{% for pindex in pages %}
{% if pindex == order_page.number %}
<a href="{% url 'user:order' pindex %}" class="active">{{ pindex }}</a>
{% else %}
<a href="{% url 'user:order' pindex %}">{{ pindex }}</a>
{% endif %}
{% endfor %}
{% if order_page.has_next_page %}
<a href="{% url 'user:order' order_page.next_page_number %}">下一页></a>
{% endif %}
</div>
</div>
{% endblock right_content %}
{% block bottomfiles %}
<script src="{% static 'js/jquery-1.12.4.min.js' %}"></script>
<script>
$('.oper_btn').each(function () {
// 获取支付状态
status = $(this).attr('status')
if (status == 1){
$(this).text('去支付')
}
else if (status == 4){
$(this).text('去评价')
}
else if (status == 5){
$(this).text('已完成')
}
})
$('.oper_btn').click(function () {
// 获取status
status = $(this).attr('status')
// 获取订单id
order_id = $(this).attr('order_id')
if (status == 1){
// 进行支付
csrf = $('input[name="csrfmiddlewaretoken"]').val()
// 组织参数
params = {'order_id':order_id, 'csrfmiddlewaretoken':csrf}
// 发起ajax post请求,访问/order/pay, 传递参数:order_id
$.post('/order/pay', params, function (data) {
if (data.res == 3){
// 引导用户到支付页面
window.open(data.pay_url)
// 浏览器访问/order/check, 获取支付交易的结果
// ajax post 传递参数:order_id
$.post('/order/check', params, function (data){
if (data.res == 3){
alert('支付成功')
// 刷新页面
location.reload()
}
else{
alert(data.errmsg)
}
})
}
else{
alert(data.errmsg)
}
})
}
else if (status == 4){
// 其他情况
// 跳转到评价页面
location.href = '/order/comment/'+order_id
}
})
</script>
{% endblock bottomfiles %}
订单支付view
# ajax post
# 前端传递的参数:订单id(order_id)
# /order/pay
class OrderPayView(View):
'''订单支付'''
def post(self, request):
'''订单支付'''
# 用户是否登录
user = request.user
if not user.is_authenticated():
return JsonResponse({'res':0, 'errmsg':'用户未登录'})
# 接收参数
order_id = request.POST.get('order_id')
# 校验参数
if not order_id:
return JsonResponse({'res':1, 'errmsg':'无效的订单id'})
try:
order = OrderInfo.objects.get(order_id=order_id,
user=user,
pay_method=3,
order_status=1)
except OrderInfo.DoesNotExist:
return JsonResponse({'res':2, 'errmsg':'订单错误'})
# 业务处理:使用python sdk调用支付宝的支付接口
# 初始化
alipay = AliPay(
appid="2016090800464054", # 应用id
app_notify_url=None, # 默认回调url
app_private_key_path=os.path.join(settings.BASE_DIR, 'apps/order/app_private_key.pem'),
alipay_public_key_path=os.path.join(settings.BASE_DIR, 'apps/order/alipay_public_key.pem'), # 支付宝的公钥,验证支付宝回传消息使用,不是你自己的公钥,
sign_type="RSA2", # RSA 或者 RSA2
debug=True # 默认False
)
# 调用支付接口
# 电脑网站支付,需要跳转到https://openapi.alipaydev.com/gateway.do? + order_string
total_pay = order.total_price+order.transit_price # Decimal
order_string = alipay.api_alipay_trade_page_pay(
out_trade_no=order_id, # 订单id
total_amount=str(total_pay), # 支付总金额
subject='天天生鲜%s'%order_id,
return_url=None,
notify_url=None # 可选, 不填则使用默认notify url
)
# 返回应答
pay_url = 'https://openapi.alipaydev.com/gateway.do?' + order_string
return JsonResponse({'res':3, 'pay_url':pay_url})
# ajax post
# 前端传递的参数:订单id(order_id)
# /order/check
class CheckPayView(View):
'''查看订单支付的结果'''
def post(self, request):
'''查询支付结果'''
# 用户是否登录
user = request.user
if not user.is_authenticated():
return JsonResponse({'res': 0, 'errmsg': '用户未登录'})
# 接收参数
order_id = request.POST.get('order_id')
# 校验参数
if not order_id:
return JsonResponse({'res': 1, 'errmsg': '无效的订单id'})
try:
order = OrderInfo.objects.get(order_id=order_id,
user=user,
pay_method=3,
order_status=1)
except OrderInfo.DoesNotExist:
return JsonResponse({'res': 2, 'errmsg': '订单错误'})
# 业务处理:使用python sdk调用支付宝的支付接口
# 初始化
alipay = AliPay(
appid="2016090800464054", # 应用id
app_notify_url=None, # 默认回调url
app_private_key_path=os.path.join(settings.BASE_DIR, 'apps/order/app_private_key.pem'),
alipay_public_key_path=os.path.join(settings.BASE_DIR, 'apps/order/alipay_public_key.pem'),
# 支付宝的公钥,验证支付宝回传消息使用,不是你自己的公钥,
sign_type="RSA2", # RSA 或者 RSA2
debug=True # 默认False
)
# 调用支付宝的交易查询接口
while True:
response = alipay.api_alipay_trade_query(order_id)
# response = {
# "trade_no": "2017032121001004070200176844", # 支付宝交易号
# "code": "10000", # 接口调用是否成功
# "invoice_amount": "20.00",
# "open_id": "20880072506750308812798160715407",
# "fund_bill_list": [
# {
# "amount": "20.00",
# "fund_channel": "ALIPAYACCOUNT"
# }
# ],
# "buyer_logon_id": "csq***@sandbox.com",
# "send_pay_date": "2017-03-21 13:29:17",
# "receipt_amount": "20.00",
# "out_trade_no": "out_trade_no15",
# "buyer_pay_amount": "20.00",
# "buyer_user_id": "2088102169481075",
# "msg": "Success",
# "point_amount": "0.00",
# "trade_status": "TRADE_SUCCESS", # 支付结果
# "total_amount": "20.00"
# }
code = response.get('code')
if code == '10000' and response.get('trade_status') == 'TRADE_SUCCESS':
# 支付成功
# 获取支付宝交易号
trade_no = response.get('trade_no')
# 更新订单状态
order.trade_no = trade_no
order.order_status = 4 # 待评价
order.save()
# 返回结果
return JsonResponse({'res':3, 'message':'支付成功'})
elif code == '40004' or (code == '10000' and response.get('trade_status') == 'WAIT_BUYER_PAY'):
# 等待买家付款
# 业务处理失败,可能一会就会成功
import time
time.sleep(5)
continue
else:
# 支付出错
print(code)
return JsonResponse({'res':4, 'errmsg':'支付失败'})
用户订单页面
view
# /user/order
class UserOrderView(LoginRequiredMixin, View):
'''用户中心-订单页'''
def get(self, request, page):
'''显示'''
# 获取用户的订单信息
user = request.user
orders = OrderInfo.objects.filter(user=user).order_by('-create_time')
# 遍历获取订单商品的信息
for order in orders:
# 根据order_id查询订单商品信息
order_skus = OrderGoods.objects.filter(order_id=order.order_id)
# 遍历order_skus计算商品的小计
for order_sku in order_skus:
# 计算小计
amount = order_sku.count*order_sku.price
# 动态给order_sku增加属性amount,保存订单商品的小计
order_sku.amount = amount
# 动态给order增加属性,保存订单状态标题
order.status_name = OrderInfo.ORDER_STATUS[order.order_status]
# 动态给order增加属性,保存订单商品的信息
order.order_skus = order_skus
# 分页
paginator = Paginator(orders, 1)
# 获取第page页的内容
try:
page = int(page)
except Exception as e:
page = 1
if page > paginator.num_pages:
page = 1
# 获取第page页的Page实例对象
order_page = paginator.page(page)
# todo: 进行页码的控制,页面上最多显示5个页码
# 1.总页数小于5页,页面上显示所有页码
# 2.如果当前页是前3页,显示1-5页
# 3.如果当前页是后3页,显示后5页
# 4.其他情况,显示当前页的前2页,当前页,当前页的后2页
num_pages = paginator.num_pages
if num_pages < 5:
pages = range(1, num_pages + 1)
elif page <= 3:
pages = range(1, 6)
elif num_pages - page <= 2:
pages = range(num_pages - 4, num_pages + 1)
else:
pages = range(page - 2, page + 3)
# 组织上下文
context = {'order_page':order_page,
'pages':pages,
'page': 'order'}
# 使用模板
return render(request, 'user_center_order.html', context)
模板
{% extends 'base_user_center.html' %}
{% load staticfiles %}
{% block right_content %}
<div class="right_content clearfix">
{% csrf_token %}
<h3 class="common_title2">全部订单</h3>
{% for order in order_page %}
<ul class="order_list_th w978 clearfix">
<li class="col01">{{ order.create_time }}</li>
<li class="col02">订单号:{{ order.order_id }}</li>
<li class="col02 stress">{{ order.status_name }}</li>
</ul>
<table class="order_list_table w980">
<tbody>
<tr>
<td width="55%">
{% for order_sku in order.order_skus %}
<ul class="order_goods_list clearfix">
<li class="col01"><img src="{{ order_sku.sku.image.url }}"></li>
<li class="col02">{{ order_sku.sku.name }}<em>{{ order_sku.price }}元/{{ order_sku.sku.unite }}</em></li>
<li class="col03">{{ order_sku.count }}</li>
<li class="col04">{{ order_sku.amount }}元</li>
</ul>
{% endfor %}
</td>
<td width="15%">{{ order.total_price|add:order.transit_price }}(含运费:{{ order.transit_price }})元</td>
<td width="15%">{{ order.status_name }}</td>
<td width="15%"><a href="#" order_id="{{ order.order_id }}" status="{{ order.order_status }}" class="oper_btn">去付款</a></td>
</tr>
</tbody>
</table>
{% endfor %}
<div class="pagenation">
{% if order_page.has_previous_page %}
<a href="{% url 'user:order' order_page.previous_page_number %}"><上一页</a>
{% endif %}
{% for pindex in pages %}
{% if pindex == order_page.number %}
<a href="{% url 'user:order' pindex %}" class="active">{{ pindex }}</a>
{% else %}
<a href="{% url 'user:order' pindex %}">{{ pindex }}</a>
{% endif %}
{% endfor %}
{% if order_page.has_next_page %}
<a href="{% url 'user:order' order_page.next_page_number %}">下一页></a>
{% endif %}
</div>
</div>
{% endblock right_content %}
{% block bottomfiles %}
<script src="{% static 'js/jquery-1.12.4.min.js' %}"></script>
<script>
$('.oper_btn').each(function () {
// 获取支付状态
status = $(this).attr('status')
if (status == 1){
$(this).text('去支付')
}
else if (status == 4){
$(this).text('去评价')
}
else if (status == 5){
$(this).text('已完成')
}
})
$('.oper_btn').click(function () {
// 获取status
status = $(this).attr('status')
// 获取订单id
order_id = $(this).attr('order_id')
if (status == 1){
// 进行支付
csrf = $('input[name="csrfmiddlewaretoken"]').val()
// 组织参数
params = {'order_id':order_id, 'csrfmiddlewaretoken':csrf}
// 发起ajax post请求,访问/order/pay, 传递参数:order_id
$.post('/order/pay', params, function (data) {
if (data.res == 3){
// 引导用户到支付页面
window.open(data.pay_url)
// 浏览器访问/order/check, 获取支付交易的结果
// ajax post 传递参数:order_id
$.post('/order/check', params, function (data){
if (data.res == 3){
alert('支付成功')
// 刷新页面
location.reload()
}
else{
alert(data.errmsg)
}
})
}
else{
alert(data.errmsg)
}
})
}
else if (status == 4){
// 其他情况
// 跳转到评价页面
location.href = '/order/comment/'+order_id
}
})
</script>
{% endblock bottomfiles %}
支付宝支付
-
支付宝开放平台登录
使用已有的支付宝账号即可https://open.alipay.com/platform/home.htm
-
关于沙箱环境(开发模拟环境)
https://docs.open.alipay.com/200/105311
登录后,在页面顶部可以选择进入沙箱环境设置页面
-
支付宝开发者文档
https://openhome.alipay.com/developmentDocument.htm
电脑网站支付https://docs.open.alipay.com/270
-
电脑网站支付流程
- 签名
发送给支付的请求都需要进行签名https://docs.open.alipay.com/291/106118
- 使用python工具包
https://github.com/fzlee/alipay/blob/master/README.zh-hans.md
安装
# 从 1.3.0升级上来的用户, 请先卸载pycrypto:
pip uninstall pycrypto
# 安装python-alipay-sdk
pip install python-alipay-sdk --upgrade
生成密钥文件
openssl
OpenSSL> genrsa -out app_private_key.pem 2048 # 私钥
OpenSSL> rsa -in app_private_key.pem -pubout -out app_public_key.pem # 导出公钥
OpenSSL> exit
cat app_publict_key.pem 查看公钥的内容
将-----BEGIN PUBLIC KEY-----和-----END PUBLIC KEY-----中间的内容保存在支付宝的用户配置中(沙箱或者正式)https://openhome.alipay.com/platform/appDaily.htm?tab=info
下载支付宝的公钥文件
将公钥的内容复制保存到一个文本文件中(alipay_pubilc_key.pem),注意需要在文本的首尾添加标记位(-----BEGIN PUBLIC KEY-----和-----END PUBLIC KEY-----) ,形如:
将刚刚生成的私钥app_private_key.pem和支付宝公钥alipay_public_key.pem放到我们的项目目录中
使用支付宝 python包的初始化
-
支付接口
https://docs.open.alipay.com/270/alipay.trade.page.pay/
-
获取支付结果接口
https://docs.open.alipay.com/api_1/alipay.trade.query
订单评论
模板
{% extends 'base_user_center.html' %}
{% load staticfiles %}
{% block title %}天天生鲜-用户中心{% endblock %}
{% block page_title %}用户中心{% endblock page_title %}
{% block right_content %}
<div class="right_content clearfix">
<h3 class="common_title2">订单评价</h3>
<ul class="order_list_th w978 clearfix">
<li class="col01">{{order.create_time}}</li>
<li class="col02">订单号:{{order.order_id}}</li>
<li class="col02 stress">{{order.status_name}}</li>
</ul>
<form method="post">
{% csrf_token %}
{# 订单id #}
<input type="hidden" name="order_id" value="{{order.order_id}}">
{# 订单中有几个商品 #}
<input type="hidden" name="total_count" value="{{order.order_skus|length}}">
{% for order_sku in order.order_skus %}
<table class="order_list_table w980">
<tbody>
<tr>
<td width="80%">
<ul class="order_goods_list clearfix">
<li class="col01"><img src="{{ order_sku.sku.image.url }}"></li>
<li class="col02">{{order_sku.sku.name}}<em>{{order_sku.price}}/{{order_sku.sku.unite}}</em></li>
<li class="col03">{{order_sku.count}}</li>
</ul>
</td>
<td width="20%">{{order_sku.amount}}元</td>
</tr>
</tbody>
</table>
<div class="site_con">
<input type="hidden" name="sku_{{forloop.counter}}" value="{{order_sku.sku.id}}">
<div class="form_group form_group2">
<label>评价内容:</label>
<textarea class="site_area" name="content_{{forloop.counter}}"></textarea>
</div>
</div>
{% endfor %}
<input type="submit" name="" value="提交" class="info_submit">
</form>
</div>
{% endblock right_content %}
view
class CommentView(LoginRequiredMixin, View):
"""订单评论"""
def get(self, request, order_id):
"""提供评论页面"""
user = request.user
# 校验数据
if not order_id:
return redirect(reverse('user:order'))
try:
order = OrderInfo.objects.get(order_id=order_id, user=user)
except OrderInfo.DoesNotExist:
return redirect(reverse("user:order"))
# 根据订单的状态获取订单的状态标题
order.status_name = OrderInfo.ORDER_STATUS[order.order_status]
# 获取订单商品信息
order_skus = OrderGoods.objects.filter(order_id=order_id)
for order_sku in order_skus:
# 计算商品的小计
amount = order_sku.count*order_sku.price
# 动态给order_sku增加属性amount,保存商品小计
order_sku.amount = amount
# 动态给order增加属性order_skus, 保存订单商品信息
order.order_skus = order_skus
# 使用模板
return render(request, "order_comment.html", {"order": order})
def post(self, request, order_id):
"""处理评论内容"""
user = request.user
# 校验数据
if not order_id:
return redirect(reverse('user:order'))
try:
order = OrderInfo.objects.get(order_id=order_id, user=user)
except OrderInfo.DoesNotExist:
return redirect(reverse("user:order"))
# 获取评论条数
total_count = request.POST.get("total_count")
total_count = int(total_count)
# 循环获取订单中商品的评论内容
for i in range(1, total_count + 1):
# 获取评论的商品的id
sku_id = request.POST.get("sku_%d" % i) # sku_1 sku_2
# 获取评论的商品的内容
content = request.POST.get('content_%d' % i, '') # cotent_1 content_2 content_3
try:
order_goods = OrderGoods.objects.get(order=order, sku_id=sku_id)
except OrderGoods.DoesNotExist:
continue
order_goods.comment = content
order_goods.save()
order.order_status = 5 # 已完成
order.save()
return redirect(reverse("user:order", kwargs={"page": 1}))