购物车与商城订单的关系以及技术实现深入分析
购物车与商城订单的关系以及技术实现深入分析
技术小树懒 发表于1年前
购物车与商城订单的关系以及技术实现深入分析
  • 发表于 1年前
  • 阅读 287
  • 收藏 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
×
技术小树懒
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: