电商系统设计之订单
1. 前言
用戶交易將經歷一段艱辛的歷程,一般用戶感覺不到,實際程序是經歷了一段生死離別。具體付款流程如下
不(wo)是(gu)這(yi)張(chuan)圖(de),請看正經流程圖
之前的幾篇文章介紹了
- 購物車如何設計
- 用戶系統如何設計
- 商品系統如何設計
其實他們都在為交易系統做鋪墊,一個產品如果沒有收入,那這只能是寺廟的公益產品。任何產品最終都要走向這步 (收錢)。
?
2. 付款
用戶付款過程中有很多場景也會出現意外,以下是我碰到的“天災人禍”
2.1 成功
- 用戶發起微信支付并成功支付
- 用戶發起支付寶支付并成功支付
- 用戶發起銀聯支付并成功支付
- 用戶發起其他支付并成功支付
2.2 人禍
- 用戶發起微信支付但取消支付
- 用戶發起支付寶支付但取消支付
- 用戶發起銀聯支付但取消支付
- 用戶發起其他支付但取消支付
2.3 天災
- 用戶發起微信支付“手機爆炸了”
- 用戶發起支付寶支付“瞬間沒網了”
- 用戶發起銀聯支付“老婆來電話了”
- 用戶發起其他支付“老板進來了”
2.4 注釋
遇到以上的情況,不要害怕、不要驚慌,并且不要“理會”,你只需要將這些操作記錄下來即可。 正常我們都會將用戶通過哪種支付方式存儲到訂單表中,方便查詢。我想說這種做法沒錯,但是少了點什么,你應該有一張交易記錄表,來記錄用戶發起了多少次支付,只有支付成功的時候方可記錄到訂單表中。這樣做的優點有以下兩點
- 訂單表是比較重要的,迫不得已盡量不要操作這張表,防止出現意外,訂單表除了收貨發貨外一般沒有其他需要操作的地方。
- 可以記錄每次用戶發起支付的時間,通過所謂大數據分析用戶對產品的需求度和認可度,如果用戶多次發起付款但取消支付,那就說明(他沒錢)他可能很期望得到,但是因為某種原因一直在猶豫,這個時候可以針對當前用戶做優惠處理,例如發一張優惠券等等。
2.5 表結構
2.5.1 交易表
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;2.5.2 支付記錄表
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;這個記錄表可能讓你匪夷所思,不知你對日志有什么概念,但我能說的就是,將用戶的所有動作全部記錄下來。這是很重要的,早晚你會懂。
2.5.3 訂單表
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;?
3. 運輸
用戶付款結束后接下來就是快遞公司的事了,當然咱們不搭理送快遞的。到這一步我們就應該給客戶展示運輸信息。現在一些api開放平臺都有快遞查詢的服務,有收費有免費的,性能方面差異也不大。但這里要注意一點。不是每次用戶都會查詢到新的信息。對于小公司來說,這樣成本極高。所以我們應該定時去查詢快遞物流信息。這個地方有個簡單的算法。
if(用戶點擊查看了){從用戶點擊查看兩小時后更新物流信息?//?這里是按照兩小時來更新的,也可以拉長這個時間 }else{每兩小時更新一次物流信息 }這種頻繁的更新絕對要使用nosql,當用戶確認收貨后再存儲到mysql等數據庫中。
?
4. 收貨
當用戶收到貨后,這其實是最難伺候的時候,用戶對產品的各種不滿意就可能導致退換貨,收貨操作既改變訂單狀態為已收貨,復雜點的可能還需要im,短信,推送提醒下。一般都直接提醒,量大的話加入隊列內處理。
?
5. 退換貨
退換貨淘寶是這樣處理的。 淘寶將訂單分兩種狀態
- 未付款、已付款、已收貨、已評價
- 發起售后、售后審核、售后處理、處理完成
?
圖2是點擊申請售后之后的頁面?
圖3是選擇退換貨的相關事項?
當完成這些步驟后,就會開啟售后審核,賣家審核成功后方可進行下一步操作
5.1 售后申請表
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;5.2 售后表
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;?
6. 評價
如果用戶收貨后直接評價了,那恭喜你,這筆訂單基本成交了。這個沒什么可講的,一般小的電商也沒有刷評價的,類似淘寶的防止刷評價的做法太過于復雜,這里也不過多講解(其實我也沒接觸過)。
6.1 評價數據表
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;?
7. 致謝
感謝你看到這里,希望我的文章和代碼可以幫助到你。如果有什么疑問可以在評論區留言,謝謝
總結
- 上一篇: 海量数据的分库分表技术演进,最佳实践
- 下一篇: Nginx可以做什么?看完这篇你就懂了