文档章节

购物车与商城订单的关系以及技术实现深入分析

技术小树懒
 技术小树懒
发布于 2016/07/15 12:55
字数 2343
阅读 402
收藏 6
点赞 0
评论 0

本站所有文章均为原创,欢迎转载,来源:技术小树懒(www.drw1314.com),作者:锦焕同学

接触商城开发已经有一段时间了,我们从B2C拼团项目做到了C2C视频电商系统。虽然项目都还不算成功,但还是积累了些业务经验,希望可以对大家有用。其实商城最主要的还是订单相关逻辑,例如购物车,下单,改价等。当然,电商还有一些比较麻烦的一些业务,例如sku,运费的合理计算,这不属于我们讨论的范围,今天我们主要分析购物车,商城,以及订单这三者的关系,以及相关数据库设计与伪代码实现。

- 透过现象看本质

首先我们从商城入手,来看看各家的购物车与订单的界面。

1、七乐康(比较传统的B2C医药电商网站)

             (1)购物车

           

             (2)生成订单

               

       

2、微店(微商的开店好帮手,C2C商城)

           (1)购物车

            

          (2)生成订单

            

3、有赞(移动零售服务商,C2C商城)

        (1)购物车

                    

        (2)生成订单

          

    

- 购物车与商城以及订单的关系

从一般的商城来看,可以分为B2C与C2C,也就是单商城系统和多商城系统。单商城的系统,基本上就是全部商品生成一个订单,而多商城系统里面的购物车则是可以根据店铺来分别支付生成订单(如微店)或者全部统一支付然后根据店铺拆分订单(如有赞,淘宝等)。

      总结如下:

          

      如上图所示:

     (1)根据每个店铺生成订单去支付,很好理解,例如我在店铺A,买了1,2,3这几个商品,我只需要生成一个订单号,然后去支付就可以了,后续的退款等各种处理,只需要根据该订单号进行处理即可。

     (2) 那么,最后一个,购物车里面有多个店铺的商品,又需要一起支付的时候怎么办呢?假定我们使用微信支付,微信支付每次下单只能使用唯一一个单号,那么我们只能把不同的店铺,例如店铺A和店铺B的所有商品,都统一放到一个订单号去微信下单支付。但是,这样子又违反了订单规则:不同的店铺存在着不同的订单业务,店铺和订单是一对多的关系,而且每个订单号必须是唯一的。怎么办?这个时候,我们可以把内部订单号和微信下单号做一个映射(也就是图所说的拆单),后续做各种处理例如退款等,就可以通过映射关系去进行处理,如下图:

      

      总结一下他们之间的关系:

      (1)购物车可以存在多个店铺多个商品,可以一次性给钱购买购物车所有商品

      (2)一个订单只能对应一个店铺,一个店铺可以拥有多个订单

      (3)微信下单号只有一个,一个微信下单号可以对应多个内部订单号,一个内部订单号只能对应一个微信下单号。

 

- C2C商城购物车数据库设计与技术实现

 由于B2C商城和C2C大同小异,这里暂且不讨论B2C的设计和实现,相信会C2C实现而不会B2C的同学是不存在的。且纵观目前的商城,大部分慢慢倾向于增加商家入住功能,所以建议预留多商铺功能,即先把商铺表加进去,与商品相关的带上商铺id,只不过目前商铺只有一个就是自己,就这样可以减少业务需求改动带来的大量数据库结构和代码的改动。

如果用户购物车内的商品都是一个店铺的,那么就不存在拆单、映射表这种说法,直接生成唯一订单号作为微信订单号支付就可以,但是谁都不知道需求是如何变化的,既然淘宝都是可以统一支付不同店铺的商品,那么设计的时候最好是支持购物车所有商品统一支付的,这样子就通杀了,不管你是B2C的购物车,还是微店的购物车,还是淘宝的购物车,都能满足需求。如果只能支持不同店铺做分别支付,类似微店这样,那么万一产品要改成支付宝这样子,就又得重新设计映射表,进行拆单了。本人所在公司的产品经理刚开始比较倾向于微店这种产品设计,而我设计系统时,也仅仅往产品的需求思考,而没考虑到淘宝的设计,现在换一个产品又要改为淘宝这种购物车,就感觉深深地掉进了坑里面。这里学到了一个道理,那就是永远不要相信产品经理(哭),当然也不要过度设计,这里其实不是过度设计,只是用多一点时间,就能减少以后的巨大时间,而且产品人员也很喜欢参考大公司的产品功能,毕竟一些基础功能都是经过大量的用户反馈的。

那么我们就以有赞这种做法来设计我们的购物车和订单吧。

      1、订单表

          点击查看原图

     2、购物车表

          QQ截图20160715011215.jpg

      最主要的是:商铺订单号in_trade_no和第三方支付下单号out_trade_no

 

- 下单核心实现(非完整代码)

       

《一》购物车提交过来的下单最终是以不同店铺组成的数组
  如:             

$data = arrray(
           '店铺A' => array('商品1','商品2'),
           '店铺B' => array('商品1','商品2'),
);

《二》只有一个数组时,让商铺订单号in_trade_no和第三方支付下单号out_trade_no一致,这样子的好处是,我们可以认为订单号和下单号一致时就是在一个店铺支付的,而不是多个,这样就可以复用微信下单接口返回的数据,从而对该待付款订单进行付款,而不是再调下单接口生成新的订单号去支付(既可以减少接口调用,也可以减少费单)
        如:            

1234 =》 1234 

$unified_order = WeixinPay::unifiedOrder(
         $this->conf['weixin']['pay_key'],
         $this->openid,1234,$order['pay']*100,$this->appid,
         $this->conf['weixin']['mch_id'],
         $this->conf['weixin']['pay_notify_url'],
         WeixinPay::getNonceStr(),$order['title']
);

$data = array(                              
    'appId' => $this->appid,
    'nonceStr' => $unified_order['nonce_str'],
    'package' => "prepay_id={$unified_order['prepay_id']}",
    'signType' => 'MD5',
     'timeStamp' => strval($_SERVER['time']),
);
$data['paySign'] = WeixinPay::MakeSign($data, $this->conf['weixin']['pay_key']);

$this->vshop_orderWeixinPrepay->setPrePay(1234,$data);
$this->err_msg['ok']['data'] = $data;
$this->_showJsonMsg('ok');

用户支付待付款订单时直接把之前存着的下单数据拿出来:

if(商铺订单号==第三方支付下单号){           //在一个店铺内购买东西
         去微信检查1234这个下单号是否已经支付过了,支付过了则退出,而且如果订单不是未付款状态,例如网络超时等直接报错退出
          通过执行下面代码
          $data = $this->vshop_orderWeixinPrepay->getPrePay(1234);
       	  $this->err_msg['ok']['data'] = $data;
           $this->_showJsonMsg('ok');

}else{          //不一致为什么这么做?请看《三》
    
    重新生成商铺订单号和第三方支付下单号,让其一致
    调用微信下单接口,根据该订单金额等,重新下单

}

《三》多个数组时,每个店铺订单对应相同的第三方支付下单号,但是商铺订单号不能与下单号出现一致的情况,否则就会导致超额付款问题。

    如
      

1234 => 1111
       4567 => 1111
       8910 => 1111

       而不能是
       1234 => 4567
       4567 => 4567
       8910 => 4567

为什么商铺订单号不能与下单号出现一致的情况,否则就会导致超额付款?
场景是用户把几个店铺的商品提交过来,假如3个店铺,我们内部会生成3个内部订单号和一个微信下单号,如果成功支付问题很好解决,假如没有成功支付,前端就会像有赞那样出现3个待付款的订单。
假如这么巧,用户就对        4567 => 4567  这个单进行付款操作,按照上面《二》的逻辑,就会进到getPrePay获取到微信下单号4567的下单数据,记住,微信下单号4567的金额是内部订单号1234,4567, 8910三者金额的和,用户本来想支付第二个内部订单4567的钱,最后却变成了支付三个订单的钱,这是万万不可的,因此要确保商铺订单号不能与下单号出现一致的情况,这很简单,例如加个字母前缀等即可      

1234 => o_4567
       4567 =>o_4567
       8910 =>o_4567

这样子,用户单独支付订单时,永远走的是:《 重新生成商铺订单号和第三方支付下单号,让其一致; 调用微信下单接口,根据该订单金额等,重新下单》这个逻辑,请看《二》。

 

《四》订单的退款,成功付款,只需要结合内部订单号和第三方下单号处理就可以了

© 著作权归作者所有

共有 人打赏支持
技术小树懒
粉丝 0
博文 1
码字总数 2343
作品 0
广州
高级程序员
多渠道分销商城平台系统专业开发

  多渠道分销商城平台系统专业开发《苏134-1619-5045》,多渠道跨平台商城系统。   移动电商引领着全新的商业模式,越来越多的企业需要多渠道跨平台商城管理平台来管理不同电商平台的业务...

系统平台APP开发
2017/12/27
0
0
商城开发方案书

商城开发方案书 一、项目简介 项目名称 :易商城 项目设计方:点多多科技 项目简介 :项目总体由两个部分组成,管理员端与商城端, 管理员端对商城进行总的管理,包括商品分类管理、商品管理...

桃子红了呐
2017/04/30
0
0
Yii 2.0开发一个仿京东商城平台

第1章 课程简介 介绍了课程内容、背景和案例展示。 第2章 项目的准备工作 介绍了如何使用PHP依赖管理工具Composer安装Yii2框架,模拟配置真实企业开发项目运行环境和编辑器。 第3章 项目前台...

15543595340
05/19
0
0
项目复盘—诠释国内电商(一)

2015年-2017年,两年的时间,接触了两次电商项目,自身对于电商的理解从懵懂无知到如今的深入了解。中间踩了很多坑,有自己去挖的,也有前方未知的,对于国内电商,总结了一下步骤帮助大家去...

在雾霾的下午
2017/12/27
0
0
JAVAWEB贵美网上商城完整项目源码(SSH2)

JAVAWEB贵美网上商城完整项目源码(SSH2) 贵美网上商城原是北大青鸟的一个内部项目,项目采用 struts2+spring4+hibernate4+MySQL等技术实现,数据库连接池采用c3p0的方式。 贵美商城包括前后台...

小柒2012
2016/12/28
183
0
React Native开源项目-嘎嘎商城客户端(持续更新中)

纯React Native开发的嘎嘎商城客户端,开源地址:https://github.com/jiangqqlmj/GaGaMall 欢迎大家star,fork.... 本开源项目由江清清的技术专栏整理(http://www.lcode.org/),转发请求注明来源...

jiangqq781931404
2016/08/05
0
0
(四)购物商城数据库设计-订单系统设计

上一篇文章购物商城数据库设计-商品表设计中我们介绍了商品表的设计与实现。 接下来我们来一起设计下订单表。 订单系统在整个商城体系中的作用非常重要,因为一些业务的开展往往是围绕订单来...

tanghc
06/20
0
0
JavaWeb20-HTML篇笔记

第20章WEB20-网上商城实战篇 今日任务 Ø 完成购物模块的功能 Ø 完成订单模块的功能 1.1 购物模块的功能:1.1.1 需求: 1.1.2 代码实现:1.1.2.1 封装实体 封装实体: 购物项: 购物车: 调用C...

我是小谷粒
06/07
0
0
基于 YII2 的商城系统--YiiShop

YiiShop开源商城顾名思义是以YII框架为底层框架,并吸收了众多开源商城的优点,经过作者多年的电商经验总结。我的目标致力于为中小企业提供电子商务解决方案,让他们顺利走上电商之路。 浏览...

路边拾草人
2015/04/08
13.1K
3
淘淘商城系列——利用拦截器实现登录功能及订单确认页面展示

我们上文一起搭建了订单的服务工程和web工程。我们参考京东可以知道,京东在没有登录时就可以使用购物车,但是当要真正付款的时候,一定是要求登录的,也就是说由购物车列表页面直接跳转到登...

yerenyuan_pku
2017/06/17
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

JVM学习手册(一):查看堆内存使用情况以及排错

平时出现内存溢出以及死锁,一般处理方式都是查看日志,找到抛出异常的代码行,然后本地分析代码,但是这样对于线上排查十分糟糕,这段时间在研究JVM发现了几个比较好的工具和指令. 1.针对频繁GC和...

勤奋的蚂蚁
刚刚
0
0
Java IO类库之ObjectInputStream和ObjectOutPutStream

一、ObjectOutputStream 1 - ObjectOuputStream介绍 ObjectOutputStream(对象字节输出流),用于将一个序列化对象写入到创建ObjectOutputStream时传入的底层字节输入流中,通过源码可知该类继...

老韭菜
13分钟前
0
0
17.TCP:传输控制协议

介绍 TCP和UDP使用同一网络层(IP),但TCP提供了面向连接、可靠的传输层服务 TCP传输给IP层的信息单位称为报文段或段 TCP通过如下方式保证可靠性: 应用数据被分割成TCP认为最合适发送的数据...

loda0128
22分钟前
0
0
重装Oracle时出现environment variable "PATH"错误的解决办法

在win7 64位下重新安装oracle 11g,一直报environment variable "PATH"的错误,按说明将path里多余的路径删除,但没办法解决。选择忽略错误继续安装,装一半会报CRC错误,还是安装失败。最好...

良言
27分钟前
0
0
TensorFlow 全连接的mnist

全连接的mnist import tensorflow as tf# 导入 MINST 数据集from tensorflow.examples.tutorials.mnist import input_datamnist = input_data.read_data_sets("MNIST_data/", one_ho......

阿豪boy
28分钟前
0
0
JAVA 三种WebService 规范

JAVA 中共有三种WebService 规范,分别是JAX-WS(JAX-RPC)、JAXM&SAAJ、JAX-RS。 1. Jaxws(掌握) JAX-WS 的全称为 Java API for XML-Based Webservices ,早期的基于SOAP 的JAVA 的Web 服务...

onedotdot
46分钟前
0
0
将博客搬至CSDN

将博客搬至CSDN

xpbob
47分钟前
1
0
Aidl进程间通信详细介绍

目录介绍 1.问题答疑 2.Aidl相关属性介绍 2.1 AIDL所支持的数据类型 2.2 服务端和客户端 2.3 AIDL的基本概念 3.实际开发中案例操作 3.1 aidl通信业务需求 3.2 操作步骤伪代码 3.3 服务端操作...

潇湘剑雨
今天
0
0
python爬虫日志(3)下载图片

import urlliburl='https://xxx.jpg'#图片地址res=urllib.request.urlopen(url)#此函数用于对url的访问data=res.read() #字节流with open(r'D:\1.jpg',"wb") as code: c...

茫羽行
今天
0
0
vue中$emit的用法

1、父组件可以使用 props 把数据传给子组件。 2、子组件可以使用 $emit 触发父组件的自定义事件。 vm.$emit( event, arg ) //触发当前实例上的事件 vm.$on( event, fn );//监听event事件后运...

JamesView
今天
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部