第六步、cart.html页面,order.html页面

1、订单页面
在这里插入图片描述在这里插入图片描述
cart.html编写

{% extends 'base_no_cart.html' %}
{% load staticfiles %}
{% block title %}天天生鲜-购物车{% endblock title %}
{% block page_title %}购物车{% endblock page_title %}
{% block body %}
	<div class="total_count">全部商品<em>{{ total_count }}</em></div>
    {% csrf_token %}
	<ul class="cart_list_th clearfix">
		<li class="col01">商品名称</li>
		<li class="col02">商品单位</li>
		<li class="col03">商品价格</li>
		<li class="col04">数量</li>
		<li class="col05">小计</li>
		<li class="col06">操作</li>
	</ul>


    <form method="post" action="{% url 'order:place' %}">
    {% csrf_token%}
    {% for sku in skus %}
	<ul class="cart_list_td clearfix">
		<li class="col01"><input type="checkbox" name="sku_ids"  value="{{ sku.id }}"></li>
		<li class="col02"><img src="{{ sku.image.url }}"></li>
		<li class="col03">{{ sku.name }}<br><em>{{ sku.price }}/{{ sku.unite }}</em></li>
		<li class="col04">{{ sku.unite }}</li>
		<li class="col05">{{ sku.price }}</li>
		<li class="col06">
			<div class="num_add">
				<a href="javascript:;" class="add fl">+</a>
				<input type="text" sku_id="{{ sku.id }}" class="num_show fl" value="{{ sku.count }}">
				<a href="javascript:;" class="minus fl">-</a>	
			</div>
		</li>
		<li class="col07">{{ sku.amount }}</li>
		<li class="col08"><a href="javascript:;">删除</a></li>
	</ul>
    {% endfor %}
	<ul class="settlements">
		<li class="col01"><input type="checkbox" name=""></li>
		<li class="col02">全选</li>
		<li class="col03">合计(不含运费)<span>¥</span><em>{{ total_price }}</em><br>共计<b>{{ total_count }}</b>件商品</li>
		<li class="col04"><input type="submit" value="去结算"></li>
	</ul>
    </form>
{% endblock body %}

{# 开始编写jq代码#}
{% block bottomfiles %}
    <script src="{% static 'js/jquery-1.12.4.min.js' %}"></script>
    <script>
    update_page_info()
    // 计算被选中的商品的总件数和总价格
    function update_page_info() {
        var total_count = 0
        var total_price = 0
        // 获取所有被选中的商品的ul元素
        $('.cart_list_td').find(':checked').parents('ul').each(function () {
            // 获取商品的数目和小计
            var count = $(this).find('.num_show').val();
            var amount = $(this).children('.col07').text();
            // 累加计算商品的总件数和总金额
            total_count += parseInt(count);
            total_price += parseFloat(amount)
        });
        // 设置选中商品的总件数和总金额
        $('.settlements').find('em').text(total_price.toFixed(2));
        $('.settlements').find('b').text(total_count)

    }

    // 更新商品的小计
    function update_sku_amount(sku_ul) {
        // 获取商品的数目和价格
        var price = sku_ul.children('.col05').text();
        var count = sku_ul.find('.num_show').val();
        // 计算商品的小计
        var amount = parseInt(count)*parseFloat(price);
        // 设置商品的小计
        sku_ul.children('.col07').text(amount.toFixed(2)+'元')
    }

    // 全选和全不选
    $('.settlements').find(':checkbox').change(function () {
        // 获取全选checkbox的选中状态
        var is_checked = $(this).prop('checked');
        // 设置商品的checkbox和全选的checkbox状态保持一致
        $('.cart_list_td').find(':checkbox').each(function () {
            $(this).prop('checked', is_checked)
        });
        // 更新页面信息
        update_page_info()
    });

    // 商品的checkbox状态发生改变时,设置全选checkbox的状态改变
    $('.cart_list_td').find(':checkbox').change(function () {
        // 获取所有商品checkbox的数目
        var all_len = $('.cart_list_td').find(':checkbox').length;
        // 获取被选中的商品checkbox的数目
        var check_len = $('.cart_list_td').find(':checked').length;
        // 判断
        var is_checked = true;
        if (check_len < all_len){
            is_checked = false
        }
        // 设置全选checkbox的选中状态
        $('.settlements').find(':checkbox').prop('checked', is_checked);
        // 更新页面信息
        update_page_info()
    });

    // 更新购物车商品的信息
    var error_update = false;
    var total_count = 0;
    function update_remote_cart_info(sku_id, count) {
        var csrf = $('input[name="csrfmiddlewaretoken"]').val();
        // 组织参数
        var params = {'sku_id':sku_id, 'count':count, 'csrfmiddlewaretoken':csrf};
        // 更新购物车记录
        // 设置ajax 请求为同步
        $.ajaxSettings.async = false;
        // 发起ajax post请求,访问/cart/update, 传递参数:sku_id count
        $.post('/cart/update', params, function (data) {
            if (data.res === 5){
                // 更新成功
                error_update = false;
                total_count = data.total_count
            }
            else{
                // 更新失败
                error_update = true;
                alert(data.errmsg)
            }
        })
        // 设置ajax请求为异步, false 代表为 同步 true 代表异步
        $.ajaxSettings.async = true
    }

    var total_count = 0;
    // 购物车记录的增加
    $('.add').click(function () {
        // 获取商品的id和商品的数目
        var count = $(this).next().val();
        var sku_id = $(this).next().attr('sku_id');

        count = parseInt(count)+1;

        // 更新购物车记录
        update_remote_cart_info(sku_id, count);

        // 进行处理
        if (error_update == false){
            // 重新设置商品的数目
            $(this).next().val(count)
            // 更新商品的小计
            update_sku_amount($(this).parents('ul'))
            // 判断是否更新选中商品的总件数和总金额
            is_checked = $(this).parents('ul').find(':checkbox').prop('checked');
            if (is_checked){
                // 更新页面信息
                update_page_info()
            }
            // 更新页面购物车商品的总件数
            $('.total_count').children('em').text(total_count)
        }
    })

    // 购物车记录的减少
    $('.minus').click(function () {
        // 获取商品的id和商品的数目
        console.log('666')
        var count = $(this).prev().val();
        var sku_id = $(this).prev().attr('sku_id');

        count = parseInt(count)-1
        if (count <= 0){
            return
        }

        // 更新购物车记录
        update_remote_cart_info(sku_id, count)

        // 进行处理
        if (error_update == false){
            // 重新设置商品的数目
            $(this).prev().val(count)
            // 更新商品的小计
            update_sku_amount($(this).parents('ul'))
            // 判断是否更新选中商品的总件数和总金额
            is_checked = $(this).parents('ul').find(':checkbox').prop('checked')
            if (is_checked){
                // 更新页面信息
                update_page_info()
            }
            // 更新页面购物车商品的总件数
            $('.total_count').children('em').text(total_count)
        }
    })

    // 保存用户输入之前购物车中商品的数目
    var pre_count = 0
    $('.num_show').focus(function () {
        pre_count = $(this).val()
    })

    // 手动输入购物车商品数目
    $('.num_show').blur(function () {
        // 获取商品的id和商品的数目
        var count = $(this).val()
        var sku_id = $(this).attr('sku_id')

        // 判断用户输入的商品数目是否合法
        if (isNaN(count) || count.trim().length==0 || parseInt(count)<=0){
            // 设置商品的数目为用户输入之前的数目
            $(this).val(pre_count)
            return
        }

        // 更新购物车记录
        count = parseInt(count)
        update_remote_cart_info(sku_id, count)

        // 进行处理
        if (error_update == false){
            // 重新设置商品的数目
            $(this).val(count)
            // 更新商品的小计
            update_sku_amount($(this).parents('ul'))
            // 判断是否更新选中商品的总件数和总金额
            is_checked = $(this).parents('ul').find(':checkbox').prop('checked')
            if (is_checked){
                // 更新页面信息
                update_page_info()
            }
            // 更新页面购物车商品的总件数
            $('.total_count').children('em').text(total_count)
        }
        else{
            // 设置商品的数目为用户输入之前的数目
            $(this).val(pre_count)
        }
    })

    // 删除购物车记录
    $('.cart_list_td').children('.col08').children('a').click(function () {
        // 获取商品的id
        var sku_id = $(this).parents('ul').find('.num_show').attr('sku_id');
        var csrf = $('input[name="csrfmiddlewaretoken"]').val()
        var sku_ul = $(this).parents('ul')
        // 组织参数
        params = {'sku_id':sku_id, 'csrfmiddlewaretoken':csrf}
        // 发起ajax post请求,访问/cart/delete, 传递参数:sku_id
        $.post('/cart/delete', params, function (data) {
            if (data.res == 3){
                // 删除成功
                // 移除页面商品所在的ul
                sku_ul.remove() // 移除自身和子元素 empty:只移除子元素
                // 获取sku_ul中checkbox的选中状态
                var is_checked = sku_ul.find(':checkbox').prop('checked')
                if (is_checked){
                    // 更新页面信息
                    update_page_info()
                }
                // 设置页面购物车中商品的总件数
                $('.total_count').children('em').text(data.total_count)
            }
            else{
                // 删除失败
                alert(data.errmsg)
            }
        })
    })

    </script>
{% endblock bottomfiles %}

在这里插入图片描述

cast.views.py编写

from django.shortcuts import render
from django.views import View
from django.http import JsonResponse
from django_redis import get_redis_connection
from goods.models import GoodsSKU
from utils.mixin import LoginRequredMixIn


# Create your views here.

class CartAddView(View):
    def post(self, request):

        user = request.user
        if not user.is_authenticated:
            return JsonResponse({'res': 0, 'errmsg': '请先登录!'})

        sku_id = request.POST.get('sku_id')
        count = request.POST.get('count')

        if not all([sku_id, count]):
            return JsonResponse({'res': 1, 'errmsg': '数据不完整!'})

        try:
            count = int(count)
        except Exception:
            return JsonResponse({'res': 2, 'errmsg': '商品数目错误'})

        try:
            sku = GoodsSKU.objects.get(pk=sku_id)
        except GoodsSKU.DoesNotExist:
            return JsonResponse({'res': 3, 'errmsg': '商品不存在'})

        coon = get_redis_connection('default')

        cart_key = 'cart_%d' % user.id

        cart_count = coon.hget(cart_key, sku_id)

        if count > sku.stock:
            return JsonResponse({'res': 4, 'errmsg': '存库不足!'})

        if cart_count:
            count += int(cart_count)

        # 设置hash中sku对应得值
        coon.hset(cart_key, sku_id, count)

        total_count = coon.hlen(cart_key)

        return JsonResponse({'res': 5, 'message': '添加成功!', 'total_count': total_count})


class CartInfoView(LoginRequredMixIn):
    def get(self, request):
        user = request.user
        # 获取购物车商品信息
        coon = get_redis_connection('default')
        cart_key = 'cart_%d' % user.id
        cart_dict = coon.hgetall(cart_key)

        skus = []
        total_count = 0
        total_price = 0
        for sku_id, count in cart_dict.items():
            sku = GoodsSKU.objects.get(pk=sku_id)
            amount = sku.price * int(count)
            sku.amount = amount
            sku.count = int(count)
            skus.append(sku)
            total_count += int(count)
            total_price += amount

        context = {
            'total_count': total_count,
            'total_price': total_price,
            'skus': skus
        }

        return render(request, 'cart.html', context)


# 购物车记录更新
class CartUpdateView(View):
    def post(self, request):
        user = request.user
        if not user.is_authenticated:
            return JsonResponse({'res': 0, 'errmsg': '请先登录'})

        sku_id = request.POST.get('sku_id')
        count = request.POST.get('count')

        if not all([sku_id, count]):
            return JsonResponse({'res': 1, 'errmsg': '数据不完整!'})

        try:
            count = int(count)
        except Exception:
            return JsonResponse({'res': 2, 'errmsg': '商品数目错误'})

        try:
            sku = GoodsSKU.objects.get(pk=sku_id)
        except GoodsSKU.DoesNotExist:
            return JsonResponse({'res': 3, 'errmsg': '商品不存在'})

        coon = get_redis_connection('default')

        cart_key = 'cart_%d' % user.id

        if count > sku.stock:
            return JsonResponse({'res': 4, 'errmsg': '存库不足!'})

        # 设置hash中sku对应得值
        coon.hset(cart_key, sku_id, count)

        values = coon.hvals(cart_key)

        total_count = sum(values)

        return JsonResponse({'res': 5, 'message': '更新成功!', 'total_count': total_count})


class CartDeleteView(View):
    def post(self, request):
        user = request.user
        if not user.is_authenticated:
            return JsonResponse({'res': 0, 'errmsg': '请先登录'})

        sku_id = request.POST.get('sku_id')

        if not sku_id:
            return JsonResponse({'res': 1, 'errmsg': '无效的商品id'})

        try:
            GoodsSKU.objects.get(pk=sku_id)
        except GoodsSKU.DoesNotExist:
            return JsonResponse({'res': 2, 'errmsg': '商品不存在!'})

        coon = get_redis_connection('default')

        cart_key = 'cart_%d' % user.id

        coon.hdel(cart_key, sku_id)

        values = coon.hvals(cart_key)

        values = [int(value.decode()) for value in values]


        total_count = sum(values)

        return JsonResponse({'res': 3, 'message': '删除成功!', 'total_count': total_count})

在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述

在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述在这里插入图片描述
在这里插入图片描述在这里插入图片描述在这里插入图片描述
order.html页面编写

{% extends 'base_detail_list.html' %}
{% load static %}
{% block title %}天天生鲜-商品详情{% endblock %}

{% block main_content %}

    <div class="breadcrumb">
        <a href="{% url 'goods:index' %}">全部分类</a>
        <span>></span>
        <a href="{% url 'goods:index' %}">{{ sku.type.name }}</a>
        <span>></span>
        <a href="#">商品详情</a>
    </div>
    <div class="goods_detail_con clearfix">
        <div class="goods_detail_pic fl"><img src="{{ sku.image.url }}" alt=""></div>

        <div class="goods_detail_list fr">
            <h3>{{ sku.name }}</h3>
            <p>{{ sku.desc }}</p>
            <div class="prize_bar">
                <span class="show_pirze">¥<em>{{ sku.price }}</em></span>
                <span class="show_unit">单  位:{{ sku.unite }}</span>
            </div>
            <div class="goods_num clearfix">
                <div class="num_name fl">数 量:</div>
                <div class="num_add fl">
                    <input type="text" class="num_show fl" value="1">
                    <a href="javascript:;" class="add fr">+</a>
                    <a href="javascript:;" class="minus fr">-</a>
                </div>
            </div>
            <div>
                <p>其他规格:</p>
                <ul>
                    {% for sku in same_spu_skus %}
                        <li><a href="{% url 'goods:detail' sku.id %}">{{ sku.name }}</a></li>
                    {% endfor %}
                </ul>

            </div>


            <div class="total">总价:<em>16.80</em></div>
            <div class="operate_btn">
                <a href="javascript:;" class="buy_btn">立即购买</a>
                <a href="javascript:;" sku_id="{{ sku.id }}" class="add_cart" id="add_cart">加入购物车</a>
            </div>
        </div>
    </div>

    <div class="main_wrap clearfix">
        <div class="l_wrap fl clearfix">
            <div class="new_goods">
                <h3>新品推荐</h3>
                <ul>
                    {% for sku in new_skus %}
                        <li>
                            <a href="{% url 'goods:detail' sku.id %}"><img src="{{ sku.image.url }}" alt=""></a>
                            <h4><a href="#">{{ sku.name }}</a></h4>
                            <div class="prize">{{ sku.price }}</div>
                        </li>
                    {% endfor %}
                </ul>
            </div>
        </div>

        <div class="r_wrap fr clearfix">
            <ul class="detail_tab clearfix">
                <li class="active">商品介绍</li>
                <li>评论</li>
            </ul>

            <div class="tab_content">
                <dl>
                    <dt>商品详情:</dt>
                    <dd>{{ sku.goods.detail|safe }}
                    </dd>
                </dl>
            </div>
            <div class="tab_content">
                <dl>
                    {% for order in sku_order %}
                        <dt>评论时间:{{ order.update_time }}&nbsp;&nbsp;用户名:{{ order.order.user.username }}</dt>
                        <dd>评论内容:{{ order.comment }}</dd>
                    {% endfor %}
                </dl>
            </div>
        </div>
    </div>
{% endblock %}

{% block bottom %}
    <div class="add_jump"></div>
    {% csrf_token %}
{% endblock %}
{% block bottomfiles %}
    <script type="text/javascript" src="{% static 'js/jquery-1.12.4.min.js' %}"></script>
    <script type="text/javascript">
        update_goods_amount();
        function update_goods_amount() {
            // 获取商品的数量和价格
            var price = $('.show_pirze').children('em').text();
            var count = $('.num_show').val();
            // 计算商品的总价
            price = parseFloat(price);
            count = parseInt(count);
            var amount = price * count;
            $('.total').children('em').text(amount.toFixed(2) + '元');

        }

        // 增加商品的数量
        $('.add').click(function () {
            // 获取商品原油的数目
            var count = $('.num_show').val();
            count = parseInt(count) + 1;
            $('.num_show').val(count);
            update_goods_amount();
        });


        // 减少商品的数量
        $('.minus').click(function () {
            // 获取商品原油的数目
            var count = $('.num_show').val();
            count = parseInt(count) - 1;
            if (count <= 0) {
                count = 1;
            }

            $('.num_show').val(count);
            update_goods_amount();
        });

        // 手动输入商品的数量
        $('.num_show').blur(function () {
            // 获取商品原油的数目
            var count = $(this).val();
            // 校验count是否合法
            if (isNaN(count) || count.trim().length == 0 || parseInt(count) <= 0) {
                count = 1
            }
            // 重新设置商品的数目
            $(this).val(parseInt(count));
            update_goods_amount();
        });

        // 获取add_cart div元素左上角坐标
        var $add_x = $('#add_cart').offset().top;
        var $add_y = $('#add_cart').offset().left;

        // 获取show_count div元素左上角坐标
        var $to_x = $('#show_count').offset().top;
        var $to_y = $('#show_count').offset().left;


        $('#add_cart').click(function () {
            // 获取商品的id和数量
            var sku_id = $(this).attr('sku_id');
            var count = $('.num_show').val();
            var scrf = $('input[name="csrfmiddlewaretoken"]').val();

            // 发起请求
            $.ajax({
                type: 'post',
                url: "{% url 'cart:add' %}",
                data: {
                    sku_id: sku_id,
                    count: count,
                    csrfmiddlewaretoken: scrf,
                },
                success: function (data) {
                    if (data.res === 5) {
                        $(".add_jump").css({'left': $add_y + 80, 'top': $add_x + 10, 'display': 'block'});
                        $(".add_jump").stop().animate({
                                'left': $to_y + 7,
                                'top': $to_x + 7
                            },
                            "fast", function () {
                                $(".add_jump").fadeOut('fast', function () {
                                    $('#show_count').html(data.total_count);
                                });
                            });
                    } else {
                        alert(data.errmsg)
                    }
                }
            });
        })
    </script>
{% endblock %}

order.vews.py编写

from django.shortcuts import redirect, reverse, render
from goods.models import GoodsSKU
from user.models import Address
from django_redis import get_redis_connection
from utils.mixin import LoginRequredMixIn
from django.http import JsonResponse
from order.models import OrderInfo, OrderGoods
from datetime import datetime
from django.db import transaction
from django.conf import settings
from django.views import View
from alipay import AliPay
from time import sleep


# Create your views here.

class OrderPlaceView(LoginRequredMixIn):
    def post(self, request):

        user = request.user

        sku_ids = request.POST.getlist('sku_ids')

        if not sku_ids:
            return redirect(reverse('cart:show'))

        coon = get_redis_connection('default')

        cart_key = 'cart_%d' % user.id

        skus = []
        total_count = 0
        total_price = 0

        for sku_id in sku_ids:
            sku = GoodsSKU.objects.get(pk=sku_id)
            # 获取商品的数量
            conut = coon.hget(cart_key, sku_id)
            amount = sku.price * int(conut)
            sku.count = int(conut.decode())
            sku.amount = amount
            skus.append(sku)
            total_count += int(conut)
            total_price += amount

        # 运费
        transit_price = 10  # 假数据, 写死
        # 实付费
        total_pay = total_price + transit_price

        addrs = Address.objects.filter(user=user)

        sku_ids = ",".join(sku_ids)

        # 组织上下文
        context = {
            'skus': skus,
            'total_count': total_count,
            'total_price': transit_price,
            'transit_price': transit_price,
            'total_pay': total_pay,
            'addrs': addrs,
            'sku_ids': sku_ids}

        return render(request, 'place_order.html', context)


# 悲观锁
class OrderCommitView(LoginRequredMixIn):

    @transaction.atomic
    def post(self, request):
        user = request.user

        if not user.is_authenticated:
            return JsonResponse({'res': 0, 'errmsg': '用户未登录!'})

        addr_id = request.POST.get('addr_id')
        pay_method = request.POST.get('pay_method')
        sku_ids = request.POST.get('sku_ids')

        if not all([addr_id, pay_method, sku_ids]):
            return JsonResponse({'res': 1, 'errmsg': '参数不完整!'})

        # todo 校验支付方式
        if pay_method not in OrderInfo.PAY_METHODS.keys():
            return JsonResponse({'res': 2, 'errmsg': '非法的支付方式!'})

        try:
            addr = Address.objects.get(pk=addr_id)
        except Address.DoesNotExist:
            return JsonResponse({'res': 3, 'errmsg': '地址非法'})

        # TODO: 创建订单
        order_id = datetime.now().strftime('%Y%m%d%H%M%S') + str(user.id)
        # 运费
        transit_price = 10  # 假数据, 写死
        total_count = 0
        total_price = 0
        coon = get_redis_connection('default')
        cart_key = 'cart_%d' % user.id
        # 设置保存点
        save_id = transaction.savepoint()
        try:
            # TODO  想订单信息表中添加一条记录
            order = OrderInfo.objects.create(
                order_id=order_id,
                user=user,
                addr=addr,
                pay_method=pay_method,
                total_count=total_count,
                total_price=total_price,
                transit_price=transit_price
            )

            # todo 用户的订单中有几个商品就要添加几条记录
            sku_ids = sku_ids.split(',')
            for sku_id in sku_ids:
                try:
                    sku = GoodsSKU.objects.select_for_update().get(id=sku_id)  # 悲观锁
                except GoodsSKU.DoesNotExist:
                    transaction.savepoint_rollback(save_id)
                    return JsonResponse({'res': 4, 'errmsg': '商品不存在!'})

                # 获取商品的数目
                count = coon.hget(cart_key, sku_id)

                # todo 判断商品的库存
                if int(count) > sku.stock:
                    transaction.savepoint_rollback(save_id)
                    return JsonResponse({'res': 6, 'errmsg': '商品库存不足'})

                # todo to订单信息表中添加一条记录
                OrderGoods.objects.create(
                    order=order,
                    sku=sku,
                    count=int(count),
                    price=sku.price,
                )

                # todo 更新商品的库存销量和库存
                sku.stock -= int(count)
                sku.sales += int(count)
                sku.save()

                # todo 累加计算商品的订单的总数量和总价格
                amount = sku.price * int(count)
                total_count += int(count)
                total_price += amount

            # todo 更新订单信息表中的商品的总数量和价格
            order.total_count = total_count
            order.total_price = total_price
            order.save()
        except Exception:
            transaction.savepoint_rollback(save_id)
            return JsonResponse({'res': 7, 'errmsg': '下单失败!'})
        # 提交
        transaction.savepoint_commit(save_id)
        # todo 清楚用户的购物车记录
        coon.hdel(cart_key, *sku_ids)

        return JsonResponse({'res': 5, 'message': '创建成功!'})


# 乐观锁
class OrderCommitView2(LoginRequredMixIn):

    @transaction.atomic
    def post(self, request):
        user = request.user

        if not user.is_authenticated:
            return JsonResponse({'res': 0, 'errmsg': '用户未登录!'})

        addr_id = request.POST.get('addr_id')
        pay_method = request.POST.get('pay_method')
        sku_ids = request.POST.get('sku_ids')

        if not all([addr_id, pay_method, sku_ids]):
            return JsonResponse({'res': 1, 'errmsg': '参数不完整!'})

        # todo 校验支付方式
        if pay_method not in OrderInfo.PAY_METHODS.keys():
            return JsonResponse({'res': 2, 'errmsg': '非法的支付方式!'})

        try:
            addr = Address.objects.get(pk=addr_id)
        except Address.DoesNotExist:
            return JsonResponse({'res': 3, 'errmsg': '地址非法'})

        # TODO: 创建订单
        order_id = datetime.now().strftime('%Y%m%d%H%M%S') + str(user.id)
        # 运费
        transit_price = 10  # 假数据, 写死
        total_count = 0
        total_price = 0
        coon = get_redis_connection('default')
        cart_key = 'cart_%d' % user.id
        # 设置保存点
        save_id = transaction.savepoint()
        try:
            # TODO  想订单信息表中添加一条记录
            order = OrderInfo.objects.create(
                order_id=order_id,
                user=user,
                addr=addr,
                pay_method=pay_method,
                total_count=total_count,
                total_price=total_price,
                transit_price=transit_price
            )

            # todo 用户的订单中有几个商品就要添加几条记录
            sku_ids = sku_ids.split(',')
            for sku_id in sku_ids:
                for i in range(settings.NUMBER_OF_FAILED_ORDER_TIMES):
                    try:
                        sku = GoodsSKU.objects.get(id=sku_id)  # 悲观锁
                    except GoodsSKU.DoesNotExist:
                        transaction.savepoint_rollback(save_id)
                        return JsonResponse({'res': 4, 'errmsg': '商品不存在!'})

                    # 获取商品的数目
                    count = coon.hget(cart_key, sku_id)

                    # todo 判断商品的库存
                    if int(count) > sku.stock:
                        transaction.savepoint_rollback(save_id)
                        return JsonResponse({'res': 6, 'errmsg': '商品库存不足'})

                    # todo 更新商品的库存销量和库存
                    orign_stock = sku.stock
                    new_stock = orign_stock - int(count)
                    new_slales = sku.sales + int(count)

                    res = GoodsSKU.objects.filter(
                        id=sku_id, stock=orign_stock).update(
                        stock=new_stock, sales=new_slales)
                    if res == 0:
                        if i == settings.NUMBER_OF_FAILED_ORDER_TIMES - 1:
                            transaction.savepoint_rollback(save_id)
                            return JsonResponse({'res': 7, 'errmsg': '下单失败!'})
                        continue

                    # todo to订单信息表中添加一条记录
                    OrderGoods.objects.create(
                        order=order,
                        sku=sku,
                        count=int(count),
                        price=sku.price,
                    )

                    # todo 累加计算商品的订单的总数量和总价格
                    amount = sku.price * int(count)
                    total_count += int(count)
                    total_price += amount

                    break

            # todo 更新订单信息表中的商品的总数量和价格
            order.total_count = total_count
            order.total_price = total_price
            order.save()
        except Exception:
            transaction.savepoint_rollback(save_id)
            return JsonResponse({'res': 7, 'errmsg': '下单失败!'})
        # 提交
        transaction.savepoint_commit(save_id)
        # todo 清楚用户的购物车记录
        coon.hdel(cart_key, *sku_ids)

        return JsonResponse({'res': 5, 'message': '创建成功!'})


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': '订单错误!'})

        alipay = AliPay(
            appid=settings.ALIPAY_APP_ID,
            app_notify_url=None,  # 默认回调url
            app_private_key_path=settings.APP_PRIVATE_KEY_PATH,
            # 支付宝的公钥,验证支付宝回传消息使用,不是你自己的公钥,
            alipay_public_key_path=settings.ALIPAY_PUBLIC_KEY_PATH,
            sign_type="RSA2",  # RSA 或者 RSA2
            debug=True  # 默认False
        )
        total_pay = order.total_price + order.transit_price
        order_string = alipay.api_alipay_trade_page_pay(
            out_trade_no=order_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})


class OrderCheckView(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': '订单错误!'})

        alipay = AliPay(
            appid=settings.ALIPAY_APP_ID,
            app_notify_url=None,  # 默认回调url
            app_private_key_path=settings.APP_PRIVATE_KEY_PATH,
            # 支付宝的公钥,验证支付宝回传消息使用,不是你自己的公钥,
            alipay_public_key_path=settings.ALIPAY_PUBLIC_KEY_PATH,
            sign_type="RSA2",  # RSA 或者 RSA2
            debug=True  # 默认False
        )

        # 调用支付宝的交易查询接口
        while True:
            response = alipay.api_alipay_trade_query(order_id)

            code = response.get('code')
            if code == '10000' and response.get(
                    'trade_status') == 'TRADE_SUCCESS':
                # 支付成功
                # 更新订单的状态
                train_no = response.get('trade_no')
                order.trade_no = train_no
                # 将支付状态改为待评价
                order.order_status = 4
                order.save()
                return JsonResponse({'res': 3, 'message': '支付成功!'})
            elif (code == '10000' and response.get('trade_status') == 'WAIT_BUYER_PAY') or code == '40004':
                # 等待支付
                sleep(5)
                continue
            else:
                # 支付失败
                return JsonResponse({'res': 4, 'errmsg': '支付失败!'})

在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_42611683/article/details/107398380