电商系统设计之订单
1. 前言
用戶交易將經(jīng)歷一段艱辛的歷程,一般用戶感覺不到,實(shí)際程序是經(jīng)歷了一段生死離別。具體付款流程如下
不(wo)是(gu)這(yi)張(chuan)圖(de),請(qǐng)看正經(jīng)流程圖
之前的幾篇文章介紹了
- 購物車如何設(shè)計(jì)
- 用戶系統(tǒng)如何設(shè)計(jì)
- 商品系統(tǒng)如何設(shè)計(jì)
其實(shí)他們都在為交易系統(tǒng)做鋪墊,一個(gè)產(chǎn)品如果沒有收入,那這只能是寺廟的公益產(chǎn)品。任何產(chǎn)品最終都要走向這步 (收錢)。
?
2. 付款
用戶付款過程中有很多場景也會(huì)出現(xiàn)意外,以下是我碰到的“天災(zāi)人禍”
2.1 成功
- 用戶發(fā)起微信支付并成功支付
- 用戶發(fā)起支付寶支付并成功支付
- 用戶發(fā)起銀聯(lián)支付并成功支付
- 用戶發(fā)起其他支付并成功支付
2.2 人禍
- 用戶發(fā)起微信支付但取消支付
- 用戶發(fā)起支付寶支付但取消支付
- 用戶發(fā)起銀聯(lián)支付但取消支付
- 用戶發(fā)起其他支付但取消支付
2.3 天災(zāi)
- 用戶發(fā)起微信支付“手機(jī)爆炸了”
- 用戶發(fā)起支付寶支付“瞬間沒網(wǎng)了”
- 用戶發(fā)起銀聯(lián)支付“老婆來電話了”
- 用戶發(fā)起其他支付“老板進(jìn)來了”
2.4 注釋
遇到以上的情況,不要害怕、不要驚慌,并且不要“理會(huì)”,你只需要將這些操作記錄下來即可。 正常我們都會(huì)將用戶通過哪種支付方式存儲(chǔ)到訂單表中,方便查詢。我想說這種做法沒錯(cuò),但是少了點(diǎn)什么,你應(yīng)該有一張交易記錄表,來記錄用戶發(fā)起了多少次支付,只有支付成功的時(shí)候方可記錄到訂單表中。這樣做的優(yōu)點(diǎn)有以下兩點(diǎn)
- 訂單表是比較重要的,迫不得已盡量不要操作這張表,防止出現(xiàn)意外,訂單表除了收貨發(fā)貨外一般沒有其他需要操作的地方。
- 可以記錄每次用戶發(fā)起支付的時(shí)間,通過所謂大數(shù)據(jù)分析用戶對(duì)產(chǎn)品的需求度和認(rèn)可度,如果用戶多次發(fā)起付款但取消支付,那就說明(他沒錢)他可能很期望得到,但是因?yàn)槟撤N原因一直在猶豫,這個(gè)時(shí)候可以針對(duì)當(dāng)前用戶做優(yōu)惠處理,例如發(fā)一張優(yōu)惠券等等。
2.5 表結(jié)構(gòu)
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?'交易單號(hào)',`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?'支付狀態(tài)?-1:取消?0?未完成?1已完成?-2:異常',`completion_time`?int(11)?NOT?NULL?COMMENT?'交易完成時(shí)間',`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?'結(jié)果詳情',`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;這個(gè)記錄表可能讓你匪夷所思,不知你對(duì)日志有什么概念,但我能說的就是,將用戶的所有動(dòng)作全部記錄下來。這是很重要的,早晚你會(huì)懂。
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?'訂單編號(hào)',`order_sn`?varchar(100)?COLLATE?utf8mb4_unicode_ci?NOT?NULL?COMMENT?'交易號(hào)',`member_id`?int(11)?NOT?NULL?COMMENT?'客戶編號(hào)',`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?'訂單狀態(tài)?0未付款,1已付款,2已發(fā)貨,3已簽收,-1退貨申請(qǐng),-2退貨中,-3已退貨,-4取消交易',`after_status`?tinyint(4)?NOT?NULL?DEFAULT?'0'?COMMENT?'用戶售后狀態(tài)?0?未發(fā)起售后?1?申請(qǐng)售后?-1?售后已取消?2?處理中?200?處理完畢',`product_count`?int(11)?NOT?NULL?DEFAULT?'0'?COMMENT?'商品數(shù)量',`product_amount_total`?decimal(12,4)?NOT?NULL?COMMENT?'商品總價(jià)',`order_amount_total`?decimal(12,4)?NOT?NULL?DEFAULT?'0.0000'?COMMENT?'實(shí)際付款金額',`logistics_fee`?decimal(12,4)?NOT?NULL?COMMENT?'運(yùn)費(fèi)金額',`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?'訂單支付單號(hào)',`escrow_trade_no`?varchar(255)?COLLATE?utf8mb4_unicode_ci?DEFAULT?NULL?COMMENT?'第三方支付流水號(hào)',`pay_time`?int(11)?NOT?NULL?DEFAULT?'0'?COMMENT?'付款時(shí)間',`delivery_time`?int(11)?NOT?NULL?DEFAULT?'0'?COMMENT?'發(fā)貨時(shí)間',`order_settlement_status`?tinyint(4)?NOT?NULL?DEFAULT?'0'?COMMENT?'訂單結(jié)算狀態(tài)?0未結(jié)算?1已結(jié)算',`order_settlement_time`?int(11)?NOT?NULL?DEFAULT?'0'?COMMENT?'訂單結(jié)算時(shí)間',`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?'是否是積分產(chǎn)品',`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. 運(yùn)輸
用戶付款結(jié)束后接下來就是快遞公司的事了,當(dāng)然咱們不搭理送快遞的。到這一步我們就應(yīng)該給客戶展示運(yùn)輸信息。現(xiàn)在一些api開放平臺(tái)都有快遞查詢的服務(wù),有收費(fèi)有免費(fèi)的,性能方面差異也不大。但這里要注意一點(diǎn)。不是每次用戶都會(huì)查詢到新的信息。對(duì)于小公司來說,這樣成本極高。所以我們應(yīng)該定時(shí)去查詢快遞物流信息。這個(gè)地方有個(gè)簡單的算法。
if(用戶點(diǎn)擊查看了){從用戶點(diǎn)擊查看兩小時(shí)后更新物流信息?//?這里是按照兩小時(shí)來更新的,也可以拉長這個(gè)時(shí)間 }else{每兩小時(shí)更新一次物流信息 }這種頻繁的更新絕對(duì)要使用nosql,當(dāng)用戶確認(rèn)收貨后再存儲(chǔ)到mysql等數(shù)據(jù)庫中。
?
4. 收貨
當(dāng)用戶收到貨后,這其實(shí)是最難伺候的時(shí)候,用戶對(duì)產(chǎn)品的各種不滿意就可能導(dǎo)致退換貨,收貨操作既改變訂單狀態(tài)為已收貨,復(fù)雜點(diǎn)的可能還需要im,短信,推送提醒下。一般都直接提醒,量大的話加入隊(duì)列內(nèi)處理。
?
5. 退換貨
退換貨淘寶是這樣處理的。 淘寶將訂單分兩種狀態(tài)
- 未付款、已付款、已收貨、已評(píng)價(jià)
- 發(fā)起售后、售后審核、售后處理、處理完成
?
圖2是點(diǎn)擊申請(qǐng)售后之后的頁面?
圖3是選擇退換貨的相關(guān)事項(xiàng)?
當(dāng)完成這些步驟后,就會(huì)開啟售后審核,賣家審核成功后方可進(jìn)行下一步操作
5.1 售后申請(qǐng)表
CREATE?TABLE?`order_returns_apply`?(`id`?int(10)?unsigned?NOT?NULL?AUTO_INCREMENT,`order_no`?varchar(255)?COLLATE?utf8mb4_unicode_ci?NOT?NULL?COMMENT?'訂單單號(hào)',`order_detail_id`?varchar(255)?COLLATE?utf8mb4_unicode_ci?NOT?NULL?COMMENT?'子訂單編碼',`return_no`?varchar(255)?COLLATE?utf8mb4_unicode_ci?NOT?NULL?COMMENT?'售后單號(hào)',`member_id`?int(11)?NOT?NULL?COMMENT?'用戶編碼',`state`?tinyint(4)?NOT?NULL?COMMENT?'類型?0?僅退款?1退貨退款',`product_status`?tinyint(4)?NOT?NULL?DEFAULT?'0'?COMMENT?'貨物狀態(tài)?0:已收到貨?1:未收到貨',`why`?varchar(255)?COLLATE?utf8mb4_unicode_ci?DEFAULT?NULL?COMMENT?'退換貨原因',`status`?tinyint(4)?NOT?NULL?DEFAULT?'0'?COMMENT?'審核狀態(tài)?-1?拒絕?0?未審核?1審核通過',`audit_time`?int(11)?NOT?NULL?DEFAULT?'0'?COMMENT?'審核時(shí)間',`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?'退貨編號(hào)?供客戶查詢',`order_id`?int(11)?NOT?NULL?COMMENT?'訂單編號(hào)',`express_no`?varchar(255)?COLLATE?utf8mb4_unicode_ci?DEFAULT?NULL?COMMENT?'物流單號(hào)',`consignee_realname`?varchar(255)?COLLATE?utf8mb4_unicode_ci?NOT?NULL?COMMENT?'收貨人姓名',`consignee_telphone`?varchar(255)?COLLATE?utf8mb4_unicode_ci?NOT?NULL?COMMENT?'聯(lián)系電話',`consignee_telphone2`?varchar(255)?COLLATE?utf8mb4_unicode_ci?NOT?NULL?COMMENT?'備用聯(lián)系電話',`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?'物流發(fā)貨運(yùn)費(fèi)',`order_logistics_status`?int(11)?DEFAULT?NULL?COMMENT?'物流狀態(tài)',`logistics_settlement_status`?int(11)?DEFAULT?NULL?COMMENT?'物流結(jié)算狀態(tài)',`logistics_result_last`?varchar(255)?COLLATE?utf8mb4_unicode_ci?DEFAULT?NULL?COMMENT?'物流最后狀態(tài)描述',`logistics_result`?varchar(255)?COLLATE?utf8mb4_unicode_ci?DEFAULT?NULL?COMMENT?'物流描述',`logistics_create_time`?int(11)?DEFAULT?NULL?COMMENT?'發(fā)貨時(shí)間',`logistics_update_time`?int(11)?DEFAULT?NULL?COMMENT?'物流更新時(shí)間',`logistics_settlement_time`?int(11)?DEFAULT?NULL?COMMENT?'物流結(jié)算時(shí)間',`returns_type`?tinyint(4)?NOT?NULL?DEFAULT?'0'?COMMENT?'0全部退單?1部分退單',`handling_way`?varchar(255)?COLLATE?utf8mb4_unicode_ci?NOT?NULL?COMMENT?'PUPAWAY:退貨入庫;REDELIVERY:重新發(fā)貨;RECLAIM-REDELIVERY:不要求歸還并重新發(fā)貨;?REFUND:退款;?COMPENSATION:不退貨并賠償',`returns_amount`?decimal(8,2)?NOT?NULL?COMMENT?'退款金額',`return_submit_time`?int(11)?NOT?NULL?COMMENT?'退貨申請(qǐng)時(shí)間',`handling_time`?int(11)?NOT?NULL?COMMENT?'退貨處理時(shí)間',`remark`?text?COLLATE?utf8mb4_unicode_ci?NOT?NULL?COMMENT?'退貨原因',PRIMARY?KEY?(`id`) )?ENGINE=InnoDB?DEFAULT?CHARSET=utf8mb4?COLLATE=utf8mb4_unicode_ci;?
6. 評(píng)價(jià)
如果用戶收貨后直接評(píng)價(jià)了,那恭喜你,這筆訂單基本成交了。這個(gè)沒什么可講的,一般小的電商也沒有刷評(píng)價(jià)的,類似淘寶的防止刷評(píng)價(jià)的做法太過于復(fù)雜,這里也不過多講解(其實(shí)我也沒接觸過)。
6.1 評(píng)價(jià)數(shù)據(jù)表
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?'評(píng)論內(nèi)容',`level`?enum('-1','0','1')?COLLATE?utf8mb4_unicode_ci?NOT?NULL?COMMENT?'級(jí)別?-1差評(píng)?0中評(píng)?1好評(píng)',`desc_star`?tinyint(4)?NOT?NULL?COMMENT?'描述相符?1-5',`logistics_star`?tinyint(4)?NOT?NULL?COMMENT?'物流服務(wù)?1-5',`attitude_star`?tinyint(4)?NOT?NULL?COMMENT?'服務(wù)態(tài)度?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. 致謝
感謝你看到這里,希望我的文章和代碼可以幫助到你。如果有什么疑問可以在評(píng)論區(qū)留言,謝謝
總結(jié)
- 上一篇: 海量数据的分库分表技术演进,最佳实践
- 下一篇: Nginx可以做什么?看完这篇你就懂了