跳轉到

訂單系統

訂單中所包含的訊息

以一個通用 B2C 商城的訂單為例,梳理其包含的資訊如下:

img

為了使訂單系統能夠對訂單進行高效、精準的管理和跟踪,訂單會儲存關於產品、優惠、用戶、支付信息等一系列的訂單實時數據,來和下游系統,如:促銷、倉儲、物流進行交互。

這裡要注意的是訂單類型,隨著平台業務的不斷發展,品類豐富、交易方式豐富後,需要對訂單進行多維度的分類管理,同時訂單類型利於訂單系統的擴展性。每種訂單類型將會對應一套流程及一套狀態,以便於將訂單分類管理與重複使用。

流程引擎

流程是指從平台角度出發,將訂單從創建到完成的整個流程進行抽象,從而行程了一套標準流程規則。而不同的產品類型或交易類型在系統中的流程會千差萬別,因此為了方便對訂單流程進行管理,會組成流程引擎模組。

每套訂單流程中會包含正向流程及逆向流程,正向流程可以比喻為一次順利的網購體驗過程中,後台系統之間的資訊流轉。逆向流程則是修改訂單、取消訂單、退款、退貨等各種動作引起的後台系統流程,同時每個流程觸發的條件又可分為系統觸發和人工觸發兩種場景。

正向流程

以一個通用 B2C 商城的訂單系統為例,根據其實際業務場景,其訂單流程可抽象化為 5 大步驟:訂單創建>訂單支付>訂單生產>訂單確認>訂單完成

而每個步驟的背後,訂單是如何在多系統之間互動流轉的,可概括如下圖:

img

訂單創建

用戶下單後,系統需要產生訂單,此時需要先獲取下單中涉及的商品信息,然後獲取該商品所涉及到的優惠信息,如果商品不參與優惠信息,則無此環節。

接著取得該帳戶的會員權益,這裡要注意的是:優惠資訊與會員權益的區別,例如:商品滿減是優惠訊息,SUPER 會員全場 9.8 折指的是會員權益,一個是針對商品,另一個是針對帳戶。其次就是優惠活動的疊加規則和優先規則等。另外,搜尋公眾號程式設計技術圈後台回覆“Java”,取得一份驚喜禮包。

增減庫存規則是指訂單中的商品,何時從倉儲系統對相應商品庫存進行扣除,目前主流有兩種方式:

下單減庫存-即用戶下單成功時減少庫存數量

  • 優點:使用者體驗友好,系統邏輯簡潔;
  • 缺點:會導致惡意下單或下單後不買,使得真正有需求的用戶無法購買,影響真實銷售。

解決辦法:

  1. 設定訂單有效時間,若訂單創建成功 N 分鐘不付款,則訂單取消,庫存回滾;
  2. 限購,用各種條件限制買家的購買件數,例如一個帳號、一個 ip,只能買一件;
  3. 風控,從技術角度進行判斷,屏蔽惡意帳號,禁止惡意帳號購買。

付款減庫存-即用戶支付完成並回饋給平台後再減少庫存數量

  • 優點:減少無效訂單帶來的資源損耗;
  • 缺點:因第三方支付返回結果有時差,同一時間多個用戶同時付款成功,會導致下單數目超過庫存,商家庫存不足容易引發斷貨和投訴,成本增加。

解決辦法:

  1. 付款前再次校驗庫存,如確認訂單要付款時再驗證一次,並友好提示用戶庫存不足;
  2. 增加提示資訊:在商品詳情頁,訂單步驟頁面提示不及時付款,不能保證有庫存等。

綜上所述,兩種方式各有優缺點,因此,需結合實際場景進行考慮,如:秒殺、搶購、促銷活動等,可使用下單減庫存的方式。而對於產品庫存量大,並發流量沒有那麼強的產品使用付款減去庫存的方式。

將兩種方式帶入銷售場景中,關聯商品類型、促銷類型、供需關係等,靈活使用,以充分發揮電腦系統的優勢。

訂單支付

用戶支付訂單後,需要取得訂單的付款訊息,包括支付流水號、支付時間等。支付完訂單接著就是等商家出貨,但在出貨過程中,依照平台業務模式的不同,可能會涉及到訂單的分割。

訂單拆分一般分兩種:

  • 一種是用戶挑選的商品來自於不同管道(自營與商家,商家與商家);
  • 另一種是在 SKU 層面上拆分訂單:不同倉庫,不同運輸要求的 SKU,包裹重量體積限制等因素需要將訂單拆分。

訂單拆分也是一個相對獨立的模組,這裡就不詳細描述了。

訂單生產

指產品從企業到使用者此流程的概述。如電商平台中,商家出貨過程已有一個標準化的流程,訂單內容會送到倉庫,倉庫對商品進行打單、揀貨、包裝、交接快遞進行配送。

訂單確認

收到貨後,訂單系統需要在快遞被簽收後提醒用戶對商品做評價。這裡要注意,確認收到貨不代表交易成功,相反是售後服務的開始。

訂單完成

指在收到貨 X 天的狀態,此時訂單不在售後的支援時間範圍內。到此,一個訂單的正向流程就算走完了。

逆向流程

img

上面說到逆向流程是各種修改訂單、取消訂單、退款、退貨等操作,需要梳理清楚這些流程與正向流程的關係,才能理清訂單系統完整的訂單流程。

訂單修改

可整理訂單內訊息,根據資訊關聯程度及業務訴求,設定訂單的可修改範圍是什麼,例如:客戶下單後,想修改收貨人地址及電話。此時只需對對應資料進行更新即可。

訂單取消

用戶提交訂單後沒有進行支付操作,此時用戶原則上屬於取消訂單,因為還未付款,則比較簡單,只需要將原本提交訂單時扣減的庫存補回,促銷優惠中使用的優惠券,權益等視平台規則,進行相應補回。

退款

用戶支付成功後,客戶發出退款的訴求後,需商家進行退款審核,雙方達成協議後,系統應以退款單的形式完成退款,並關聯原訂單資料。因商品無變化,所以不考慮與庫存系統的交互,僅需考慮促銷系統及支付系統交互即可。

退貨

用戶支付成功後,客戶發出退貨的訴求後,需商家進行退款審核,雙方達成協議後,需對庫存系統進行補回,支付系統、促銷系統以退款單形式完成退款。最後,在退款/退貨流程中,需結合平台業 ​​ 務場景,考慮優惠分攤的邏輯,在發生退款/退貨時,優惠該如何退回的處理規則和流程。

狀態機

狀態機是管理訂單狀態邏輯的工具。狀態機可歸納為 3 個要素,即現態、動作、次態。

  1. 現態: 是指目前所處的狀態。
  2. 動作: 動作執行完畢後,可以遷移到新的狀態,也可以仍舊保持原狀態。
  3. 次態: 動作滿足後要遷往的新狀態,「次態」是相對於「現態」而言的,「次態」一旦被激活,就轉變成新的「現態」了。

狀態機的設計需要結合平台實際業務場景,將狀態間的切換細化成了執行了某個動作。

以一個 B2C 商城的訂單系統舉例如下:

img

訂單系統為了有效率的對訂單進行追蹤與管理,會對訂單流程當中的關鍵節點,抽像出訂單狀態。而訂單狀態從不同使用者的角度可分為,系統訂單狀態、商家訂單狀態、買家訂單狀態等。

對於訂單系統來說,訂單狀態細分的顆粒度越細、越明確,訂單系統管理的精度和可靠性就越高,例如:在待付款和待發貨兩個狀態中,訂單系統後台會細分為訂單逾時取消、訂單付款失敗、訂單付款完成等。

因此,在訂單狀態模組中,通常會維護狀態映射表,以不同的使用者角色對系統訂單狀態進行重新劃分,以滿足不同使用者的需求。

除此之外,隨著電商平台的不斷發展,不同的業務類型,所對應的訂單狀態都會有所區別。所以,訂單系統中一般會儲存多套狀態機,以滿足不同的訂單類型來使用。

如何防止訂單資料被竄改?

購買一個商品需要幾步

電商業務場景中,使用者下單流程是核心中的核心,使用者下單流程的設計不光影響了使用者的購買體驗,也極大的影響系統可擴展能力。下單內容比較多,今天重點聊一下,為什麼先預覽再提單,在此之前先熟悉下用戶網購的操作流程。

把大象放進冰箱需要 3 步,網購一個大象則需要 6 步。

步驟 系統做了什麼?
1. 瀏覽商品清單頁面找到心儀的大象 Feeds 流,推薦系統依照你的喜好推薦大象
2. 點選進入大象詳情頁 查詢商品中心,獲取大象的詳細信息
3. 點擊去結算(去購買) App 呼叫預覽接口,產生購買詳情、可用優惠
4. 商品預覽頁點選選擇收貨地址、優惠券 用戶端記錄訂單資訊
5. 點擊去支付 觸發系統提單行為,真正創建訂單,鎖定優惠、扣庫存、15 分鐘支付超時 Timer
6. 支付輸密碼 進入收銀台頁面,選擇可用付款管道

點擊去購買,不要真的產生訂單數據

我舉一個反面例子,前東家的訂單系統踩了坑。用戶點擊去購買居然真的提交了訂單,產生了訂單資料。

而在提單頁用戶可以修改訂單上的優惠信息,收貨地址等。用戶下單前可能反覆比較價格,反覆衡量糾結…,在提單頁和商品詳情頁、購物車之間反覆切換,這導致了大量的提單動作,用戶修改地址、選擇優惠等行為也導致系統需要頻繁修改訂單數據,系統產生了很多無效訂單。

為了減少用戶在訂單清單上看到很多無效訂單,就要取消上一筆訂單,用戶的切換行為給系統帶來了非常大的效能壓力。所幸的是公司小,訂單量不高。

不得不說,這真的是一個糟糕設計。我們日常溝通時也鬧出很多誤會。

關於提單,大家的理解就有不同,有的人認為去購買的行為就是提單,因為點完去購買真的產生了訂單數據。

但是有的人不那麼認為。由於在產生訂單資料後,才選擇優惠券等行為,點擊去支付,才真正鎖定優惠券,負責行銷的同事就認為用戶點擊去支付才是提單。因為這個動作真正選取地址、鎖定優惠,這個介面包括提單的主要校驗邏輯、鎖定優惠、扣減庫存等邏輯。這才是提單。

各有各的道理,每次聊到提單,都要額外確認下,「你說的提單是哪個提單」。溝通成本太高了。

踩坑的原因我也有所了解,是公司第一代程式設計師對訂單的理解淺嚐輒止,不夠透徹,調查不充分。看到京東、淘寶、美團等公司人家有去購買,去支付等操作流程,就真的以為去購買就是提單,就要產生訂單資料?實際大錯特錯。

訂單的提單介面一定要在用戶選中優惠、選中地址等資訊後,訂單的商品資訊、優惠資訊、收貨地址等板上釘釘以後,才能調用訂單接口鎖定資源(優惠券、庫存),才能真正產生訂單數據。

用戶在提單頁或訂單預覽頁可選擇優惠、選擇地址。確定後,用戶點擊去支付,系統提交訂單,喚起收銀台。這才是正確的互動流程。

用戶進入預覽頁不產生訂單數據可以減少很多無效訂單數據。

如何防止重複提單

防止使用者重複提單,前端可透過防 ​​ 手震、置灰等操作有效避免使用者高頻率點擊提單按鈕所導致的重複提單。此外服務端也要透過系統設計,避免使用者重複提單。

用戶在極短時間內提交訂單,勢必訂單資訊是相同的。例如同一個商品,購買數量相同等,在短時間內提交,被視為重複提交,可以阻斷提單。

Note

使用購買資訊產生唯一鍵防重複提單

例如使用 userId+商品 Id+購買數量,作為 Redis Key,提單時嘗試使用set key1 value1 nx ex 10"加鎖"。這個方案和分散式鎖類似,提單瞬間先嘗試加鎖,加不上鎖,則表示重複提單。不同的是,分散式鎖是被釋放的,此處的鎖,可以不用釋放,只需要配置逾時時間即可。例如用戶 5s 內對同一個商品購買被視為重複提單,那麼超時時間配置 5s 即可。

Reference