订单完成

  • 订单结算页面

    • 订单展示用的序列化器
    # 前端需要运费数据和商品信息数据的字典列表,这里使用嵌套序列化器返回数据
    class CartSKUSerializer(serializers.ModelSerializer):# 因为商品表没有count字段,所以要定义它count=serializers.IntegerField()class Meta:model=SKUfields=('id','name', 'default_image_url', 'price', 'count')class OrderSettlementSerializer(serializers.Serializer):freight = serializers.DecimalField(max_digits=10,decimal_places=2)skus = CartSKUSerializer(many=True)
    
    • 视图实现业务逻辑
    class OrderSettlementView(APIView):def get(self, request):user=request.userconn=get_redis_connection('cart')cart_dict=conn.hgetall('cart_%s'%user.id)cart_list=conn.smembers('cart_selected_%s'%user.id)cart={}for sku_id in cart_list:cart[sku_id]=cart_dict[sku_id]['count']skus=SKU.objects.filter(id__in=cart.keys())for sku in skus:sku.count=cart[sku.id]['count']freight=Decimal(10.00)serializer=OrderSettlementSerializer({'freight':freight,'skus':skus})return Response(serializer.data)
    
  • 保存订单, 视图逻辑由CreateAPIView提供, 我们需要重写序列化器的保存操作

    class SaveOrderView(CreateAPIView):serializer_class= SaveOrderSerializerclass SaveOrderSerializer(serializers.ModelSerializer):class Meta:model = OrderInfofields=('order_id','address','pay_method')read_only_fields=('order_id',)extra_kwargs={'address':{'write_only':True,'required':True,},'pay_method':{'write_only':True,'required':True}}def create(self, validated_data):# 获取当前下单用户user=self.context['request'].user# 生成订单编号order_id = datetime.now().strftime('%Y%m%d%H%M%S')+('%09s'%user.id)# 保存订单基本信息数据 OrderInfoaddress=validated_data.get('address')pay_method=validated_data['pay_method']with transaction.atomic():save_id=transaction.savepoint()try:order =OrderInfo.objects.create(order_id=order_id,user=user,address=address,total_count=0,total_amount=Decimal(0),freight=Decimal(10.00),pay_method=pay_method,status=OrderInfo.ORDER_STATUS_ENUM['UNSEND'] if pay_method == OrderInfo.PAY_METHODS_ENUM['CASH'] else OrderInfo.ORDER_STATUS_ENUM['UNPAID'])# 从redis中获取购物车结算商品数据conn=get_redis_connection('cart')cart_dict=conn.hgetall('cart_%s'%user.id)cart_list=conn.smembers('cart_selected_%s'%user.id)cart={}for sku_id in cart_list:cart[int(sku_id)]=int(cart_dict[sku_id])skus=SKU.objects.filter(id__in=cart.keys())          # 遍历结算商品:for sku in skus:sku_count=cart[sku.id]# 判断商品库存是否充足origin_stock = sku.stockorigin_sales = sku.salesif sku_count > origin_stock:transcation.save_point_rollback(save_id)raise serializers.ValidationError('商品库存不足')# 减少商品库存,增加商品销量new_stock=origin_stock-sku_countnew_sales=origin_sales+sku_countsku.stock=new_stocksku.sales=new_salessku.save()# 累计商品的SPU 销量信息sku.goods.total_count+=sku_countsku.goods.save()# 累计订单基本信息的数据order.total_count+=sku_countorder.total_amount+=(int(sku_count)*int(sku.price))# 保存订单商品数据OrderInfo.objects.create(order=order,sku=sku,count=sku_count,price=sku.price)order.total_amount+=order.freightorder.save()except Exception as e:logger.error(e)transcation.savepoint_rollback(save_id)raisetransaction.savepoint_commit(save_id)# 删除的是fields列表conn.hdel('cart_%s'%user.id,*cart_list)conn.srem('cart_selected_%s'%user.id,*cart_list)return order
    
  • 并发处理使用乐观锁, 因为资源竞争的问题, 多用户之前执行程序不具备完整性

    # 乐观锁的原理是死循环和验证数据
    # 在对数据库进行操作时
    for id in sku_list:while True:# 因为查询集具备缓存和惰性的原因, 不使用查询集sku=SKU.objects.get(id=id)...# 查询语句的原子性, 先验证数据没有发生变化ret=SKU.objects.get(id=sku.id,stock=stock,sales=sales).update(stock=new_stock)if ret==0:continue...# 没有出错就进行下一个sku_idbreak
    # 同时修改事务执行的隔离级别为Read committed
    
  • 发起支付

    class PaymentView(APIView):def get(self, request, order_id):try:order=OrderInfo.objects.get(order_id=order_id,user=request.user,pay_method=OrderInfo.PAY_METHODS_ENUM['ALIPY'],status=OrderInfoi.ORDERS_STATUS_ENUM['UNPAID'])except Exception as e:return Reaponse({'message':'订单信息有错误'})# 创建alipay对象alipay=AliPay(appid=settings.ALIPAY_APPID,app_notify_url=None,  # 默认回调urlapp_private_key_path=os.path.join(os.path.dirname(os.path.abspath(__file__)),                                "keys/app_private_key.pem"),                                 alipay_public_key_path=os.path.join(os.path.dirname(os.path.abspath(__file__)),                                  "keys/alipay_public_key.pem"), sign_type="RSA2",  # RSA 或者 RSA2debug=settings.ALIPAY_DEBUG  # 默认False)order_string=alipay.api_alipay_trade_page_pay(out_trade_no=order_id,total_amount=str(order.total_amount),subject="美多商城%s" % order_id,return_url="http://www.meiduo.site:8080/pay_success.html",)alipay_url=settings.ALIPAY_URL+order_stringreturn Response({'alipay_url':alipay_url})
    
  • 保存支付结果, 回调链接携带从支付宝返回的查询字符串, 然后前端发给后端, 后端做保存操作, 并返回给前端支付宝流水编号.

    class PaymentStatusView(APIView):def put(self, request):# 将查询字符串转换为字典data = request.query_params.dict()sign=data.pop('sign')# 生成alipay对象alipay = AliPay(appid=settings.ALIPAY_APPID,app_notify_url=None,  # 默认回调urlapp_private_key_path=os.path.join(os.path.dirname(os.path.abspath(__file__)),             "keys/app_private_key.pem"),alipay_public_key_path=os.path.join(os.path.dirname(os.path.abspath(__file__)),"keys/alipay_public_key.pem"), sign_type="RSA2",  # RSA 或者 RSA2debug=settings.ALIPAY_DEBUG  # 默认False)# 验证是否是支付宝返回的数据success=alipay.verify(data,sign)if success:order_id=data.get('out_trade_no')trade_id=data.get('trade_id')Payment.objects.create(order_id=order_id,trade_id=trade_id)                                                                OrderInfo.objects.filter(order_id=order_id).update(status=OrderInfo.ORDER_STATUS_ENUM["UNCOMMENT"])return Response({'trade_id': trade_id})else:return Response({'message': '非法请求'}, status=403)
    

美多商城项目订单和支付模块总结相关推荐

  1. JAVA项目实战开发电商项目案例(十)订单与支付模块

    文章目录 1项目架构 2项目采用技术 3订单与支付模块功能演示 4如何开发支付宝的支付模块以及订单模块 4.1首先需要编写前端页面以及JS文件 4.2其次需要编写JAVA后台接口 4.3支付模块分析 ...

  2. 【美多商城项目01】了解主要需求和架构设计,创建配置工程

    一.美多商城项目介绍 1.1 项目需求分析 需求分析原因 项目中,需求驱动开发,即开发人员需要以需求为目标来实现业务逻辑. 需求分析方式 企业中,借助产品原型图分析需求. 需求分析完后,前端按照产品原 ...

  3. python美多商城项目百度网盘_美多商城项目(七)

    正文共: 7620字 4图 预计阅读时间: 20分钟 每日分享 If you can change your mind, you can change your life. 如果你愿意改变你的想法,你 ...

  4. python美多商城项目百度网盘_美多商城项目(六)

    正文共: 4850字 4图 预计阅读时间: 13分钟 每日分享 Never let success get to your head, and never let failure get to you ...

  5. Django3+Vue美多商城项目的总结

    文章目录 项目说明 主要环境搭建 主要技术实现 django 的配置文件 celery的使用(异步发送短信验证码和邮箱验证链接) 容联云通讯短信平台 QQ登录 jwt实现加密解密验证实现数据的安全性 ...

  6. Django框架之美多商城项目

    后续技术类文档更新到微信公众号-------->>喜欢的扫码关注 美多商城 1. 项目的准备 - 分析商业模式:B2C- 开发流程- 项目的架构- 创建工程- 配置 2. 登录模块 2.1 ...

  7. 【谷粒商城之订单服务-支付】

    本笔记内容为尚硅谷谷粒商城订单服务支付部分 目录 一.支付宝沙箱 沙箱环境 二.公钥.私钥.加密.加签.验签 1.公钥私钥 2.加密和数字签名 3.对称加密和非对称加密 三.内网穿透 四.整合支付 1 ...

  8. 美多商城项目之用户登录:账号登录、QQ登录

    一.账号登录 1.1 用户名登录 1. 用户名登录逻辑分析 2. 用户名登录接口设计 1.请求方式 选项 方案 请求方法 POST 请求地址 /login/ 2.请求参数:表单 参数名 类型 是否必传 ...

  9. Flutter-防京东商城项目-订单列表、订单详情页面布局-45

    一直觉得自己写的不是技术,而是情怀,一个个的教程是自己这一路走来的痕迹.靠专业技能的成功是最具可复制性的,希望我的这条路能让你们少走弯路,希望我能帮你们抹去知识的蒙尘,希望我能帮你们理清知识的脉络,希 ...

最新文章

  1. 微软10亿美元砸入OpenAI:明为AGI,暗争谷歌,被指云计算换投资
  2. Redis NoSQL
  3. HttpClient实现CSDN自动登录
  4. ​iIIegalArgumentException:the bind value at index 1 isnull
  5. 博客屏蔽搜索引擎只是个笑话!!
  6. LETTERS (信息学奥赛一本通-T1212)
  7. Learn OpenGL(七)——OpenGL中使用着色器的基本步骤及GLSL渲染简单示例
  8. LeetCode【119. 杨辉三角 II】
  9. Julia: h5write ,h5read 与ASCIIString、Float64及效率比较
  10. bfs和dfs:poj2386和leetcode130
  11. vue 中使用海康威视视频插件
  12. 《矩阵分析与应用》(第2版)———知识+Matlab2018a——2nd
  13. 一个好的热修复技术,将为你的 App助力百倍
  14. 打开新材料世界的大门:拓扑电子材料目录问世
  15. 我的消费记录怎么查看呢?
  16. URI跳转方式地图导航的代码实践
  17. 智联“焊”界,数字未来
  18. haas506 2.0开发教程-hota(仅支持2.2以上版本)
  19. 我的面试经历--缘起
  20. Java 三种循环的流程图画法总结(for,while,do-while循环)

热门文章

  1. C语言与Java实现:数制转换
  2. AJAX框架简笔画风景简单,好看简单的简笔画风景
  3. 好用的企微scrm系统应具备哪些能力
  4. Apache 解析漏洞
  5. 牛客小白月赛8 F-数列操作 (有序表)
  6. 改善编程体验: IdeaVimExtension介绍 1
  7. golang 如何快速测试代码
  8. 如何为Matlab添加自己喜欢的字体
  9. 基于51单片机的8个小彩灯花样流水灯proteus仿真汇编语言
  10. 深入理解for update 和 lock in share mode