订单系统初识

计划将订单系统做一下梳理,包括之前写的IAP支付。其中一些细节,自己描述的也不是特别满意。后续慢慢的完善。

整个订单系统,概括的讲,其实就是创建订单支付订单交付权益这三个过程。但里面涉及的东西,可能必我们想象的要多很多。

订单号

在调用支付时,一般都会要求创建订单号。该订单号是标识本地交易的凭证,必须做到系统唯一。

创建订单号也有很多学问。最差也得做到:首先,不重复;其次,别人不能通过订单号,推测出任何有意义的信息;再次,订单号长度一定要做好控制。

订单再支付

描述一个场景:用户下单之后,并没有立即支付,而是过了一段时间,重新支付之前下的订单。这种情况,如果涉及到扣减库存,还会设置订单的过期时间。

重新支付的时候可能会有点问题:很多支付接口,不允许使用同一个订单号支付两次,即使上一次没有支付成功。换句话说,当你想重新支付时,系统需要生成一个新的订单号。

这样会导致:用户仅仅成功购买了一个商品,后台却生成了数笔订单。后期的统计变得麻烦了不少。

我们的做法便是:在确认支付时,生成两个订单,一个父订单,一个子订单。父订单用来标识用户的购买行为,子订单用户跟第三方支付。

订单统一管理

对于业务简单的部门来说,订单号自己创建,自己管理完全足够了。

但公司想汇总各个部门的订单数据时会变得异常麻烦。所以需要统一的订单创建平台。该平台负责订单的创建、以及后续订单的状态管理。

整个系统也开始变得复杂起来了。订单创建、订单状态更新都需要通知“订单系统”。数据也开始出现不一致。

交付

在用户下单、支付成功之后,将购买的商品或权益给到用户。

实物商品

将用户的购买行为添加到他的购买记录等,让快递员将商品送到用户手中等。

虚拟商品

用户在王者荣耀上买了一套皮肤,这就属于购买虚拟商品。最终腾讯只需要给用户的数据库写一条权益记录就好,不存在发货的过程。

签收

拆单

用户可能一次性购买多个商品,但系统只生成一个订单。对于实物商品,会涉及的拆单流程。比如用户买了肥皂和书,后台系统需要将肥皂交给卖家A来发货,将书交给卖家B来发。同样的商品,可能还会根据卖家和买家的距离来拆单。

签收

那么当更新订单签收状态时,就有疑问了。一个订单,它可能对应多个商品,那么只有商品全部被签收成功,才应该修改为已签收状态。但这种全部成功或者全部失败的状态,本身就很难保证。

所以签收应该针对具体商品。商城系统中,有两个常用的概念:SPUSKU。那小米手机来举例,小米Note可以当作是一个SPU,而具体的红色-32G等能具体到一个实际的个体的就是SKU

最终,签收状态应该是订单号+SKU_ID来决定的。

表结构设计

在用户下单、支付的过程中,跟订单内部商品的SKU关系不大,而且为了保证订单的幂等性,将订单设置为唯一索引是必须的。

在签收的过程中,无法做到针对订单来签收,而应该对订单下的SKU做签收。所以签收表应该独立出来。