電商系統設計之訂單

timg?image&quality=80&size=b9999_10000&sec=1532631649974&di=1d2a5259543900a105826e512fb6e8a3&imgtype=0&src=http%3A%2F%2Fpic.cifnews.com%2Fupload%2F201503%2F23%2F201503230925232295.jpg

前言

用戶交易將經歷一段艱辛的歷程,通常用戶感受不到,實際程序是經歷了一段生死離別。具體付款流程以下mysql

clipboard.png

不(wo)是(gu)這(yi)張(chuan)圖(de),請看正經流程圖web

clipboard.png

以前的幾篇文章介紹了算法

  • 購物車如何設計
  • 用戶系統如何設計
  • 商品系統如何設計

其實他們都在爲交易系統作鋪墊,一個產品若是沒有收入,那這隻能是寺廟的公益產品。任何產品最終都要走向這步 (收錢)。sql

付款

用戶付款過程當中有不少場景也會出現意外,如下是我碰到的「天災人禍」數據庫

成功

  • 用戶發起微信支付併成功支付
  • 用戶發起支付寶支付併成功支付
  • 用戶發起銀聯支付併成功支付
  • 用戶發起其餘支付併成功支付

人禍

  • 用戶發起微信支付但取消支付
  • 用戶發起支付寶支付但取消支付
  • 用戶發起銀聯支付但取消支付
  • 用戶發起其餘支付但取消支付

天災

  • 用戶發起微信支付「手機爆炸了」
  • 用戶發起支付寶支付「瞬間沒網了」
  • 用戶發起銀聯支付「老婆來電話了」
  • 用戶發起其餘支付「老闆進來了」

註釋

遇到以上的狀況,不要懼怕、不要驚慌,而且不要「理會」,你只須要將這些操做記錄下來便可。
正常咱們都會將用戶經過哪一種支付方式存儲到訂單表中,方便查詢。我想說這種作法沒錯,可是少了點什麼,你應該有一張交易記錄表,來記錄用戶發起了多少次支付,只有支付成功的時候方可記錄到訂單表中。這樣作的優勢有如下兩點express

  • 訂單表是比較重要的,無可奈何儘可能不要操做這張表,防止出現意外,訂單表除了收貨發貨外通常沒有其餘須要操做的地方。
  • 能夠記錄每次用戶發起支付的時間,經過所謂大數據分析用戶對產品的需求度和承認度,若是用戶屢次發起付款但取消支付,那就說明(他沒錢)他可能很指望獲得,可是由於某種緣由一直在猶豫,這個時候能夠針對當前用戶作優惠處理,例如發一張優惠券等等。

clipboard.png

表結構

交易表

CREATE TABLE `transaction` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `order_sn` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '交易單號',
  `member_id` bigint(20) NOT NULL COMMENT '交易的用戶ID',
  `amount` decimal(8,2) NOT NULL COMMENT '交易金額',
  `integral` int(11) NOT NULL DEFAULT '0' COMMENT '使用的積分',
  `pay_state` tinyint(4) NOT NULL COMMENT '支付類型 0:餘額 1:微信 2:支付寶 3:xxx',
  `source` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '支付來源 wx app web wap',
  `status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '支付狀態 -1:取消 0 未完成 1已完成 -2:異常',
  `completion_time` int(11) NOT NULL COMMENT '交易完成時間',
  `note` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '備註',
  `created_at` timestamp NULL DEFAULT NULL,
  `updated_at` timestamp NULL DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `transaction_order_sn_member_id_pay_state_source_status_index` (`order_sn`(191),`member_id`,`pay_state`,`source`(191),`status`)
) ENGINE=InnoDB AUTO_INCREMENT=36 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

支付記錄表

CREATE TABLE `transaction_record` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `order_sn` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
  `events` text COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '事件詳情',
  `result` text COLLATE utf8mb4_unicode_ci COMMENT '結果詳情',
  `created_at` timestamp NULL DEFAULT NULL,
  `updated_at` timestamp NULL DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=36 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

這個記錄表可能讓你匪夷所思,不知你對日誌有什麼概念,但我能說的就是,將用戶的全部動做所有記錄下來。這是很重要的,遲早你會懂。api

訂單表

CREATE TABLE `order` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `order_no` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '訂單編號',
  `order_sn` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '交易號',
  `member_id` int(11) NOT NULL COMMENT '客戶編號',
  `supplier_id` int(11) NOT NULL COMMENT '商戶編碼',
  `supplier_name` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '商戶名稱',
  `order_status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '訂單狀態 0未付款,1已付款,2已發貨,3已簽收,-1退貨申請,-2退貨中,-3已退貨,-4取消交易',
  `after_status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '用戶售後狀態 0 未發起售後 1 申請售後 -1 售後已取消 2 處理中 200 處理完畢',
  `product_count` int(11) NOT NULL DEFAULT '0' COMMENT '商品數量',
  `product_amount_total` decimal(12,4) NOT NULL COMMENT '商品總價',
  `order_amount_total` decimal(12,4) NOT NULL DEFAULT '0.0000' COMMENT '實際付款金額',
  `logistics_fee` decimal(12,4) NOT NULL COMMENT '運費金額',
  `address_id` int(11) NOT NULL COMMENT '收貨地址編碼',
  `pay_channel` tinyint(4) NOT NULL DEFAULT '0' COMMENT '支付渠道 0餘額 1微信 2支付寶',
  `out_trade_no` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '訂單支付單號',
  `escrow_trade_no` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '第三方支付流水號',
  `pay_time` int(11) NOT NULL DEFAULT '0' COMMENT '付款時間',
  `delivery_time` int(11) NOT NULL DEFAULT '0' COMMENT '發貨時間',
  `order_settlement_status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '訂單結算狀態 0未結算 1已結算',
  `order_settlement_time` int(11) NOT NULL DEFAULT '0' COMMENT '訂單結算時間',
  `is_package` enum('0','1') COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '0' COMMENT '是不是套餐',
  `is_integral` enum('0','1') COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '0' COMMENT '是不是積分產品',
  `created_at` timestamp NULL DEFAULT NULL,
  `updated_at` timestamp NULL DEFAULT NULL,
  `deleted_at` timestamp NULL DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `order_order_sn_unique` (`order_sn`),
  KEY `order_order_sn_member_id_order_status_out_trade_no_index` (`order_sn`,`member_id`,`order_status`,`out_trade_no`(191))
) ENGINE=InnoDB AUTO_INCREMENT=44 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

運輸

用戶付款結束後接下來就是快遞公司的事了,固然我們不搭理送快遞的。到這一步咱們就應該給客戶展現運輸信息。如今一些api開放平臺都有快遞查詢的服務,有收費有免費的,性能方面差別也不大。但這裏要注意一點。不是每次用戶都會查詢到新的信息。對於小公司來講,這樣成本極高。因此咱們應該定時去查詢快遞物流信息。這個地方有個簡單的算法。微信

if(用戶點擊查看了){
    從用戶點擊查看兩小時後更新物流信息 // 這裏是按照兩小時來更新的,也能夠拉長這個時間
}else{
    每兩小時更新一次物流信息
}

這種頻繁的更新絕對要使用nosql,當用戶確認收貨後再存儲到mysql等數據庫中。app

收貨

當用戶收到貨後,這實際上是最難伺候的時候,用戶對產品的各類不滿意就可能致使退換貨,收貨操做既改變訂單狀態爲已收貨,複雜點的可能還須要im,短信,推送提醒下。通常都直接提醒,量大的話加入隊列內處理。nosql

退換貨

退換貨淘寶是這樣處理的。
淘寶將訂單分兩種狀態

  • 未付款、已付款、已收貨、已評價
  • 發起售後、售後審覈、售後處理、處理完成

clipboard.png

圖1展現了每一個商品,包括子商品均可以單獨發起售後

clipboard.png

圖2是點擊申請售後以後的頁面

clipboard.png

圖3是選擇退換貨的相關事項

當完成這些步驟後,就會開啓售後審覈,賣家審覈成功後方可進行下一步操做

售後申請表

CREATE TABLE `order_returns_apply` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `order_no` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '訂單單號',
  `order_detail_id` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '子訂單編碼',
  `return_no` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '售後單號',
  `member_id` int(11) NOT NULL COMMENT '用戶編碼',
  `state` tinyint(4) NOT NULL COMMENT '類型 0 僅退款 1退貨退款',
  `product_status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '貨物狀態 0:已收到貨 1:未收到貨',
  `why` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '退換貨緣由',
  `status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '審覈狀態 -1 拒絕 0 未審覈 1審覈經過',
  `audit_time` int(11) NOT NULL DEFAULT '0' COMMENT '審覈時間',
  `audit_why` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '審覈緣由',
  `note` text COLLATE utf8mb4_unicode_ci COMMENT '備註',
  `created_at` timestamp NULL DEFAULT NULL,
  `updated_at` timestamp NULL DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

售後表

CREATE TABLE `order_returns` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `returns_no` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '退貨編號 供客戶查詢',
  `order_id` int(11) NOT NULL COMMENT '訂單編號',
  `express_no` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '物流單號',
  `consignee_realname` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '收貨人姓名',
  `consignee_telphone` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '聯繫電話',
  `consignee_telphone2` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '備用聯繫電話',
  `consignee_address` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '收貨地址',
  `consignee_zip` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '郵政編碼',
  `logistics_type` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '物流方式',
  `logistics_fee` decimal(12,2) NOT NULL COMMENT '物流發貨運費',
  `order_logistics_status` int(11) DEFAULT NULL COMMENT '物流狀態',
  `logistics_settlement_status` int(11) DEFAULT NULL COMMENT '物流結算狀態',
  `logistics_result_last` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '物流最後狀態描述',
  `logistics_result` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '物流描述',
  `logistics_create_time` int(11) DEFAULT NULL COMMENT '發貨時間',
  `logistics_update_time` int(11) DEFAULT NULL COMMENT '物流更新時間',
  `logistics_settlement_time` int(11) DEFAULT NULL COMMENT '物流結算時間',
  `returns_type` tinyint(4) NOT NULL DEFAULT '0' COMMENT '0所有退單 1部分退單',
  `handling_way` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT 'PUPAWAY:退貨入庫;REDELIVERY:從新發貨;RECLAIM-REDELIVERY:不要求歸還並從新發貨; REFUND:退款; COMPENSATION:不退貨並賠償',
  `returns_amount` decimal(8,2) NOT NULL COMMENT '退款金額',
  `return_submit_time` int(11) NOT NULL COMMENT '退貨申請時間',
  `handling_time` int(11) NOT NULL COMMENT '退貨處理時間',
  `remark` text COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '退貨緣由',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

評價

若是用戶收貨後直接評價了,那恭喜你,這筆訂單基本成交了。這個沒什麼可講的,通常小的電商也沒有刷評價的,相似淘寶的防止刷評價的作法太過於複雜,這裏也不過多講解(其實我也沒接觸過)。

評價數據表

CREATE TABLE `order_appraise` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `order_id` int(11) NOT NULL COMMENT '訂單編碼',
  `info` text COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '評論內容',
  `level` enum('-1','0','1') COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '級別 -1差評 0中評 1好評',
  `desc_star` tinyint(4) NOT NULL COMMENT '描述相符 1-5',
  `logistics_star` tinyint(4) NOT NULL COMMENT '物流服務 1-5',
  `attitude_star` tinyint(4) NOT NULL COMMENT '服務態度 1-5',
  `created_at` timestamp NULL DEFAULT NULL,
  `updated_at` timestamp NULL DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `order_appraise_order_id_index` (`order_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

致謝

感謝你看到這裏,但願個人文章和代碼能夠幫助到你。若是有什麼疑問能夠在評論區留言,謝謝

相關文章
相關標籤/搜索